E x c e r c i s e 1 − 2 Excercise\quad 1-2 Excercise1−2:测试结果如图1所示,这里需要注意的是转义字符序列 \ o o o \backslash ooo \ooo和序列 \ x h h \backslash xhh \xhh分别表示3个八进制数和2个十进制数对应的值对应于 A S C I I ASCII ASCII码表中的字符,比如字符 A A A对应的 A S C I I ASCII ASCII码表中的十进制值为65(其对应的十六进制和8进制分别是 0 x 41 0x41 0x41和 0101 0101 0101),那么 \ 101 \backslash 101 \101和 \ x 41 \backslash x41 \x41都表示字符 A A A,但是在实际的程序中十六进制数前面带的是 0 x 0x 0x,八进制数前面带的是 0 0 0,这一点要区别开。
#include <stdio.h>int main(void)
{printf("alert(bell) character(0x07,\\a): te\ast\n");printf("backspace(0x08,\\b): te\bst\n");printf("formfeed(0x0C,\\f): te\fst\n"); printf("newline(0x0A,\\n): te\nst\n"); printf("carriage return(0x0D,\\r): te\rst\n"); printf("horizontal tab(0x09,\\t): te\tst\n");printf("vertical tab (0x0B,\\v): te\vst\n");printf("backslash(0x5C,\\\\): te\\st\n");printf("question mark(0x3F,\\?): te\?st\n");printf("single quote(0x27,\\\'): te\'st\n"); printf("double quote(0x22,\\\"): te\"st\n");/* ** ASCII Decimal Hexadecimal* A 65 41* */printf("hexadecimal number to decimal number=%d\n",0x41); printf("hexadecimal escape sequence described character to decimal number=%d\n",'\x41');printf("hexadecimal escape sequence described character=%c\n",'\x41'); /* ** ASCII Decimal octal* A 65 41* */printf("octal number to decimal number=%d\n",0101); printf("octal escape sequence described character to decimal number=%d\n",'\101');printf("octal escape sequence described character=%c",'\101');return 0;
}
E x c e r c i s e 1 − 3 Excercise\quad 1-3 Excercise1−3:测试结果如图2所所示。
#include <stdio.h>/* ** print Fahrenheit-Celsius table for fahr=0,20,...,300;* */int main(void)
{float fahr,celsius;int lower,upper,step;lower=0; /* lower limit of temperature table */upper=300;/* upper limit */step=20; fahr=lower;printf("fahr celsius\n"); while(fahr<=upper){celsius=(5.0/9.0)*(fahr-32.0);printf("%4.0f %6.1f\n",fahr,celsius); fahr=fahr+step; }return 0;
}
E x c e r c i s e 1 − 4 Excercise\quad 1-4 Excercise1−4:测试结果如图3所所示。
#include <stdio.h>/* ** print Celsius-Fahrenheit table for Celsius=0,20,...,300;* */int main(void)
{float fahr,celsius;int lower,upper,step;lower=0; /* lower limit of temperature table */upper=300;/* upper limit */step=20; celsius=lower;printf("celsius fahr\n"); while(celsius<=upper){fahr=(9.0/5.0)*celsius+32.0;printf("%4.0f %10.1f\n",celsius,fahr); celsius=celsius+step; }return 0;
}
E x c e r c i s e 1 − 5 Excercise\quad 1-5 Excercise1−5:测试结果如图4所所示。
#include <stdio.h>/* ** print Fahrenheit-Celsius table for fahr=0,20,...,300;* */int main(void)
{int fahr;printf("fahr celsius\n");for(fahr=300;fahr>=0;fahr=fahr-20){printf("%4d %7.1f\n",fahr,(5.0/9.0)*(fahr-32.0)); } return 0;
}
E x c e r c i s e 1 − 6 Excercise\quad 1-6 Excercise1−6:测试结果如图5所所示。
/* This program prompts for input, and then captures a character* from the keyboard. If EOF is signalled (through a control+Z * for windows system),the program prints 0. Otherwise, it prints 1.* If your input stream is buffered (and it probably is), then* you will need to press the ENTER key before the program will* respond.*/#include <stdio.h>int main(void)
{printf("Press a key. ENTER would be nice :\n");printf("The expression getchar() != EOF evaluates to %d\n", getchar() != EOF);return 0;
}
E x c e r c i s e 1 − 7 Excercise\quad 1-7 Excercise1−7:测试结果如图6所所示。
#include <stdio.h>int main(void)
{printf("The value of EOF is %d\n\n", EOF); return 0;
}
E x c e r c i s e 1 − 8 Excercise\quad 1-8 Excercise1−8:
#include <stdio.h>int main(void)
{char c=0;int numOfBlank=0;int numOfTab=0;int numOfNewline=0; while((c=getchar())!=EOF){if(c=='\n'){numOfNewline++; printf("This is new line character\n"); }else if(c=='\t'){numOfTab++; printf("This is tab character\n"); }else if(c==' '){numOfBlank++; printf("This is blank character\n"); }else{printf("Is none of the three characters\n"); }}printf("numOfNewline=%d,numOfTab=%d,numOfBlank=%d\n", numOfNewline,numOfTab,numOfBlank); return 0;
}
E x c e r c i s e 1 − 9 Excercise\quad 1-9 Excercise1−9:
#include <stdio.h>int main(void)
{char c=0;char blank_c=' '; int numOfContinuousBlanks=0; while((c=getchar())!=EOF){if(c==' '){numOfContinuousBlanks++; }else{if(numOfContinuousBlanks!=0){numOfContinuousBlanks=0;putchar(blank_c); } putchar(c); }}return 0;
}
E x c e r c i s e 1 − 10 Excercise\quad 1-10 Excercise1−10:
#include <stdio.h>int main(void)
{char c=0; while((c=getchar())!=EOF){if(c=='\t'){putchar('\\'); putchar('t'); }else if(c=='\b'){putchar('\\'); putchar('b'); }else if(c=='\\'){putchar('\\'); putchar('\\'); }else{ putchar(c); } }return 0;
}
E x c e r c i s e 1 − 12 Excercise\quad 1-12 Excercise1−12:
#include <stdio.h>int main(void)
{char c=0;int already_print_newline=0;int word_ch_start=0; while((c=getchar())!=EOF){if((c=='\n') ||(c=='\t') ||(c==' ')){if(word_ch_start==1){ if(already_print_newline==0){ c='\n';putchar(c); already_print_newline=1; } } }else{if(word_ch_start==0){ word_ch_start=1; } if(already_print_newline==1){ already_print_newline=0; } putchar(c); } }return 0;
}
E x c e r c i s e 1 − 13 Excercise\quad 1-13 Excercise1−13:这里对 w o r d word word的定义是连续的且不包含 \ t \backslash t \t, \ n \backslash n \n和空格的连续的字符序列。代码中变量 w _ s t a r t w\_start w_start是为了处理处理的字符流的最前面就是一个或多个的 \ t \backslash t \t, \ n \backslash n \n或空格的情况。
#include <stdio.h>#define MAX_WORD_LEN (10)#define IN_WORD (0)
#define OUT_WORD (1)int main(void)
{char c=0;int w_l_sta[MAX_WORD_LEN+1]={0}; int current_w_l=0; int current_w_c=0; int index=0;int index_e=0; int w_state=IN_WORD;int w_start=0; int c_most=0; while((c=getchar())!=EOF){if((c=='\n') ||(c=='\t') ||(c==' ')){ if(w_start==1){ if(w_state==IN_WORD){ w_state=OUT_WORD;w_l_sta[current_w_l]++; current_w_l=0; } } }else{if(w_start==0){ w_start=1; } if(w_state==OUT_WORD){ w_state=IN_WORD; } current_w_l++; } }printf("Below is horizontal histogram:\n"); printf("word length | word number\n"); for(index=1;index<=MAX_WORD_LEN;index++){printf("%11d : ",index); current_w_c=w_l_sta[index];if(current_w_c>c_most){c_most=current_w_c; }while(current_w_c!=0){current_w_c=current_w_c-1; printf("*"); }printf("\n"); }printf("Below is vertical histogram:\n"); printf("word number :\n"); for(index=c_most;index>0;index--){printf("%11d :",index); for(index_e=1;index_e<=MAX_WORD_LEN;index_e++){if(w_l_sta[index_e]>=index){printf(" * "); } } printf("\n"); }printf(" =============================================\n"); printf("word length :"); for(index=1;index<=MAX_WORD_LEN;index++){printf(" %d ",index); } return 0;
}
E x c e r c i s e 1 − 14 Excercise\quad 1-14 Excercise1−14:
#include <stdio.h>int main(void)
{char c=0;int char_num[256]={0}; int most_num=0; int curr_num=0; int index_e=0;int index_i=0; while((c=getchar())!=EOF){curr_num=++char_num[c]; if(curr_num>most_num){ most_num=curr_num;} }printf("Below is vertical histogram:\n"); printf("char number:\n"); for(index_e=most_num;index_e>0;index_e--){printf("%11d|",index_e); for(index_i=0;index_i<=255;index_i++){if(char_num[index_i]>=index_e){printf(" * "); }else if(char_num[index_i]>0){printf(" "); } } printf("\n"); }printf(" -------------------------------------------------------------------\n"); printf("char decima:"); for(index_i=0;index_i<=255;index_i++){if(char_num[index_i]>0){printf(" %d ",(index_i/100)); } }printf("\n "); for(index_i=0;index_i<=255;index_i++){if(char_num[index_i]>0){printf(" %d ",(index_i-(index_i/100)*100)/10); } }printf("\n ");for(index_i=0;index_i<=255;index_i++){if(char_num[index_i]>0){printf(" %d ",(index_i-(index_i/10)*10)); } }printf("\n"); return 0;
}
E x c e r c i s e 1 − 15 Excercise\quad 1-15 Excercise1−15:
#include <stdio.h>/* ** print Fahrenheit-Celsius table for fahr=0,20,...,300;* */float fahrTocelsius(float fahr);int main(void)
{float fahr,celsius;int lower,upper,step;lower=0; /* lower limit of temperature table */upper=300;/* upper limit */step=20; fahr=lower;printf("fahr celsius\n"); while(fahr<=upper){celsius=fahrTocelsius(fahr);printf("%4.0f %6.1f\n",fahr,celsius); fahr=fahr+step; }return 0;
}float fahrTocelsius(float fahr)
{float celsius=(5.0/9.0)*(fahr-32.0); return celsius;
}
E x c e r c i s e 1 − 16 Excercise\quad 1-16 Excercise1−16:这个练习题的意图似乎是在说在只修改 m a i n main main函数的情况下要求可以打印出任何长度的输入行的长度以及尽可能多的文本。在书中的初始程序中当输入行的长度超过允许的最大长度时,返回的长度就是这个允许的最大长度,而不是当前行的实际长度,下面两个实现分别只修改 g e t l i n e getline getline函数(虽然练习题的意图似乎是只让修改 m a i n main main函数)和只修改 m a i n main main函数实现了当输入行的长度超过允许的最大长度时,返回的长度是当前行的实际长度。这里需要注意的是,假设此时程序中宏 M A X L I N E MAXLINE MAXLINE 被定义为5,那么实际用来存储行中字符的空间只有4个,因为另外一个要用来存储字符串的结束字符 \ 0 \backslash 0 \0,还有就是 g e t l i n e getline getline函数返回的长度也是不包含字符串的结束字符 \ 0 \backslash 0 \0的。
/* This is the first program exercise where the spec isn't entirely* clear. The spec says, 'Revise the main routine', but the true* length of an input line can only be determined by modifying* getline. So that's what we'll do. getline will now return the* actual length of the line rather than the number of characters* read into the array passed to it.*/#include <stdio.h>#define MAXLINE 1000 /* maximum input line size */int getline(char line[], int maxline);
void copy(char to[], char from[]);/* print longest input line */
int main(void)
{int len; /* current line length */int max; /* maximum length seen so far */char line[MAXLINE]; /* current input line */char longest[MAXLINE]; /* longest line saved here */max = 0;while((len = getline(line, MAXLINE)) > 0){printf("%d: %s", len, line);if(len > max){max = len;copy(longest, line);}}if(max > 0){printf("Longest is %d characters:\n%s", max, longest);}printf("\n");return 0;
}/* getline: read a line into s, return length */
int getline(char s[], int lim)
{int c, i, j;for(i = 0, j = 0; (c = getchar())!=EOF && c != '\n'; ++i){if(i < lim - 1){s[j++] = c;}}if(c == '\n'){if(i < (lim - 1)){s[j++] = c;}++i;}s[j] = '\0';return i;
}/* copy: copy 'from' into 'to'; assume 'to' is big enough */
void copy(char to[], char from[])
{int i;i = 0;while((to[i] = from[i]) != '\0'){++i;}
}
/* I only changed the main routine. This version ignores the newlines like the unix command wc -L. */
#include <stdio.h>#define MAXLINE 40 /* maximum input line size */int getline(char line[], int maxline);
void copy(char to[], char from[]);/* print longest input line */
int main()
{int c;int len; /* current line length */int max; /* maximum length seen so far */char line[MAXLINE]; /* current input line */char longest[MAXLINE]; /* longest line saved here */max = 0;while ((len = getline(line, MAXLINE)) > 0) {if (line[len-1] != '\n')while ((c = getchar()) != EOF && c != '\n')++len;if (len > max) {max = len;copy(longest, line);}}if (max > 0) { /* there was a line */printf("Longest line with %d characters:\n", max);printf("%s ...\n", longest);}return 0;
}/* getline: read a line s, return length */
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;
}/* copy: copy 'from' into 'to'; assume to is big enough */
void copy(char to[], char from[])
{int i;i = 0;while ((to[i] = from[i]) != '\0')++i;
}
E x c e r c i s e 1 − 17 Excercise\quad 1-17 Excercise1−17:
#include <stdio.h>#define MAXLINE 1000 /* maximum input line size */int getline(char line[], int maxline);int main(void)
{int len; /* current line length */ char line[MAXLINE]; /* current input line */while((len = getline(line, MAXLINE)) > 0){if(len > 80){printf("%s\n", line);}}return 0;
}/* getline: read a line into s, return length */
int getline(char s[], int lim)
{int c, i, j;for(i = 0, j = 0; (c = getchar())!=EOF && c != '\n'; ++i){if(i < lim - 1){s[j++] = c;}}if(c == '\n'){if(i <(lim - 1)){s[j++] = c;}++i;}s[j] = '\0';return i;
}
E x c e r c i s e 1 − 18 Excercise\quad 1-18 Excercise1−18:
/***********************************************
The other code is so complicated. Here is mine
-- Pilcrow
***********************************************//*Perhaps the others are complicated because they are correct, or at least less broken than yours? (Well, apart from the one from TheSunShadow, perhaps?)First, this strips all preceding spaces on a line. Second it searches for and strips (not tested) NULLs. Third it outputs a NULL after every output line-break.None are part of the spec.-- Nick*/#include <stdio.h>
#define MAXLINE 10000char line[MAXLINE+1];
int getline(void);int main(void)
{int len, head, tail, inn;while((len=getline()) > 0) {for(head = 0; line[head] == ' ' || line[head] == '\t'; head++);for(tail = len; line[tail] == ' ' || line[tail] == '\t' || line[tail] == '\n' || line[tail] == '\0';tail--);if(tail - head >= 0){for(inn = head; inn <= tail; inn++)putchar(line[inn]);putchar('\n');putchar('\0');}}return 0;
}int getline(void)
{int c, i;for(i = 0; i < MAXLINE-1 && (c=getchar())!= EOF && c != '\n'; ++i) line[i] = c;if (c == '\n') {line[i] = c;++i;}line[i] = '\0';return i;
}
#include <stdio.h>#define MAXLINE 1000int getline(char str[], int lim);int main(void)
{int len;char line[MAXLINE];while ((len = getline(line, MAXLINE)) > 0)if (len > 1)printf("%s", line);return 0;
}int getline(char str[], int lim)
{int c, i;i = 0;while ((i < (lim-1))&& ((c = getchar()) != EOF) && (c != '\n') && (c != ' ') && (c != '\t')){str[i++] = c;}if(c == '\n') {if(i != 0) {str[i++] = c;} }str[i] = '\0';return i;
}
E x c e r c i s e 1 − 19 Excercise\quad 1-19 Excercise1−19:
#include <stdio.h>#define MAXLINE 1000int getline(char str[], int lim);
void reverse(char str[]);int main(void)
{int len;char line[MAXLINE];while ((len = getline(line, MAXLINE)) > 0){if (len > 1){reverse(line);printf("%s\n", line); }}return 0;
}int getline(char str[], int lim)
{int c, i;i = 0;while ((i < (lim-1))&& ((c = getchar()) != EOF) && (c != '\n')){str[i++] = c;}if(c == '\n') {str[i++] = c; }str[i] = '\0';return i;
}void reverse(char str[])
{int head, tail, len;char temp=0;len = 0;while (str[len]!='\0'){len=len+1; }head=0;tail=len-1;while(tail>=head) {temp=str[head]; str[head]=str[tail];str[tail]=temp; head=head+1;tail=tail-1; }return ;
}
E x c e r c i s e 1 − 20 Excercise\quad 1-20 Excercise1−20:要做这道题,我们首先要大概知道 T a b Tab Tab按键的作用,这里我们简单的用下面的程序演示一下 T a b Tab Tab按键的作用,测试结果如图7所示。从这里我们可以看出无论你现在输入了几个(小于8个)字符,按下 T a b Tab Tab按键之后都会将光标的位置移动到九个字符宽度的位置(这个位置叫做 t a b s t o p tab\quad stop tabstop),有了这个基础之后,我就就可以大概了解这道题的意图了,意图就是用空格来代替 T a b Tab Tab按键的作用,当检测到输入了 T a b Tab Tab按键之后程序应该判断此时应该输出几个空格来达到和 T a b Tab Tab按键同样的效果。
#include <stdio.h>int main(void)
{char line[58]={'1','2','3','4','5','6','7','8','\t','1','2','3','4','5','6','7','\t','1','2','3','4','5','6','\t', '1','2','3','4','5','\t', '1','2','3','4','\t', '1','2','3','\t','1','2','\t','1','\t','e','\0' };printf("%s\n", line); return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MAX_BUFFER 1024int CalculateNumberOfSpaces(int Offset, int TabSize)
{return TabSize - (Offset % TabSize);
}int detab(int offset, int TabSize)
{int index=0;int bla_num=0; bla_num = CalculateNumberOfSpaces(offset, TabSize);for(index = 0; index < bla_num; index++){putchar(' ');offset++;}return offset;
}/* K&R's getline() function from 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;++i;}s[i] = '\0';return i;
}int main(void)
{char Buffer[MAX_BUFFER];int TabSize = 8; int i,l;while(getline(Buffer, MAX_BUFFER) > 0){for(i = 0, l = 0; Buffer[i] != '\0'; i++){if(Buffer[i] == '\t'){l = detab(l, TabSize);}else{putchar(Buffer[i]);l++;}}}return 0;
}
E x c e r c i s e 1 − 21 Excercise\quad 1-21 Excercise1−21:
/******************************************************KnR 1-21--------Write a program "entab" which replaces strings of blanks with the minimum number of tabs and blanks to achieve the same spacing.Author: Rick Dearmanemail: rick@ricken.demon.co.uk******************************************************/
#include <stdio.h>#define MAXLINE 1000 /* max input line size */
#define TAB2SPACE 8 /* 8 spaces to a tab */char line[MAXLINE]; /*current input line*/int getline(void); /* taken from the KnR book. */int main()
{int i,t;int spacecount,len;while (( len = getline()) > 0 ){spacecount = 0;for( i=0; i < len; i++){if(line[i] == ' ')spacecount++; /* increment counter for each space */if(line[i] != ' ')spacecount = 0; /* reset counter *//* Now we have enough spaces to replace them with a tab */ if(spacecount == TAB2SPACE) {/* Because we are removing 8 spaces and** replacing them with 1 tab we move back ** 7 chars and replace the ' ' with a \t*/i -= 7; /* same as "i = i - 7" */len -= 7;line[i] = '\t';/* Now move all the char's to the right into the** places we have removed.*/for(t=i+1;t<len;t++)line[t]=line[t+7];/* Now set the counter back to zero and move the ** end of line back 7 spaces*/spacecount = 0;line[len] = '\0'; }}printf("%s", line);}return 0;
}int getline(void)
{int c, i;for ( i=0;i<MAXLINE-1 && ( c=getchar()) != EOF && c != '\n'; ++i)line[i] = c;if(c == '\n') {line[i] = c;++i;}line[i] = '\0';return i;
}
E x c e r c i s e 1 − 22 Excercise\quad 1-22 Excercise1−22:对于这一题的具体要求我没有弄清楚,下面的代码实现是基于线面代码的原作者以及这位小哥的思想来实现的。我对该题的意图的理解是对于字符数较多的行,每隔特定列数(假设10个列)就必须另作一行,如果在特定列数的字符串中包含有空格,那么特定列数的字符串又必须被划分为两行,如果特定列数的字符串的起始字符就是空格的话,那么这个特定列数的字符串就被当作完整的一行,就不用再次二次划分了。这里要注意的这里划分的依据是列数,因此是 \ t \backslash t \t需要做特殊处理。
/*********************************************************************
Mr Dearman's code assumes that there will be at least one blank before
the 'Fold-point". Since this assumption is unfounded, his code will
fail on the first long line. In addition, he fails to initialize a
variable 'spaceholder' that he subsequently uses as an array index.
I hope this is a better algorithm.
-- Pilcrow
*********************************************************************/
#include <stdio.h>#define MAXLINE (1000) /* input line max */
#define LINEFOLD (10) /* fold point max */
#define TABLEN (8)char line[MAXLINE+1];
char fold_segment[MAXLINE+1];int getline(void);int main(void)
{int space_spot, f_move, col, lapse;int len; /* len is len of input line or segment still unfolded */int first_space; /* index of leftmost space from the input line or left segment start */while((len = getline()) > 0) { while(len){ if(len > LINEFOLD) { /* folding needed */first_space = 0; /* fold here if no spaces *//* find the first space from the input line or left segment start */for(space_spot = 0; space_spot < LINEFOLD; space_spot++) {if(line[space_spot] == ' ') {first_space = space_spot;break;}}if(first_space==0){first_space=LINEFOLD-1; }/* format & print segment before first space */for(f_move=0; f_move <= first_space; ++f_move)fold_segment[f_move] = line[f_move];fold_segment[f_move] = '\0';/* terminate new line */puts(fold_segment); /* and output it */putchar('\n');/* collapse input line to eliminate segment printed */for(col=0, lapse = f_move; lapse <= len; ++col, ++lapse)line[col] = line[lapse];len -= (first_space+1); /* adjust remaining line length */ }else{ int l;for(l=0; line[l] != '\0'; l++); /* homegrown strlen */if(l > 0)puts(line);/* short segment out */len = 0; /* force more input */}}}return 0;
}int getline(void)
{int c=0;int i=0;int index=0; int nbs=0;for(index = 0; index < MAXLINE && (c=getchar()) != EOF && c != '\n';){if(c=='\t'){ nbs = TABLEN-((index)%TABLEN);for(i=0;i<nbs;i++){line[index]=' ';index++;if(index >= MAXLINE)break; }}else{line[index]=c; index++;}}if(c == '\n') {line[index] = c; ++index;}line[index] = '\0'; return index;
}
E x c e r c i s e 1 − 23 Excercise\quad 1-23 Excercise1−23:如果每一行的开头是两个正斜杠 / / // //的话那么这一行也会被注释掉,但是下面的代码没有考虑这种注释操作。这里的程序也对字符串常量和转义字符做了特殊的代码处理。
#include <stdio.h>/* author: Daniel Schmidt Silva *//* remove comments from C sources */#define YES (1)
#define NO (!YES)int main()
{/* c is the current character, c_prev is the previous one and c_pprev the one before c_prev */int c, c_prev='\0', c_pprev = '\0', is_comment = NO, is_string = NO, closing_symbol;while ((c = getchar()) != EOF){if (!is_comment){/* fix the slash if it is not a comment */if (!is_string && c_prev == '/' && c != '*' && c_pprev != '*')putchar('/');/* print the char if it is not the begining of a comment */if (is_string || (c != '/' && (c != '*' || c_prev != '/')))putchar(c);}/* closing the comment */if (is_comment && c == '/' && c_prev == '*')is_comment = NO;/* begining the comment */else if (!is_comment && !is_string && c == '*' && c_prev == '/')is_comment = YES;/* closing the string or character, handles escape sequences \' and \\' */else if (is_string && c == closing_symbol && (c_prev != '\\' || c_pprev == '\\'))is_string = NO;/* begining the string or character */else if (!is_string && !is_comment && (c == '"' || c == '\'')){is_string = YES;closing_symbol = c;}c_pprev = c_prev;c_prev = c;}return 0;
}
E x c e r c i s e 1 − 24 Excercise\quad 1-24 Excercise1−24:。
/* 1-24.c */#include <stdio.h>
#include <stdlib.h>#define MAX_STACK 1024enum
{CODE, /* nothing of the following */COMMENT, /* inside a comment */QUOTE1, /* inside '' */QUOTE2 /* inside "" */
};int main(void)
{int ch;int state = CODE;char stack[MAX_STACK];size_t top = 0; /* points to the top of the stack :-) */size_t line = 1;int error = 0; /* for ok-message */while ((ch = getchar()) != EOF){if (ch == '\n'){line++;}switch (state){case CODE:if (ch == '\''){state = QUOTE1;}else if (ch == '"'){state = QUOTE2;}else if (ch == '/'){int second = getchar();if (second == '*'){state = COMMENT;}else{ungetc(second, stdin);}}else if (ch == '(' || ch == '[' || ch == '{'){if (top < MAX_STACK){stack[top++] = ch;}else{printf("Stack too small!\n");return EXIT_FAILURE; /* exit gracefully :-) */}}else if (ch == ')' || ch == ']' || ch == '}'){if (top == 0) /* found closing brace but stack is empty */{printf("Line %lu: Closing '%c' found without ""counterpart.\n", (unsigned long)line, ch);error = 1;}else{char open = stack[--top];if ((ch == ')' && open != '(') ||(ch == ']' && open != '[') ||(ch == '}' && open != '{')){printf("Line %lu: Closing '%c' does not match ""opening '%c'.\n", (unsigned long)line, ch, open);error = 1;}}}break;case COMMENT:if (ch == '*'){int second = getchar();if (second == '/'){state = CODE;}else{ungetc(second, stdin);}}break;case QUOTE1:if (ch == '\\'){(void)getchar(); /* an escaped char inside '' throw it away */}else if (ch == '\''){state = CODE;}break;case QUOTE2:if (ch == '\\'){(void)getchar(); /* an escaped char inside "" throw it away */}else if (ch == '"'){state = CODE;}break;}}if (state == COMMENT){printf("Code ends inside comment!\n");}else if (state == QUOTE1){printf("Code ends inside single quotes!\n");}else if (state == QUOTE2){printf("Code ends inside double quotes!\n");}else if (top == 0 && error == 0){printf("Code seems to be ok.\n");}if (top > 0) /* still something in the stack */{size_t i;for (i = 0; i < top; i++){printf("Opening '%c' found without counterpart.\n", stack[i]);}}return 0;
}