1.1 入门
学习一门新程序设计语言的唯一途径就是使用它编写程序,我们第一个C语言程序:
#include程序简单的一些说明:一个C语言程序,无论其大小如何,都是由函数和变量组成的。函数中包含一些语句,以指定所要执行的计算操作;变量则用于存储计算过程中使用的值。通常情况下,函数的命名没有限制,但main是一个特殊的函数名---每个程序都从main函数的起点开始执行,这意味着每个程序都必须在某个位置包含一个main函数。main(){ printf("hello world\n");}
用双引号括起来的字符序列称为“字符串”或者“字符串常量”,而“\n”称为转义字符。
习题1-1,习题1-2略过。
1.2 变量与算数表达式
#include1. 用/**/分割起来的是注释,它可以用于简单的用于解释程序,使程序更易阅读。/* 当fahr = 0,20,...,300时,分别打印华氏温度与摄氏度对照表*/main(){ int fahr, celsius; int lower, upper, step; lower = 0; upper = 300; step = 20; fahr = lower; while (fahr <= upper){ celsius = 5 * (fahr - 32) / 9; printf("%d\t%d\n", fahr, celsius); fahr = fahr + step; }}
2. 所有变量必须先声明后使用。声明用于说明变量的属性,它由一个类型名和一个变量表组成。
3. 良好的编程习惯是:每行只写一条语句,并在运算符两边各加上一个空格字符。
为了更加精确的计算温度,我们需要将整型数替换为浮点数:
#include1. 就算浮点型常量取值整型,也要加上一个小数点,强调浮点性质。/* 当fahr = 0,20,...,300时,分别打印华氏温度与摄氏度对照表*/main(){ float fahr, celsius; int lower, upper, step; lower = 0; upper = 300; step = 20; fahr = lower; while (fahr <= upper){ celsius = (5.0 / 9.0) * (fahr - 32.0); printf("%3.0f\t%6.1f\n", fahr, celsius); fahr = fahr + step; }}
2. printf的一些格式:%o表示八进制数;%x表示十六进制数;%c表示字符;%s表示字符串;%%表示百分号(%)本身。
习题1-3:
#include习题1-4:/* 当fahr = 0,20,...,300时,分别打印华氏温度与摄氏度对照表*/main(){ float fahr, celsius; int lower, upper, step; lower = 0; upper = 300; step = 20; printf("华氏温度转换为摄氏度\n"); fahr = lower; while (fahr <= upper){ celsius = (5.0 / 9.0) * (fahr - 32.0); printf("%3.0f\t%6.1f\n", fahr, celsius); fahr = fahr + step; }}
#include程序输出:/* 当fahr = 0,20,...,300时,分别打印摄氏度与华氏温度对照表*/main(){ float fahr, celsius; int lower, upper, step; lower = 0; upper = 300; step = 20; printf("摄氏度转换为华氏温度\n"); celsius = lower; while (celsius <= upper){ fahr = 32.0 + 9.0 / 5.0 * celsius; printf("%6.1f\t%3.1f\n", celsius, fahr); celsius = celsius + step; }}
习题1-5:
#include程序输出:main(){ float fahr, celsius; int lower, upper, step; lower = 0; upper = 300; step = 20; fahr = upper; while (fahr >= lower){ celsius = (5.0 / 9.0) * (fahr - 32.0); printf("%6.1f\t%3.1f\n", celsius, fahr); fahr = fahr - step; }}
1.4 符号常量
使用幻数0,300,20并不是好的编程习惯,我们可以通过符号常量(宏定义)方式改写程序:
#include#define LOWER 0#define UPPER 300#define STEP 20main(){ int fahr; for (fahr = LOWER; fahr <= UPPER; fahr += STEP){ printf("%3d\t%6.1f\n", fahr, (5.0 / 9.0) * (fahr - 32.0)); }}
1.5 字符输入/输出
标准库提供的输入/输出模型非常简单。无论文本从何处输入,输出到何处,其输入/输出都是按照字符流的方式处理。文本流是由多行字符构成的字符序列,而每行字符则由0个或多个字符组成,行末是一个换行符。
最基本的输入输出函数为:getchar()--读取单个字符,putchar(c)--打印字符c。
1.5.1 文件复制
#include程序输入输出如下:main(){ int c; c = getchar(); while (c != EOF){ putchar(c); c = getchar(); }}
1. 这里c之所以声明为int而不是char,是因为我们要保证能够存储任何字符外还能存储特殊字符EOF(end of file).
2. c = getchar()之类的赋值操作是一个表达式,并且具有一个值,即赋值后左边变量保存的值。所以代码可以进行类似的简洁修改:
#include当处理长的表达式的时候,遇到算术符的优先级,加上括号是一个非常好的习惯。main(){ int c; while ((c = getchar()) != EOF){ putchar(c); }}
习题1-6:
表达式getchar() != EOF永远为true,因为EOF本身无法用单个字符表示。EOF的值为-1,但是当你输入-1的时候,实际上输入了两个字符“-”,“1”。我们可以通过习题1-7知道EOF的准确值。
习题1-7:
#include显示-1.main(){ printf("%d\n", EOF);}
1.5.2 字符计数
#include程序输入输出:main(){ long nc; nc = 0; while (getchar() != EOF) { ++nc; } printf("%ld\n", nc);}
我们可以用for循环简化(第一次看到这段代码的时候,我惊呆了)
#include程序输入输出:main(){ double nc; for (nc = 0; getchar() != EOF; ++nc){ ; } printf("%.0f\n", nc);}
我第一次明白,原来分号(“;”)可以这样用。
1.5.3 行计数
#include程序输入输出:main(){ int c, nl; nl = 0; while ((c = getchar()) != EOF){ if ('\n' == c){ ++nl; } } printf("%d\n", nl);}
当然,我们也可以用下面的代码完成同样的工作(不推荐):
#include1. 单引号中的字符表示一个整型值,该值等于此字符在机器字符集中对应的数值,我们称之为字符常量。但是,它只不过是小的整型数的另一种写法而已(比如‘\n’代表10),但是‘\n’的意义更加清楚,且与特定的字符集无关。main(){ int c, nl; nl = 0; while ((c = getchar()) != EOF){ if (10 == c){ ++nl; } } printf("%d\n", nl);}
习题1-8:
#include程序输入输出:main(){ int c, ns, nt, nl; ns = 0; nt = 0; nl = 0; while ((c = getchar()) != EOF){ if (' ' == c){ ns++; } else if ('\t' == c){ nt++; } else if ('\n' == c){ nl++; } } printf("空格符为%d\n制表符为%d\n换行符为%d\n", ns, nt, nl);}
习题1-9:
#include习题1-10:main(){ int c; int bSpace = 0; while ((c = getchar()) != EOF){ if (' ' == c){ bSpace = 1; } else{ if (bSpace){ putchar(' '); bSpace = 0; } putchar(c); } }}
#include1.5.4 单词计数main(){ int c; while ((c = getchar()) != EOF){ if ('\t' == c){ printf("\\t"); } else if ('\b' == c){ printf("\\b"); } else if ('\\' == c){ printf("\\\\"); } else{ putchar(c); } }}
#include程序输入输出:#define IN 1 /*在单词内*/#define OUT 0 /*在单词外*/main(){ int c, nl, nw, nc, state; state = OUT; nl = nw = nc = 0; while ((c = getchar()) != EOF){ ++nc; if ('\n' == c){ ++nl; } if ((' ' == c) || ('\n' == c) || ('\t' == c)){ state = OUT; } else if (state == OUT){ state = IN; ++nw; } } printf ("%d %d %d\n", nl, nw, nc);}
习题1-12:
#include程序输入输出:main(){ int c; int nSpace = 0; while ((c = getchar()) != EOF){ if ((' ' == c) || ('\t' == c)){ nSpace = 1; } else{ if (nSpace){ nSpace = 0; putchar('\n'); } putchar(c); } }}
1.6 数组
#include只要明白,字符常量只是整型值的一种表达形式,那么这段代码将不难理解了。main(){ int c, i, nwhite, nother; int ndigit[10]; nwhite = nother = 0; for (i = 0; i < 10; i++){ ndigit[i] = 0; } while ((c = getchar()) != EOF){ if ((c >= '0') && (c <= '9')){ ++ndigit[c - '0']; } else if ((' ' == c) || ('\n' == c) || ('\t' == c)){ ++nwhite; } else{ ++nother; } } printf("digits ="); for (i = 0; i < 10; ++i){ printf(" %d", ndigit[i]); } printf(", white space = %d, other = %d", nwhite, nother);}
习题1-13:
目前无法达到的一个高度是:通过EOF来显示所有的单词直方图结果,只要输入换行,则显示直方图的结果。
1-13-1: 水平直方图:
#include程序输入输出:main(){ int c; int nCount = 0; //单词的长度 while ((c = getchar()) != EOF){ if ((' ' != c) && ('\t' != c) && ('\n' != c)){ putchar(c); nCount++; } else{ if (nCount == 0) //处理连续的空格符,制表符和换行符 continue; putchar(':'); while (--nCount >= 0){ putchar('*'); } putchar('\n'); nCount = 0; //这里进行计数的纠正,否则nCount会变成-1,导致计数不准确 } }}
垂直直方图:
#includeint main(void){ int c; int nSpace = 0; //用于处理多空格,制表符情况 int nCount = 0; //用于处理:用*表示单词长度 int nl = 0; //用于判断显示是否换行 char nArray[10][5]; //用于存储单词--每个单词的长度限制为5,因为要在屏幕上显示出来(当然,如果你的屏幕足够大,一个单词长度可以为100) char mArray[5][10]; //用于存储每个单词出现的星号 int i = 0; int j = 0; for ( i = 0; i < 10; i++ ){ for ( j = 0; j < 5; j++ ){ nArray[ i ][ j ] = ' '; } } for ( i = 0; i < 5; i++ ){ for ( j = 0; j < 10; j++ ){ mArray[ i ][ j ] = ' '; } } i = j = 0; //显示单词和*的一个数组,比如二维数组的第一个元素是hello*****,后面加*号代表长度 while ( ( c = getchar() ) != EOF ){ if ( ( ' ' != c ) && ( '\t' != c ) && ( '\n' != c ) ){ nSpace = 0; if ((j > 5) || (i > 9)){ break; } nArray[i][j++] = c; } else{ if (nSpace) //说明是多空格,所以忽略,继续输入 continue; nSpace = 1; nCount = j + 1; while ( --nCount ){ mArray[ 5 - nCount ][ i ] = '*'; //这里的星号存放的顺序!! } i++; j = 0; } } for ( i = 0; i < 5; i++ ){ for ( j = 0; j < 10; j++ ){ printf("%c ", mArray[ i ][ j ] ); } printf("\n"); } for ( i = 0; i < 10; i++ ){ for ( j = 0; j < 5; j++ ){ printf("%c", nArray[ i ][ j ] ); } printf(" "); } return 0;}
程序输出:
这里主要是为了适应输出的客观性,所以就限制了只能输出10个单词,每个单词的长度要小于等于5.当然,水平直方图也可以参考这个代码,可以输出的更漂亮一些.
PS:顺便吐槽一下买的<C程序设计语言>的参考书,什么破答案.还是自己写的比较有保障一些.
习题1-14:
#include如果显示出垂直方向的直方图,我倒也不会写。main(){ int ndigits[52]; int c; int i; for (i = 0; i < 52; i++){ ndigits[i] = 0; } while ((c = getchar()) != EOF){ if (c >= 'a' && c <= 'z'){ ++ndigits[c - 'a']; } else if (c >= 'A' && c <= 'Z'){ ++ndigits[c - 'A' + 26]; } } for (c = 'a'; c <= 'z'; c++){ printf("%c:%d\n", c, ndigits[c - 'a']); } for (c = 'A'; c <= 'Z'; c++){ printf("%c:%d\n", c, ndigits[c - 'A' + 26]); }}
1.7 函数
我们通常把函数定义中圆括号列表中出现的变量称为形式参数,而把函数调用中与形式参数对应的值称为实际参数。
1.8 参数---传值调用
C语言中“通过值”传递,而在C++中,可以通过“引用”传递。
在C中,可以通过指针的概念达到类似“引用”传递的效果。
1.9 字符数组
读取并打印最长行:
#include#define MAXLINE 1000int getline(char line[], int maxline);void copy(char to[], char from[]);main(){ int len; int max; char line[MAXLINE]; char longest[MAXLINE]; max = 0; while ((len = getline(line, MAXLINE)) > 0){ if (len > max){ max = len; copy(longest, line); } } if (max > 0){ printf("%s", longest); } return 0;}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; ++i; } s[i] = '\0'; return i;}void copy(char to[], char from[]){ int i; i = 0; while ((to[i] = from[i]) != '\0'){ ++i; }}
习题1-16:
通过链表可以达到无限制的输入:
#include程序输出:#include #include typedef struct NODE{ int value; struct NODE *next;} Node;void printNode( Node *node ){ while ( node ){ printf("%c", node->value); node = node->next; } printf("\n");}int main(void){ int count = 0; //当前行的长度 int maxLine = 0; //最大行的长度 int ch; Node *node1 = NULL; //这里node1一定要初始化(PS:之前我经常忘记,因为用的是静态的节点,导致自动初始化) Node *tempNode = NULL; Node *resultNode = NULL; while ( ( ch = getchar() ) != EOF ){ if ( ch != '\n' ){ count++; tempNode = malloc( sizeof( Node ) ); tempNode->value = ch; tempNode->next = node1; node1 = tempNode; } else if( count > maxLine ){ Node *newNode; Node *deleteNode; maxLine = count; count = 0; while ( resultNode ){ deleteNode = resultNode; resultNode = resultNode->next; free( deleteNode ); //这里进行节点的删除的时候,一定要建立一个临时的变量进行存储节点,对临时的变量进行删除 } while ( node1 ){ newNode = malloc( sizeof( Node ) ); newNode->value = node1->value; newNode->next = resultNode; resultNode = newNode; node1 = node1->next; } } } printNode( resultNode ); return 0;}
习题1-17:对习题1-16稍做修改即可,长度大于10的输出:
#include程序输出:#include #include typedef struct NODE{ int value; struct NODE *next;} Node;void printNode( Node *node ){ printf("the line is : "); while ( node ){ printf("%c", node->value); node = node->next; } printf("\n");}int main(void){ int count = 0; //当前行的长度 int maxLine = 0; //最大行的长度 int ch; Node *node1 = NULL; //这里node1一定要初始化(PS:之前我经常忘记,因为用的是静态的节点,导致自动初始化) Node *tempNode = NULL; Node *resultNode = NULL; while ( ( ch = getchar() ) != EOF ){ if ( ch != '\n' ){ count++; tempNode = malloc( sizeof( Node ) ); tempNode->value = ch; tempNode->next = node1; node1 = tempNode; } else { Node *newNode; Node *deleteNode; while ( resultNode ){ deleteNode = resultNode; resultNode = resultNode->next; free( deleteNode ); //这里进行节点的删除的时候,一定要建立一个临时的变量进行存储节点,对临时的变量进行删除 } while ( node1 ){ newNode = malloc( sizeof( Node ) ); newNode->value = node1->value; newNode->next = resultNode; resultNode = newNode; node1 = node1->next; } if ( count > 10 ){ count = 0; printNode( resultNode ); } } } return 0;}
1-18:
第二个hello world中包含了换行符和多余的空格:
#include程序输出:#include #include #define MAXLINE 128int main(void){ int i = 0; char arr[ MAXLINE ]; int lineLen = 0; for ( i = 0; i < MAXLINE; i++ ){ arr[ i ] = '\0'; } while ( NULL != fgets( arr, MAXLINE, stdin ) ){ for ( i = MAXLINE - 1; i >= 0; i-- ){ if ( ' ' == arr[ i ] || '\n' == arr[ i ] || '\t' == arr[ i ] ){ arr[ i ] = '\0'; } else if ( arr[ i ] != '\0' ){ break; } } for ( i = 0; i < MAXLINE; i++ ){ if ( '\0' == arr[ i ] ){ lineLen = i; break; } putchar( arr[ i ] ); } printf("\nthe line length is:%d\n", lineLen ); //这里不要用i来代表长度 for ( i = 0; i < MAXLINE; i++ ){ //要对arr进行删除操作 arr[ i ] = '\0'; } } return 0;}
1-19:
#include程序输出:void reverse( char *string ){ char *temp = string; while ( *temp ){ temp++; } temp--; //'\0'要省略 while ( temp > string ){ char ch = *temp; *temp-- = *string; *string++ = ch; }}int main(void){ char str1[] = "hello"; char str2[] = "world"; reverse( str1 ); reverse( str2 ); printf("%s\n", str1 ); //str1本身就代表指针,不要输出*str1 printf("%s\n", str2 ); return 0;}
1.10 外部变量与作用域
由于自动变量只在函数调用执行期间存在,因此,在函数的两次调用之间,自动变量不保留前次调用时的赋值,且在每次进入函数时都要显式为其赋值.如果自动变量没有赋值,则其中存放的是无效值.
外部变量必须定义在所有函数之外,且只能定义一次,定义后编译器程序将为它分配存储单元.在每个需要访问外部变量的函数中,必须声明相应的外部变量,此时说明其类型.声明时可以用extern语句显式声明,也可以通过上下文隐式声明.
#include如果程序包含在多个源文件中,而某个变量在file1文件中定义,在file2和file3文件中使用,那么在文件file2与file3中就需要使用extern声明来建立该变量与其定义之间的联系.#define MAXLINE 100 //允许的输入行的最大长度int max; //到目前为止发现的最长行的长度char line[ MAXLINE ]; //当前的输入行char longest[ MAXLINE ];//用于保存最长的行int getline( void );void copy( void );int main(void){ int len; extern int max; extern char longest[]; max = 0; while ( ( len = getline() ) > 0 ){ if ( len > max ){ max = len; copy(); } } if ( max > 0 ){ printf("%s", longest ); } return 0;}int getline( void ){ int c, i; extern char line[]; for ( i = 0; i < MAXLINE - 1 && ( c = getchar() ) != EOF && c != '\n'; i++ ){ line[ i ] = c; } if ( '\n' == c ){ line[ i ] = c; i++; } line[ i ] = '\0'; return i;}void copy( void ){ int i; extern char line[], longest[]; i = 0; while ( ( longest[ i ] = line[ i ] ) != '\0' ){ i++; }}
"定义"表示创建变量或分配存储单元,而"声明"指的是说明变量的性质,但并不分配存储单元.
1-20:
#include程序输出:#include int main(void){ int ch; int temp; int isTab = 0; while ( ( ch = getchar() ) != EOF ){ temp = ch; if ( '\\' == ch && 0 == isTab ){ isTab = 1; } else{ if ( isTab ){ if ( 't' == ch ){ isTab = 0; putchar( '\t' ); continue; } else if ( '\\' != ch ){ isTab = 0; putchar( '\\' ); } } putchar( ch ); } } return 0;}
但是答案似乎不是这样写,答案如下:
#include原来程序的含义是:将\t指定为8个(或者也可以4个)输出,看来我理解错误了.#define TABINC 8int main(void){ int c, nb, pos; nb = 0; pos = 1; while ( ( c = getchar() ) != EOF ){ if ( '\t' == c ){ nb = TABINC - ( pos - 1 ) % TABINC; while ( nb > 0 ){ putchar( ' ' ); ++pos; --nb; } } else if ( '\n' == c ){ putchar( c ); pos = 1; } else{ putchar( c ); ++pos; } }}
1-21:题目没看懂其实.然后研究一下答案吧:
但是觉得这道程序貌似做无用功,把足够的空格符换成制表符输出,比如八个空格换成制表符,而一个制表符为4个空格,则只要输出4个空格就可以了.那为什么不直接计算有8个空格的时候,输出4个空格不就行了吗?
把答案粘贴出来吧,虽然我并不认可这种做法:
#include1-22:#define TABINC 8int main(void){ int c, nb, nt, pos; nb = 0; nt = 0; for ( pos = 1; ( c = getchar() ) != EOF; ++pos ){ if ( ' ' == c ){ if ( 0 != pos % TABINC ){ ++nb; } else{ nb = 0; ++nt; } } else{ for ( ; nt > 0; --nt ){ putchar( '\t' ); } if ( '\t' == c ){ nb = 0; } else{ for ( ; nb > 0; --nb ){ putchar( ' ' ); } } putchar( c ); if ( '\n' == c ){ pos = 0; } else if ( '\t' == c ){ pos = pos + ( TABINC - ( pos - 1 ) % TABINC ) - 1; } } }}
这是一种错误的思路,因为它严格按照书本上划分行了(我怀疑是书上翻译有问题的).第二段代码是自己个人觉得正确的代码.先把第一段代码copy上来:
#include程序输出:#include #include #define MAXLINE 128void showMulLine( char *string, int index ){ char *tempstr = string; int len = strlen( string ); int tempLen; int realIndex = index; //用于每次增加index if ( len <= index ){ //当一行的长度小于要分割的长度时,直接输出 printf("%s\n", string ); return; } while ( index < len ){ tempLen = index; while ( tempLen ){ if ( ' ' != string[ tempLen ] || '\t' != string[ tempLen ] ){ //略过空格和制表符 break; } tempLen--; } while ( string < &tempstr[ tempLen ] ){ //这里有个隐藏的BUG,之前是写成string < &string[ tempLen ],但是string在循环体内变了,所以这个变成了死循环!!! putchar( *string ); string++; } printf("\n"); index += realIndex; } if ( index < len ){ //处理最后要分的行 while ( len ){ if ( ' ' != string[ len ] || '\t' != string[ len ] ){ break; } len--; } while ( string < &tempstr[ len ] ){ putchar( *string ); string++; } printf("\n"); }}int main(void){ char arr[ MAXLINE ]; while ( fgets( arr, MAXLINE, stdin ) != NULL ){ showMulLine( arr, 10 ); } return 0;}
正确的代码应该可以将world单词放在第二行,而不是强行分开:
#include程序输出:#include #include #define MAXLINE 128void showMulLine( char *string, int index ){ char *tempStr = string; int pos = 0; int tempPos = 0; //临时的索引,用于处理分行中空格后面的连续空格和空格后存在单词的情况 int tempIndex = 0; //临时的索引,用于处理分行中空格出现的情况 int isSpace = 0; //判断是否出现空格 int isMulSpace = 0; //判断是否出现多个空格 int isNewLine = 0; //用于删除一行开头的空格 while ( pos < index && '\n' != string[ pos ] ){ if ( pos == index - 1 && ' ' != string[ pos ] ){ //用于处理超过一个单词超过index长度的情况 putchar( string[ pos ] ); string += pos; pos = 0; continue; } if ( ' ' == string[ pos ] ){ isSpace = 1; } else{ tempPos = pos; if ( !isSpace ){ putchar( string[ pos ] ); } else{ isSpace = 0; tempIndex = index; //判断是否出现多个空格的情况 while ( tempPos < tempIndex ){ if ( ' ' == string[ tempIndex ] ){ isMulSpace = 1; break; } tempIndex--; } if ( isMulSpace ){ putchar( ' ' ); //存在多个空格情况下,补齐第一个空格 isMulSpace = 0; while ( tempPos < tempIndex ){ putchar( string[ tempPos ] ); tempPos++; } tempPos++; //存在多个空格情况下,将导致string的开头有个空格,故删除 } putchar( '\n' ); string += tempPos; pos = -1; //因为最终pos都要执行自增,所以赋值为-1,导致下次循环从0开始 } } pos++; }}int main(void){ char arr[ MAXLINE ]; while ( fgets( arr, MAXLINE, stdin ) != NULL ){ showMulLine( arr, 10 ); } return 0;}
1.
2.
新的代码如下:
void showMulLine(char *line){ char arr[MAXLINE][MAXLINE] = {'\0'}; int i = 0; int j = 0; int isEnd = 0; int size; //数组的个数 int len; int index = 0; //将输入的一行数据分割成以空白字符分割的字符串数组:hello world i love ,则数组中存储["hello ", "world ", "i ", "love "]; while (*line) { if ((' ' == *line || '\t' == *line || '\n' == *line)) { arr[i][j++] = *line; line++; isEnd =1; continue; } if (' ' != *line && '\t' != *line && '\n' != *line) { if (isEnd) { j = 0; i++; arr[i][j++] = *line; isEnd = 0; } else { arr[i][j++] = *line; } line++; } } size = i; len = 0; index = 0; //以LENGTH为长度进行分割操作 for (i = 0; i <= size; i++) { len += strlen(arr[i]); if (len < LENGTH) { index++; printf("%s", arr[i]); } else { if (index == 0) { printf("%s", arr[i]); } else { i--; } printf("\n"); len = 0; } }}
1-23:
#include程序输出:#include #include #define MAXSIZE 128#define LINENUM 20int isDoubleSlash; //出现注释符'//'int isSlashStar; //出现注释符/**/void dealLine( char *line, char **mulLine, int index ){ int len = strlen( line ); char *newLine = malloc( len * sizeof( char )); char *temp = newLine; while ( '\n' != *line ){ //备注:getline是以换行符/n结束,而不是以\0结束 if ( '/' == *line && '/' == *( line + 1 ) ){ isDoubleSlash = 1; } else if ( '/' == *line && '*' == *( line + 1 ) ){ isSlashStar = 1; } if ( isDoubleSlash ){ //出现'//',直接忽略后面的注释字符串 isDoubleSlash = 0; *line = '\0'; break; } if ( isSlashStar && '*' == *line && '/' == *( line + 1 ) && '/' != *( line - 1 ) ){ //防止出现/*/的情况 isSlashStar = 0; line += 2; continue; } if ( !isSlashStar ){ *temp = *line; temp++; } line++; } *temp = '\0'; mulLine[ index ] = newLine;}int main(void){ int ch; char line[ MAXSIZE ]; char *mulLine[ LINENUM ]; int index = 0; int i = 0; int j = 0; for ( i = 0; i < MAXSIZE; i++ ){ line[ i ] = '\0'; } for ( i = 0; i < LINENUM; i++ ){ mulLine[ i ] = ""; } while ( NULL != fgets( line, MAXSIZE, stdin ) ){ dealLine( line, mulLine, index ); index++; } printf("\nthe text is:\n"); for ( i = 0; i < LINENUM; i++ ){ if ( '\0' != mulLine[ i ][ 0 ] ){ //不要进行"" != mulLine[ i ]的判断 printf("%s\n", mulLine[ i ] ); } } return 0;}
1-24:
#include程序输出:#include #include #define MAXSIZE 128#define LINENUM 20int isDoubleSlash; //出现注释符'//'int isSlashStar; //出现注释符/**///对注释进行处理void dealLine( char *line, char **mulLine, int index ){ int len = strlen( line ); char *newLine = malloc( len * sizeof( char )); char *temp = newLine; while ( '\n' != *line ){ //备注:getline是以换行符/n结束,而不是以\0结束 if ( '/' == *line && '/' == *( line + 1 ) ){ isDoubleSlash = 1; } else if ( '/' == *line && '*' == *( line + 1 ) ){ isSlashStar = 1; } if ( isDoubleSlash ){ //出现'//',直接忽略后面的注释字符串 isDoubleSlash = 0; *line = '\0'; break; } if ( isSlashStar && '*' == *line && '/' == *( line + 1 ) && '/' != *( line - 1 ) ){ //防止出现/*/的情况 isSlashStar = 0; line += 2; continue; } if ( !isSlashStar ){ *temp = *line; temp++; } line++; } *temp = '\0'; mulLine[ index ] = newLine;}//对方括号进行处理int dealSquareBrackets( char *line ){ int bracketNum = 0; while ( '\0' != *line ){ if ( '[' == *line && 0 == bracketNum ){ bracketNum++; } else if ( ']' == *line && 0 != bracketNum ){ bracketNum--; } if ( bracketNum < 0 ){ return 1; } line++; } return bracketNum;}//对圆括号和花括号进行处理int dealBrackets( char **mulLine ){ char *temp; int parenthesisNum = 0; //判断圆括号的次数 int braceNum = 0; //判断花括号的次数 int i = 0; int countNum = 0; int countParenthesisNum = 0; //计算左圆括号出现的位置 int countBraceNum = 0; //计算左花括号出现的位置 for ( i = 0; i < LINENUM; i++ ){ temp = mulLine[ i ]; while ( '\0' != *temp ){ countNum++; if ( '(' == *temp ){ countParenthesisNum = countNum; parenthesisNum++; } else if ( ')' == *temp ){ parenthesisNum--; } else if ( '{' == *temp ){ countBraceNum = countNum; braceNum++; } else if ( '}' == *temp ){ braceNum--; } //右圆括号和右花括号不可出现在左圆括号和左花括号之前 if ( parenthesisNum < 0 || braceNum < 0 ){ return 1; } //圆括号中不可包含花括号 if ( 0 != parenthesisNum && 0 != braceNum && ( countParenthesisNum < countBraceNum ) ){ return 1; } //圆括号中不可出现分号';' if ( 0 != parenthesisNum && ';' == *temp ){ return 1; } countNum = 0; countParenthesisNum = 0; countBraceNum = 0; temp++; } } //判断圆括号和花括号是否匹配 if ( 0 != parenthesisNum || 0 != braceNum ){ return 1; } return 0;}int main(void){ char line[ MAXSIZE ]; char *mulLine[ LINENUM ]; int index = 0; int i = 0; int j = 0; int isOK = 0; for ( i = 0; i < MAXSIZE; i++ ){ line[ i ] = '\0'; } for ( i = 0; i < LINENUM; i++ ){ mulLine[ i ] = ""; } //对注释进行处理 while ( NULL != fgets( line, MAXSIZE, stdin ) ){ dealLine( line, mulLine, index ); index++; } //对方括号进行处理 for ( i = 0; i < LINENUM; i++ ){ isOK = dealSquareBrackets( mulLine[ i ] ); if ( isOK ){ perror("1--brackets error:"); break; } } //对圆括号和花括号进行处理 isOK = dealBrackets( mulLine ); if ( isOK ){ perror("2--brackets error:"); } printf("\nthe text is:\n"); for ( i = 0; i < LINENUM; i++ ){ if ( '\0' != mulLine[ i ][ 0 ] ){ //不要进行"" != mulLine[ i ]的判断 printf("%s\n", mulLine[ i ] ); } } return 0;}