第一章 导言
1.5 字符输入/输出
- 基本形式
- 字符流:不太清楚具体定义;
- 文本流:由多行字符构成的字符序列,每行字符由0个或多个字符组成,行末是换行符;
- 基本函数:本章中使用标准c库中提供的一次读写一个字符的函数实现输入输出功能
- getchar():从输入的文本流中获取下一个字符。由于从文本流中获取字符,故得到的字符还包含换行符。
- putchar(c):将字符打印出来
1.5.1 文件复制
核心代码:将输入复制到输出(具体见上一篇文章)
1.5.2 字符计数
核心代码:统计输入文本流的字符个数,主要介绍自增运算符
#include <stdio.h>
int main() {
long nc = 0;
while (getchar() != EOF)
++nc;
printf("nc = %ld\n", nc);
return 0;
}
#include <stdio.h>
int main() {
long nc;
for (nc = 0; getchar() != EOF; ++nc);
printf("nc = %ld\n", nc);
return 0;
}
运行结果(由于getchar函数统计的是文本流中的字符,故其中包含换行符)
1.5.3 行计数
核心代码:统计文本流中的换行符个数,主要介绍条件判断语句
#include <stdio.h>
int main() {
int nc, c;
nc = 0;
while ((c = getchar()) != EOF)
// 其中单引号中的\n,是字符常量,实际上就是一串整型数字,写成字符的形式便于理解
if (c == '\n')
++nc;
printf("new line is %d\n", nc);
printf("'\\n' is %d\n", '\n');
return 0;
}
运行结果:换行符\n实际上也是一个整型数字(根据ascii码进行转换的)
练习1-8 编写一个统计空格、制表符与换行符个数的程序
主要思路:还是增加对字符的判断
#include <stdio.h>
int main() {
int c;
int tab = 0, newline = 0, space = 0;
while ((c = getchar()) != EOF) {
if (c == ' ') {
++space;
} else if (c == '\n') {
++newline;
} else if (c == '\t') {
++tab;
}
}
printf("new line is %d\n", newline);
printf("tab is %d\n", tab);
printf("space is %d\n", space);
return 0;
}
运行结果
练习1-9 编写一个将输入复制到输出的程序,并将其中连续的多个空格用一个空格代替
主要思路:使用space变量来记录putchar之后当前字符的状态
- space = 0:非空格
- space = 1 :第一个空格
- space > 1:第2、3、...、n个空格(n > 1)
所以当space>=1时,已经打印出一个空格了,无需再打印多余的空格
#include <stdio.h>
int main() {
int c, space = 0;
while ((c = getchar()) != EOF) {
if (c != ' ') {
// 若该字符非空格,则将space初始化
space = 0;
putchar(c);
} else if (space == 0) {
// 首个空格需要打印,后面的空格不打印
putchar(c);
space++;
}
}
return 0;
}
运行结果
练习1-10 编写一个将输入复制到输出的程序,并将其中的制表符替换成\t,将回退符替换成\b,将反斜杠替换成\\。这样可以将制表符和回退符以可见的方式显示出来
主要思路:在输出时判断字符是否上述特殊字符,如果是则进行特殊处理
#include <stdio.h>
int main() {
int c;
while ((c = getchar()) != EOF) {
if (c == '\t') {
printf("\\t");
} else if (c == '\b') {
printf("\\b");
} else if (c == '\\') {
printf("\\\\");
} else {
putchar(c);
}
}
return 0;
}
运行结果(mac中回退符使用control + delete模拟)
1.5.4 单词计数
核心代码:统计文本流中的单词、换行符、字符个数,主要介绍复杂条件判断语句
这里对单词的定义比较宽泛,它是任何其中不包含空格、制表符或换行符的字符序列
#include <stdio.h>
#define IN 1 // 在单词内
#define OUT 0 // 在单词外
int main() {
int c;
int nl = 0, nc = 0, nw = 0;
int state = OUT;
while ((c = getchar()) != EOF) {
++nc;
if (c == '\n') {
++nl;
}
if (c == '\n' || c == '\t' || c == ' ')
state = OUT;
else if (state == OUT) {
state = IN;
++nw;
}
}
printf("%d, %d, %d\n", nc, nl, nw);
return 0;
}
运行结果
不太懂-练习1-11 你准备如何测试单词计数程序?如果程序中存在某种错误,那么什么样的输入最可能发现这类错误呢?
单词计数程序中共包含三种判断逻辑:获取输入字符、判断换行符、判断单词。根据实现方式进行以下测试用例设计
练习1-12 编写一个程序,以每行一个单词的形式打印其输入
主要思路:识别到字符为换行符、制表符或者空格时,则直接打印换行符;否则打印字符本身
#include <stdio.h>
int main() {
int c;
while ((c = getchar()) != EOF) {
if (c == '\n' || c == '\t' || c == ' ') {
printf("\n");
} else {
putchar(c);
}
}
return 0;
}
运行结果