1.5 字符输入/输出
1.文件复制
1 #include<stdio.h> 2 3 int main(void) 4 { 5 int c; 6 7 c = getchar(); 8 while (c != EOF) { 9 putchar(c); 10 c = getchar(); 11 } 12 13 return 0; 14 }
按ctrl+Z可以结束程序。字符在机器内部都是以位模式存储的。故int也可以用于存储字符数据。
原文说:我们在声明变量c的时候,必须让它大到足以存放getchar函数返回的任何值。这里之所以不把c声明成char类型,是因为它必须足够大,除了能存储任何可能的字符外还要能存储文件结束符EOF。因此,我们将c声明成int类型。
测试的时候,没发现int和char类型有什么区别,等待进一步测试。
精炼版本
1 #include<stdio.h> 2 3 int main(void) 4 { 5 int c; 6 7 while ((c = getchar()) != EOF) 8 putchar(c); 9 10 return 0; 11 }
练习1-6 验证表达式 getchar() != EOF 的值是0还是1。
练习1-7 编写一个打印 EOF 值的程序。
1 #include<stdio.h> 2 3 int main(void) 4 { 5 int c; 6 7 c = (getchar() != EOF); 8 printf("%d\n", c); 9 10 return 0; 11 }
2 字符计数
统计数字的字符数
1 #include<stdio.h> 2 3 /*统计输入的字符数; 版本1 */ 4 5 int main(void) 6 { 7 long nc; 8 9 nc = 0; 10 while(getchar() != EOF) 11 ++nc; 12 printf("%ld\n", nc); 13 14 return 0; 15 }
for版本
1 #include<stdio.h> 2 3 /*统计输入的字符数; 版本2 */ 4 5 int main(void) 6 { 7 long nc; 8 9 for(nc=0; getchar() != EOF; ++nc) 10 ; 11 printf("%ld\n", nc); 12 13 return 0; 14 }
3. 行计数
1 #include<stdio.h> 2 3 /*统计输入中行数 */ 4 5 int main(void) 6 { 7 int c, nl; 8 9 nl = 0; 10 while( (c = getchar()) != EOF ) 11 if ( c == '\n') 12 ++nl; 13 printf("%d\n", nl); 14 15 return 0; 16 }
练习1-8 编写一个统计空格、制表符与换行符个数的程序。
1
#include<stdio.h>
int main(void)
{
int c;
int old; /*记录上一个字符*/
old = 0;
while( (c = getchar()) != EOF ){
if( (c == ' ') && (old == ' ')) /*这次输入的字符和上次输入的字符都是空格*/
;
else
putchar(c);
old = c;
}
return 0;
}
练习1-9 编写一个将输入复制到输出的程序,并将其中连续的多个空格用一个空格代替。
1 #include<stdio.h> 2 3 int main(void) 4 { 5 int c; 6 int old; /*记录上一个字符*/ 7 8 old = 0; 9 while( (c = getchar()) != EOF ){ 10 if( (c == ' ') && (old == ' ')) /*这次输入的字符和上次输入的字符都是空格*/ 11 ; 12 else 13 putchar(c); 14 old = c; 15 } 16 17 18 return 0; 19 }
练习1-10 编写一个将输入复制到输出的程序,并将其中的制表符替换为\t,把回退符替换为\b,把反斜杠替换为\\。这样可以将制表符和回退符以可见的方式显示出来。
1 #include<stdio.h> 2 3 int main(void) 4 { 5 int c; 6 7 while( (c = getchar()) != EOF ){ 8 if(c == '\t') 9 printf("\\t"); 10 else if(c == '\b') 11 printf("\\b"); 12 else if (c == '\\') 13 printf("\\\\"); 14 else 15 putchar(c); 16 } 17 18 return 0; 19 }
回退符的事情,没搞清楚。
4 单词计数
1 #include<stdio.h> 2 #define IN 1 3 #define OUT 0 4 5 int main(void) 6 { 7 int c, nl, nw, nc, state; 8 9 state = OUT; 10 nl = nw = nc = 0; 11 while((c = getchar()) != EOF) { 12 ++nc; 13 if(c == '\n') 14 ++nl; 15 if(c == ' ' || c == '\n' || c == '\t') 16 state = OUT; 17 else if (state == OUT) { 18 state = IN; 19 ++nw; 20 } 21 } 22 printf("%d %d %d\n", nl, nw, nc); 23 24 return 0; 25 }
练习1-11 你准备如何测试单词计数程序?如果程序中存在某种错误,那么什么样的输入最可能发现这类错误呢?
单词计数程序的测试工作首先要从没有任何输入的情况开始。
此时,该程序的输出结果应该是“ 0 0 0 ”,即零行、零单词、零字符。
接下来测试输入单字符单词、两字符单词、两个单字符单词。
总之是测试一些边界条件,比如:
1.没有输入
2.没有单词(只有换行)
3.没有单词(只有空格、制表符和换行符)
4.每个单词各占一行
5.单词出现于文本行行首的情况
6.单词出现于一串空格之后的情况
练习1-12 编写一个程序,以每行一个单词的形式打印其输入。
1 #include<stdio.h> 2 #define IN 1 3 #define OUT 0 4 5 int main(void) 6 { 7 int c, state; 8 9 state = OUT; 10 while((c = getchar()) != EOF) { 11 if(c == ' ' || c == '\n' || c == '\t') 12 state = OUT; 13 else if (state == OUT) { 14 state = IN; 15 printf("\n"); 16 } 17 else 18 putchar(c); 19 } 20 21 return 0; 22 }
测试问题:首先会先打印一个空行,因为我是用单词计数程序改的,第一个单词出现的时候,就输出了一个回车。