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?
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 指针数组以及指向指针的指针
- unix有个程序sort,可以完成一个功能:根据每行字符串的第一个字符,按字典顺序排序。
- 本节试着写了一个例子,简化版的sort。
- 使用 指针数组 可以高效的完成这个功能,如下图所示:
由指针组成的数组,每一个指针指向一行。不用移动文本行,仅仅改变指针的指向,就完成了这个功能 - 移动文本行将带来复杂的储存管理和巨大的开销
- 在比较字符的时候我们使用了strcmp函数。
- 程序的划分:一个问题一个函数,主函数控制其他函数的执行。
- 具体的函数我倒没有觉得有什么难点,不过可以来看看指针数组的初始化,实际上也没什么区别:
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 多维数组
- 类似矩阵的多维数组,使用不如指针数组那么频繁
- char类型在存放较小的非字符整数也是合法的
- 看一下二维数组的赋值,下面的二维数组表示某个月有多少天:
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} };
- 看作矩阵的话:
第一个是行,第二个是列daytab[i][j] /* [row][col] */
- 在二位数组作为参数传递给函数的时候,在函数的声明中必须指名数组的列数,但是多少行可以不写。
第三种写法是因为,二维数组相当于储存了一个指向很多对象的指针,每个对象都是由13个整型元素构成的一维数组。具体说一下,就是一个数组在被调用的时候传递的就是指针。f(int daytab[2][13]) { ... }//可以这样 f(int daytab[][13]) { ... }//可以这样 f(int (*daytab)[13]) { ... }//也可以这样,小心圆括号,改变优先级
int *daytab[13]//[]的优先级高,所以这样表示一个指向整型的数组指针
- 一般多维数组中,第一维可以不指定大小,其余各维都必须明确大小
练习题
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 指针数组的初始化
- 看下面的函数就知道怎么样对指针数组初始化:
/* 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 指针与多维数组
- 看例子来分析,指针数组和多维数组的区别:
a是真正的二维数组,分配了200个的储存空间。b只是分配了10个指针,10个指针可以指向不同的长度数组。int a[10][20]; int *b[10];
- 下图进一步说明了上面的说法:
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 命令行参数
- 也就是跟着main函数的两个参数
- 第一个是argc,用于参数计数
- 第二个是argv,是参数向量,是一个字符串数组的指针,每一个字符串对应一个参数,通常用多级指针处理这些参数
- c语言规定:argv[0],是启动该程序的程序名,故argc至少为1
- unix下面的回显程序:
argc 为 3, argv[0], argv[1], argv[2] 分别为: "echo", "hello,", and "world"echo hello, world
- 我们在unix经常使用:
find -nx pattern
上述这样的语句,含义就是-x和-n能够对这个程序做出一些更具体的要求,这里:-n:打印行号-x:打印所有与模式不匹配的文本行pattern:所谓模式,就是查找某行里有没有某一串字符串,这个某一行字符串就是模式。下面这段代码就是讲述了如何实现这样的效果:find -x -n pattern
#include <stdio.h> #include <string.h> #define MAXLINE 1000 int 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"); else while (getline(line, MAXLINE) > 0) { lineno++; if ((strstr(line, *argv) != NULL) != except) {//如果含有该字会返回1 if (number) //如果except等于1的话 1!=1 会返回0 printf("%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 1024
double 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-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
a
d
c
A
B
A
B
a
c
d
由于是自己花了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 -f
A
B
C
a
b
c
A
a
B
b
C
c
zy@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-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.
Exercise 5-20. Expand dcl to handle declarations with function argument types, qualifiers like const, and so on.
答:
暂时未找到合适的解法。