自言自语
1.1. getchar() & scanf()
C
程序把输入作为传入的字节流。
getchar()
函数把每个字符解释成一个字符编码。
- 用于读取每个字符,包括空格、制表符和换行符
scanf()
函数以同样的方式看待输入,但是根据转换说明
,它可以把字符输入转换成数值。
- 在读取数字时则会跳过空格、制表符和换行符
- 返回成功读取项的个数
1.2. 重定向
重定向输入
由平常的键盘输入变为了文件来作为输入。
- 符号:
<
- 比如:
echo_eof < words.txt
- 注意:
<
两侧的空格是可选的,有些系统支持,有的则不支持。 - 其中:
echo_eof
是可执行文件,words.txt
是文本文件。
重定向输出
是让程序的输出放到文件文件而不在是显示屏。
- 符号:
>
- 比如:
echo_eof > out_words.txt
- 注意:
>
两侧的空格是可选的,有些系统支持,有的则不支持。 - 其中:
echo_eof
是可执行文件,out_words.txt.txt
是文本文件。
重定向
的规则:
- 重定向运算符连接一个
可执行
程序和一个数据文件,不能用于连接一个数据文件和另外一个数据文件,也不能连接一个程序和另一个程序。 - 使用重定向运算符
不能
读取多个文件的输入,也不能
把输出定向至多个文件。
>>
此运算符可以把数据添加到现有文件的末尾
|
此运算符则是把一个文件的输出连接到另一个文件的输入。
1.3. 文件结尾
文件结尾
的判断由两种方式:
- 在文件末尾放一个特殊标记符来标记文件结尾。(例如:Ctrl + Z)
- 存储文件大小的信息。比如文件有3000字节,程序读到3000字节是就到达文件结尾。
在C语言中,用getchar()
函数读取文件检测到文件结尾时将返回一个特殊的值,即:EOF(End Of File)
scanf()
函数检测到文件结尾时也返回EOF
。
EOF
定义在stdio.h
头文件中:#define EOF -1
为什么是-1
呢?因为getchar()
函数的返回值通常介于0 ~ 127
之间,这些值对应标准字符集。如果系统能识别扩展字符集,该函数的返回值可能在0 ~ 255
之间。无论哪种清况,-1
都不对应任何字符,所有该值可以用于标记文件结尾。
EOF
是一个值,标志着检测到文件结尾,并不是在文件中找得到的符号。
1.4. 缓冲区
无缓冲输入
: 就是你输入的任何可见的字符,都会立马显示给你看见。(比如:HHeelloo OOKKffiinnee
)
缓冲输入
: 在用户按下Enter键之前不会重复打印刚输入的字符。
用户的输入被收集并存储在一个被称为缓冲区buffer
的临时存储区,只有当用户按下Enter键之后,程序才可以使用用户输入的字符。
为什么需要缓冲区
呢?有两个原因:
- 节约时间:把若干个字符作为一个块进行传输肯定比每个字符都单独传输效率高,时间更短。
- 修正错误:如果用户输入错误,可以直接通过键盘修正错误。
缓冲分为两类:
- 完全缓冲I/O:当缓冲区被填满时才刷新缓冲区(内容被发送到目的地),通常出现在文件输入中
- 行缓冲I/O:在出现换行时才刷新缓冲区。比如键盘输入,按下Enter键就刷新缓冲区
缓冲区的大小取决于系统,常见大小是512字节和4096字节。
getche()
:用于回显
无缓冲输入
getch()
:用于无回显
无缓冲输入
都在conio.h
头文件中。
ONE
下面的一些程序要求输入以EOF终止。如果你的操作系统很难或根本无法使用重定向,
请使用一些其他的测试来终止输入,如读到&字符时停止。
1.设计一个程序,统计在读到文件结尾之前读取的字符数。
2.编写一个程序,在遇到EOF之前,把输入作为字符流读取。程序要打印每个输入的字符及其相应
的ASCII十进制值。注意,在ASCII序列中,空格字符前面的字符都是非打印字符,要特殊处理
这些字符。如果非打印字符是换行符或制表符,则分别打印\n或\t。否则,使用控制字符表示法
例如,ASCII 的1是Ctrl+A,可显示为^A。注意,A的ASCII值是Ctrl+A的值加上64。其他
打印字符也有类似的关系。除每次遇到换行符打印新的-行之外,每行打印10对值。(注意:不同
的操作系统其控制字符可能不同。)
#include <stdio.h>
void count(void);
void print_ascii();
int main()
{
count();
return 0;
}
void count(void)
{
int ch;
int cnt = 0;
int line_num = 1;
char prev = '\n';
unsigned long character = 0;
unsigned long line = 0;
while((ch = getchar()) != EOF)
{
character++;
if(prev == '\n')
printf("%04d: ", line_num++);
prev = ch;
if(ch == '\n')
line++;
if(cnt == 10)
{
printf("\n ");
cnt = 0;
}
cnt++;
switch(ch)
{
case '\n':
printf("'\\n'-%-6d \n", ch);
cnt = 0;
break;
case '\t':
printf("'\\t'-%-6d ", ch);
break;
default:
printf("'%c'-%-6d ", ch, ch);
}
}
if(prev != '\n')
line++;
printf("\n++++++++ D O N E ! ++++++++++\n");
printf("This file have %-4lu characters.\n", character);
printf("This file have %-4lu lines.\n", line);
printf("++++++++ E N D ! ++++++++++\n");
}
/*
* c.txt:
* [[ Hello OKfine. ]]
* [[Nice to meet u.]]
*/
book@OKfine:~/c_primer_plus/ch8/ex01$ ./test < c.txt
0001: '['-91 '['-91 ' '-32 'H'-72 'e'-101 'l'-108 'l'-108 'o'-111 ' '-32 'O'-79
'K'-75 'f'