读书笔记:C程序设计语言,第五章:指针与数组(部分课后题解)

来源:互联网 发布:js防水涂料i型 编辑:程序博客网 时间:2024/05/16 04:40

2月27日终于下决心改变学习策略:

  • 不再总结一些基础的知识
  • 不会把书中的要点记录在博客,而是直接买书(之前都是图书馆借书),直接阅读书籍
  • 博客主要总结难度较大的问题
这是最后一篇基础性的记录博客,但是很不完整,所以只是把题贴下来了,以后完成时会单开一篇博客。

5.2 指针与函数

Exercise 5-1. As written, getint treats a + or - not followed by a digit as a valid representation of zero. Fix it to push such a character back on the input.
答:暂时未找到合适的解法。
Exercise 5-2. Write getfloat, the floating-point analog of getint. What type does getfloat return as its function value?
答:暂时未找到合适的解法。

5.5字符指针和函数

Exercise 5-3. Write a pointer version of the function strcat that we showed in Chapter 2: strcat(s,t) copies the string t to the end of s.
答:暂时未找到合适的解法。

Exercise 5-4. Write the function strend(s,t), which returns 1 if the string t occurs at the end of the string s, and zero otherwise.
答:暂时未找到合适的解法。

Exercise 5-5. Write versions of the library functions strncpy, strncat, and strncmp, which operate on at most the first n characters of their argument strings. For example, strncpy(s,t,n) copies at most n characters of t to s. Full descriptions are in Appendix B.
答:暂时未找到合适的解法。

Exercise 5-6. Rewrite appropriate programs from earlier chapters and exercises with pointers instead of array indexing. Good possibilities include getline (Chapters 1 and 4), atoi, itoa, and their variants (Chapters 2, 3, and 4), reverse (Chapter 3), and strindex and getop (Chapter 4).
答:暂时未找到合适的解法。

5.6 指针数组以及指向指针的指针

  1. unix有个程序sort,可以完成一个功能:根据每行字符串的第一个字符,按字典顺序排序。
  2. 本节试着写了一个例子,简化版的sort。
  3. 使用 指针数组 可以高效的完成这个功能,如下图所示:

    由指针组成的数组,每一个指针指向一行。不用移动文本行,仅仅改变指针的指向,就完成了这个功能
  4. 移动文本行将带来复杂的储存管理和巨大的开销
  5. 在比较字符的时候我们使用了strcmp函数。
  6. 程序的划分:一个问题一个函数,主函数控制其他函数的执行。
  7. 具体的函数我倒没有觉得有什么难点,不过可以来看看指针数组的初始化,实际上也没什么区别:
    char *lineptr[MAXLINES]

练习题

Exercise 5-7. Rewrite readlines to store lines in an array supplied by main, rather than calling alloc to maintain storage. How much faster is the program?答:code:
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <time.h>#define TRUE     1#define FALSE    0#define MAXLINES 5000       /* maximum number of lines */#define MAXLEN   1000       /* maximum length of a line */char *lineptr[MAXLINES];char lines[MAXLINES][MAXLEN];//第一个相当于存入的一行的编号/* K&R2 p29 */int getline(char s[], int lim){  int c, i;  for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; i++)    s[i] = c;  if (c == '\n') {    s[i++] = c;  }  s[i] = '\0';  return i;}/* K&R2 p109 */int readlines(char *lineptr[], int maxlines){  int len, nlines;  char *p, line[MAXLEN];  nlines = 0;  while ((len = getline(line, MAXLEN)) > 0)    if (nlines >= maxlines || (p = malloc(len)) == NULL)//Malloc 向系统申请分配指定size个字节的内存空间      return -1;    else {      line[len - 1] = '\0';  /* delete the newline */      strcpy(p, line);//将读到的行复制到新申请的内存空间中      lineptr[nlines++] = p;    }  return nlines;}int readlines2(char lines[][MAXLEN], int maxlines){  int len, nlines;  nlines = 0;  while ((len = getline(lines[nlines], MAXLEN)) > 0)    if (nlines >= maxlines)      return -1;    else      lines[nlines++][len - 1] = '\0';   return nlines;}int main(int argc, char *argv[]){  /* read things into cache, to be fair. */  readlines2(lines, MAXLINES);  if (argc > 1 && *argv[1] == '2') {    puts("readlines2()");    readlines2(lines, MAXLINES);  } else {    puts("readlines()");    readlines(lineptr, MAXLINES);  }  return 0;}

5.7 多维数组

  1. 类似矩阵的多维数组,使用不如指针数组那么频繁
  2. char类型在存放较小的非字符整数也是合法的
  3. 看一下二维数组的赋值,下面的二维数组表示某个月有多少天:
    static char daytab[2][13] = {{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
  4. 看作矩阵的话:
    daytab[i][j]   /* [row][col] */
    第一个是行,第二个是列
  5. 在二位数组作为参数传递给函数的时候,在函数的声明中必须指名数组的列数,但是多少行可以不写。
    f(int daytab[2][13]) { ... }//可以这样f(int daytab[][13]) { ... }//可以这样f(int (*daytab)[13]) { ... }//也可以这样,小心圆括号,改变优先级
    第三种写法是因为,二维数组相当于储存了一个指向很多对象的指针,每个对象都是由13个整型元素构成的一维数组。具体说一下,就是一个数组在被调用的时候传递的就是指针。
    int *daytab[13]//[]的优先级高,所以这样表示一个指向整型的数组指针
  6. 一般多维数组中,第一维可以不指定大小,其余各维都必须明确大小

练习题

Exercise 5-8. There is no error checking in day_of_year or month_day. Remedy this defect.(进行错误检查。
答:code:
/* * A solution to exercise 5-8 in K&R2, page 112: * *There is no error checking in day_of_year or month_day. Remedy *this defect. * * The error to check for is invalid argument values. That is simple, what's * hard is deciding what to do in case of error. In the real world, I would * use the assert macro from assert.h, but in this solution I take the * approach of returning -1 instead. This is more work for the caller, of * course. * * I have selected the year 1752 as the lowest allowed year, because that * is when Great Britain switched to the Gregorian calendar, and the leap * year validation is valid only for the Gregorian calendar. * * Lars Wirzenius <liw@iki.fi> */#include <stdio.h>static char daytab[2][13] =  {{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},};/* day_of_year: set day of year from month & day */int day_of_year(int year, int month, int day){int i, leap;if (year < 1752 || month < 1 || month > 12 || day < 1)return -1;leap = (year%4 == 0 && year%100 != 0) || year%400 == 0;if (day > daytab[leap][month])return -1;for (i = 1; i < month; i++)day += daytab[leap][i];return day;}/* month_day: set month, day from day of year */int month_day(int year, int yearday, int *pmonth, int *pday){int i, leap;if (year < 1752 || yearday < 1)return -1;leap = (year%4 == 0 && year%100 != 0) || year%400 == 0;if ((leap && yearday > 366) || (!leap && yearday > 365))return -1;for (i = 1; yearday > daytab[leap][i]; i++)yearday -= daytab[leap][i];*pmonth = i;*pday = yearday;return 0;}/* main: test day_of_year and month_day */int main(void){int year, month, day, yearday;for (year = 1970; year <= 2000; ++year) {for (yearday = 1; yearday < 366; ++yearday) {if (month_day(year, yearday, &month, &day) == -1) {printf("month_day failed: %d %d\n",year, yearday);} else if (day_of_year(year, month, day) != yearday) {printf("bad result: %d %d\n", year, yearday);printf("month = %d, day = %d\n", month, day);}}}return 0;}

5.8 指针数组的初始化

  1. 看下面的函数就知道怎么样对指针数组初始化:
    /* month_name: return name of n-th month */char *month_name(int n){static char *name[] = {"Illegal month","January", "February", "March","April", "May", "June","July", "August", "September","October", "November", "December"};return (n < 1 || n > 12) ? name[0] : name[n];}

5.9 指针与多维数组

  1. 看例子来分析,指针数组和多维数组的区别:
    int a[10][20];int *b[10];
    a是真正的二维数组,分配了200个的储存空间。b只是分配了10个指针,10个指针可以指向不同的长度数组。
  2. 下图进一步说明了上面的说法:
    char *name[] = { "Illegal month", "Jan", "Feb", "Mar" };

    char aname[][15] = { "Illegal month", "Jan", "Feb", "Mar" };

练习题

Exercise 5-9. Rewrite the routines day_of_year and month_day with pointers instead of indexing.
答:code:
/* * A solution to exercise 5-9 in K&R2, page 114: * *Rewrite the routines day_of_year and month_day with pointers *instead of indexing. * * Lars Wirzenius <liw@iki.fi> */#include <stdio.h>static char daytab[2][13] =  {{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},};/* original versions, for comparison purposes */int day_of_year(int year, int month, int day){int i, leap;leap = (year%4 == 0 && year%100 != 0) || year%400 == 0;for (i = 1; i < month; i++)day += daytab[leap][i];return day;}void month_day(int year, int yearday, int *pmonth, int *pday){int i, leap;leap = (year%4 == 0 && year%100 != 0) || year%400 == 0;for (i = 1; yearday > daytab[leap][i]; i++)yearday -= daytab[leap][i];*pmonth = i;*pday = yearday;}/* pointer versions */int day_of_year_pointer(int year, int month, int day){int i, leap;char *p;leap = (year%4 == 0 && year%100 != 0) || year%400 == 0;/* Set `p' to point at first month in the correct row. */p = &daytab[leap][1];//指向第一个月/* Move `p' along the row, to each successive month. */for (i = 1; i < month; i++) {day += *p;++p;}return day;}void month_day_pointer(int year, int yearday, int *pmonth, int *pday){int i, leap;char *p;leap = (year%4 == 0 && year%100 != 0) || year%400 == 0;p = &daytab[leap][1];//指向第一个月for (i = 1; yearday > *p; i++) {yearday -= *p;++p;}*pmonth = i;*pday = yearday;}int main(void){int year, month, day, yearday;year = 2000;month = 3;day = 1;printf("The date is: %d-%02d-%02d\n", year, month, day);printf("day_of_year: %d\n", day_of_year(year, month, day));printf("day_of_year_pointer: %d\n",day_of_year_pointer(year, month, day));yearday = 61;/* 2000-03-01 */month_day(year, yearday, &month, &day);printf("Yearday is %d\n", yearday);printf("month_day: %d %d\n", month, day);month_day_pointer(year, yearday, &month, &day);printf("month_day_pointer: %d %d\n", month, day);return 0;}

5.10 命令行参数

  1. 也就是跟着main函数的两个参数
  2. 第一个是argc,用于参数计数
  3. 第二个是argv,是参数向量,是一个字符串数组的指针,每一个字符串对应一个参数,通常用多级指针处理这些参数
  4. c语言规定:argv[0],是启动该程序的程序名,故argc至少为1
  5. unix下面的回显程序:
    echo hello, world
    argc 为 3,  argv[0], argv[1], argv[2] 分别为: "echo", "hello,", and "world"
  6. 我们在unix经常使用:
    find -nx pattern 
    find -x -n pattern
    上述这样的语句,含义就是-x和-n能够对这个程序做出一些更具体的要求,这里:-n:打印行号-x:打印所有与模式不匹配的文本行pattern:所谓模式,就是查找某行里有没有某一串字符串,这个某一行字符串就是模式。下面这段代码就是讲述了如何实现这样的效果:
    #include <stdio.h>#include <string.h>#define MAXLINE 1000int getline(char *line, int max);/* find: print lines that match pattern from 1st arg */main(int argc, char *argv[]){char line[MAXLINE];long lineno = 0;int c, except = 0, number = 0, found = 0;while (--argc > 0 && (*++argv)[0] == '-')//先找到‘-’。另外没有{}的原因是后面直接根了一个while的程序块while (c = *++argv[0])//为什么要加[0]这是因为*argv代表字符串switch (c) {//*argv[0]代表字符串的第一个字符case 'x'://*argv[0]和**argv是等效的except = 1;//稍稍分析就可以看出这段代码既可以应对:-nx 或者 -n -x两种形式break;case 'n':number = 1;break;default:printf("find: illegal option %c\n", c);argc = 0;found = -1;break;}if (argc != 1)printf("Usage: find -x -n pattern\n");elsewhile (getline(line, MAXLINE) > 0) {lineno++;if ((strstr(line, *argv) != NULL) != except) {//如果含有该字会返回1if (number)//如果except等于1的话 1!=1 会返回0printf("%ld:", lineno);//所以就不打印了printf("%s", line);//如果不含有这个字段的分析方式类似found++;}}return found;}

练习题

Exercise 5-10. Write the program expr, which evaluates a reverse Polish expression from the command line, where each operator or operand is a separate argument. For example, expr 2 3 4 + * evaluates 2 * (3+4).答:code:
#include <ctype.h>#include <stdio.h>#include <stdlib.h>#define STACK_SIZE 1024double stack[STACK_SIZE];int stack_height = 0;void panic(const char *msg) {fprintf(stderr, "%s\n", msg);exit(EXIT_FAILURE);}void push(double value) {if (stack_height == STACK_SIZE)panic("stack is too high!");stack[stack_height] = value;++stack_height;}double pop(void) {if (stack_height == 0)panic("stack is empty!");return stack[--stack_height];}int main(int argc, char **argv) {int i;double value;for (i = 1; i < argc; ++i) {switch (argv[i][0]) {case '\0':panic("empty command line argument");break;case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':push(atof(argv[i]));break;case '+':push(pop() + pop());break;case '-':value = pop();push(pop() - value);break;case '*':push(pop() * pop());break;case '/':value = pop();push(pop() / value);break;default:panic("unknown operator");break;}}printf("%g\n", pop());return 0;}

Exercise 5-11. Modify the program entab and detab (written as exercises in Chapter 1) to accept a list of tab stops as arguments Use the default tab settings if there are no arguments.
答:没找到合适的解法。
Exercise 5-12. Extend entab and detab to accept the shorthand entab -m +n to mean tab stops every n columns, starting at column m. Choose convenient (for the user) default behavior.
答:没找到合适的解法。
Exercise 5-13. Write the program tail, which prints the last n lines of its input. By default, n is set to 10, let us say, but it can be changed by an optional argument so that
tail -n
prints the last n lines. The program should behave rationally no matter how unreasonable the input or the value of n. Write the program so it makes the best use of available storage; lines should be stored as in the sorting program of Section 5.6, not in a two-dimensional array of 
fixed size.
答:code:
/* K&R Exercise 5-13 *//* Steven Huang */#include <stdio.h>#include <stdlib.h>#include <string.h>#define DEFAULT_NUM_LINES      10#define MAX_LINE_LEN           1000/*   Points of interest for a novice:   1.  atoi() has a normally annoying property of not being able to       tell the caller conclusively whether the input was bad ("abc")       or it was really zero ("0"), because it returns 0 for both       cases.  Here, we exploit that property, because we only want       to accept options in the form of "-n".   2.  Try to understand how this program deals with input that       doesn't even have as many lines as the line_ptrs[] array.       That is, how does this program degenerate into just displaying       everything it read?  (Hint:  what does it mean when line_ptrs[x]       is NULL?)   3.  Using modulo arithmetic on an index to a circular array is       a common and useful technique.  Try to understand the range       of values that current_line (and j, later) will take.  In       particular, why shouldn't we just do this:       for (i = 0; i < num_lines; i++)         if (line_ptrs[i])           printf("%s", line_ptrs[i]);   4.  Why do we still use a "%s" to display what's inside line_ptrs,       rather than just:       printf(line_ptrs[i]);   5.  There is a bug in this program, where you see:       numlines = -numlines;       When will this break?*//* K&R2 p29 */int getline1(char s[], int lim){  int c, i;  for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; i++)    s[i] = c;  if (c == '\n')    s[i++] = c;  s[i] = '\0';  return i;}/* duplicates a string */char *dupstr(const char *s){  char *p = malloc(strlen(s) + 1);  if (p)    strcpy(p, s);  return p;}int main(int argc, char *argv[]){  int num_lines = DEFAULT_NUM_LINES;  char **line_ptrs;  char buffer[MAX_LINE_LEN];  int i;  unsigned j, current_line;  if (argc > 1) {    /*       We use a little trick here.  The command line parameter should be       in the form of "-n", where n is the number of lines.  We don't       check for the "-", but just pass it to atoi() anyway, and then       check if atoi() returned us a negative number.    */    num_lines = atoi(argv[1]);    if (num_lines >= 0) {      fprintf(stderr, "Expected -n, where n is the number of lines\n");      return EXIT_FAILURE;    }    /* Now make num_lines the positive number it's supposed to be. */    num_lines = -num_lines;  }   /* First, let's get enough storage for a list of n pointers... */  line_ptrs = malloc(sizeof *line_ptrs * num_lines);  if (!line_ptrs) {    fprintf(stderr, "Out of memory.  Sorry.\n");    return EXIT_FAILURE;  }  /* and make them all point to NULL */  for (i = 0; i < num_lines; i++)    line_ptrs[i] = NULL;  /* Now start reading */  current_line = 0;  do {    getline1(buffer, sizeof buffer);    if (!feof(stdin)) {      if (line_ptrs[current_line]) {        /* there's already something here */        free(line_ptrs[current_lidne]);      }      line_ptrs[current_line] = dupstr(buffer);      if (!line_ptrs[current_line]) {        fprintf(stderr, "Out of memory.  Sorry.\n");        return EXIT_FAILURE;      }      current_line = (current_line + 1) % num_lines;    }  } while (!feof(stdin));  /* Finished reading the file, so we are ready to print the lines */  for (i = 0; i < num_lines; i++) {    j = (current_line + i) % num_lines;    if (line_ptrs[j]) {      printf("%s", line_ptrs[j]);      free(line_ptrs[j]);    }  }  return EXIT_SUCCESS;}

5.11 指向函数的指针

练习题

Exercise 5-14. Modify the sort program to handle a -r flag, which indicates sorting in reverse (decreasing) order. Be sure that -r works with -n.
/* K&R Exercise 5-14 *//* 完成者:Steven Huang *//** * 添加注释者:zy * 这段代码调用的qsort居然是库函数stdlib.h里面的 * 于是我顺带分析了一个qsort的几个参数 * 分析结果如下图。 * 此外,虽然在仅仅将函数的名字当作qsort参数传过去就可以了 * 但是书上对这段还有着比较详细的描述,因为书上的qsort函数是自己实现的 *  */#include <stdio.h>#include <string.h>#include <stdlib.h>#define TRUE 1#define FALSE 0#define MAXLINES 5000       /* maximum number of lines */char *lineptr[MAXLINES];#define MAXLEN 1000         /* maximum length of a line */int reverse = FALSE;/* K&R2 p29 */int getline1(char s[], int lim){  int c, i;  for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; i++)    s[i] = c;  if (c == '\n') {    s[i++] = c;  }  s[i] = '\0';  return i;}/* K&R2 p109 */int readlines(char *lineptr[], int maxlines){  int len, nlines;  char *p, line[MAXLEN];  nlines = 0;  while ((len = getline1(line, MAXLEN)) > 0)    if (nlines >= maxlines || (p = malloc(len)) == NULL)      return -1;    else {      line[len - 1] = '\0';  /* delete the newline */      strcpy(p, line);      lineptr[nlines++] = p;    }  return nlines;}/* K&R2 p109 */void writelines(char *lineptr[], int nlines){  int i;  for (i = 0; i < nlines; i++)    printf("%s\n", lineptr[i]);}int pstrcmp(const void *p1, const void *p2){  char * const *s1 = reverse ? p2 : p1;  char * const *s2 = reverse ? p1 : p2;  return strcmp(*s1, *s2);}int numcmp(const void *p1, const void *p2){  char * const *s1 = reverse ? p2 : p1;  char * const *s2 = reverse ? p1 : p2;  double v1, v2;  v1 = atof(*s1);  v2 = atof(*s2);  if (v1 < v2)    return -1;  else if (v1 > v2)    return 1;  else    return 0;}int main(int argc, char *argv[]){  int nlines;  int numeric = FALSE;  int i;  for (i = 1; i < argc; i++) {    if (*argv[i] == '-') {      switch (*(argv[i] + 1)) {        case 'n':  numeric = TRUE;  break;        case 'r':  reverse = TRUE;  break;        default:          fprintf(stderr, "invalid switch '%s'\n", argv[i]);          return EXIT_FAILURE;      }    }  }  if ((nlines = readlines(lineptr, MAXLINES)) >= 0) {    qsort(lineptr, nlines, sizeof(*lineptr), numeric ? numcmp : pstrcmp);//numcmp和pstrcmp就是函数名    writelines(lineptr, nlines);    return EXIT_SUCCESS;  } else {    fputs("input too big to sort\n", stderr);    return EXIT_FAILURE;  }}

调试情况:
打印参数:
Exercise 5-15. Add the option -f to fold upper and lower case together, so that case distinctions are not made during sorting; for example, a and A compare equal.
答:
code:
该题完成前:
zy@zy:~/Documents/eclipseWorkSpace/test/src$ ./a.out adcABABacd
由于是自己花了12个小时写的,倒不是代码有多难,只是指针的使用还比较弱完成后:
/* K&R Exercise 5-15 *//* 完成者:zy * 在Exercise 5-14的基础上修改完成,修改前的作者是:Steven Huang * */#include <stdio.h>#include <string.h>#include <stdlib.h>#define TRUE 1#define FALSE 0#define MAXLINES 5000       /* maximum number of lines */char *lineptr[MAXLINES];#define MAXLEN 1000         /* maximum length of a line */int reverse = FALSE;int ignoreCase = FALSE;//表示是否忽略大小写/* K&R2 p29 */int getline1(char s[], int lim){  int c, i;  for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; i++)    s[i] = c;  if (c == '\n') {    s[i++] = c;  }  s[i] = '\0';  return i;}/* K&R2 p109 */int readlines(char *lineptr[], int maxlines){  int len, nlines;  char *p, line[MAXLEN];  nlines = 0;  while ((len = getline1(line, MAXLEN)) > 0)    if (nlines >= maxlines || (p = malloc(len)) == NULL)      return -1;    else {      line[len - 1] = '\0';  /* delete the newline */      strcpy(p, line);      lineptr[nlines++] = p;    }  return nlines;}/* K&R2 p109 */void writelines(char *lineptr[], int nlines){  int i;  for (i = 0; i < nlines; i++)    printf("%s\n", lineptr[i]);}void swap(void *v[],int i,int j){void *temp;temp=v[i];v[i]=v[j];v[j]=temp;}/** * K&R2 P119 * 不再调用库函数:stdlib.h 里面的qsort * 自己按着书上写一个:写的原因就是因为:当我传入 A B C a b c的时候会传出来:a a b b c c * 不知道为什么库函数里面的qsort会修改了原指针的值(指向) */void myQsort(void *v[],int left,int right,int (*comp)(void *,void *)){int i,last;void swap(void *v[],int,int);if(left>=right)return;swap(v,left,(left+right)/2);last=left;for(i= left+1;i<=right;i++)if((*comp)(v[i],v[left])<0){swap(v,++last,i);}swap(v,left,last);myQsort(v,left,last-1,comp);myQsort(v,left+1,right,comp);}/** * 该函数还可以进一步改进,现在只能对第一个字母实现 不区分大小写的功能 * */int pstrcmp( char *p1,  char *p2)//这里表示传过来的是一个以p1为名的字符数组,请看下图{char  a1 = *p1;//p1:就是一个字符串,可以直接理解为一个字符数组,对其*p1是取其第一个字符char  a2 = *p2;if(ignoreCase){if(a1>64 && a1<91 ){a1+=32;}if(a2>64 && a2<91 ){a2+=32;}}if (a1==a2) return 0;else return a1-a2;}int numcmp( char *p1,  char *p2){  double v1, v2;  v1 = atof(p1);  v2 = atof(p2);  if (v1 < v2)    return -1;  else if (v1 > v2)    return 1;  else    return 0;}int main(int argc, char *argv[]){  int nlines;  int numeric = FALSE;  int i;  for (i = 1; i < argc; i++) {    if (*argv[i] == '-') {      switch (*(argv[i] + 1)) {        case 'n':  numeric = TRUE;  break;        case 'r':  reverse = TRUE;  break;        case 'f':  ignoreCase = TRUE;  break;        default:          fprintf(stderr, "invalid switch '%s'\n", argv[i]);          return EXIT_FAILURE;      }    }  }  if ((nlines = readlines(lineptr, MAXLINES)) >= 0) {    myQsort((void **)lineptr,0, nlines-1, numeric ? numcmp : pstrcmp);//numcmp和pstrcmp就是函数名    writelines(lineptr, nlines);    return EXIT_SUCCESS;  } else {    fputs("input too big to sort\n", stderr);    return EXIT_FAILURE;  }}
运行结果:
zy@zy:~/Documents/eclipseWorkSpace/test/src$ ./a.out -fABCabcAaBbCczy@zy:~/Documents/eclipseWorkSpace/test/src$ 

可以看出声明为一个char *p1就是一个数组的形式,下面直接打印p1的时候看出来,当*p1


Exercise 5-16. Add the -d (‘‘directory order’’) option, which makes comparisons only on letters, numbers and blanks. Make sure it works in conjunction with -f.
答:暂时未找到合适的解法。

5.12 复杂声明

Exercise 5-17. Add a field-searching capability, so sorting may bee done on fields within lines, each field sorted according to an independent set of options. (The index for this book was sorted with -df for the index category and -n for the page numbers.)
答:暂时未找到合适的解法。

Exercise 5-18. Make dcl recover from input errors.
答:
暂时未找到合适的解法。
Exercise 5-19. Modify undcl so that it does not add redundant parentheses to declarations.
答:暂时未找到合适的解法。
Exercise 5-20. Expand dcl to handle declarations with function argument types, qualifiers like const, and so on.
答:暂时未找到合适的解法。





0 0
原创粉丝点击