参考程序
内容参考Dennis M.Rithchie编写的《C程序设计语言 第二版》
文件复制
#include<stdio.h>
/*将输入复制到输出*/
int main()
{
int ch;
while((c=getchar())!=EOF)
putchar(ch);
}
int c: char类型专门用于存储字符型数据,当然任何整型(int)也可用于存储字符型数据。这里之所以不把c声明成char类型,是因为它必须足够大,除了能存储任何可能的字符外还要能存储文件结束符EOF
EOF:文件结束符,Windows下为组合键Ctrl+Z, Unix/Linux下为组合键Ctrl+D。
从运行结果上看,getchar()并不是你每按一次键就执行一次,而是在键入回车键后整体运行的结果。
博主可乐’给出了这种现象的解释:键盘输入的字符都存到缓冲区内,一旦键入回车,getchar()就进入缓冲区读取字符,一次只返回第一个字符作为getchar函数的值,如果有循环或足够多的getchar语句,就会依次读出缓冲区内的所有字符直到’\n’。
整个过程为
1.abcdefg 键入进入缓冲区
2.abcdefg+enter 键入回车 getchar()进入缓冲区读取字符
3.getchar()每读取缓冲区一个字符,while判断为真,putchar()输出输出该字符,回车也被读取输出。
单词计数
#include<stdio.h>
#define IN 1 /*在单词内*/
#define OUT 0 /*在单词外*/
int main()
{
int ch,nw,nl,nc,state;
state=OUT;
while((ch=getchar())!=EOF){
++nc;
if(ch=='\n')
++nl;
if(ch==' '||ch=='\n'||ch=='\t')
state=OUT;
if(state==OUT){
state=IN;
++nw;
}
}
printf("%d %d %d\n",nl,nw,nc);
}
读取字符数组设计getline()
#include<stdio.h>
/*按行读取字符数组,最后两位留为回车和空*/
#define MAXLINE 4 /*允许的输入行的最大长度*/
int main()
{
int ch,i;
for(i=0;i<MALINE-1 && (ch=getchar())!=EOF && ch!='\n';++i)
s[i]=ch;
if(ch='\n'){
s[i]=ch;
++i;
}
s[i]='\0';
printf('%s %d',s,i);
}
设置字符数组最大长度为4
输入为ab+回车
1.ab键入缓冲区
2.ab+enter 键入回车,getchar()进入缓冲区读取字符,for循环开始执行ch=getchar()
3.getchar()读取 b后 i=2
4.getchar()读取回车ch=’\n’,i=2,跳出循环
5.if(ch==’\n’)条件成立 s[2]=ch=’\n’ i=3
6.s[3]=’\0’
7.最终结果 s=[a b ‘\n’ ‘\0’]
打印时 a b+回车(转至次行)空+3(i)
输入为abcdef+回车
1.abcdef键入缓冲区
2.abcedf+enter 键入回车 for循环中getchar()进入缓冲区读取字符,for循环开始执行ch=getchar()
3.getchar()读取c至ch后 c的内容被存入s[2] 之后 i=3
4.此时 ch=‘c’不等于’\n’
5.s[3]=’\0’
6.最终结果 s=[a b c ‘\0’]
打印时 a b c 空 3
getline()函数
int getline(char s[], int lim)
{
int ch,i;
for(i=0;i<lim-1 && (ch=getchar())!=EOF && ch!='\n';++i)
s[i]=ch; /*回车会被读入c但是不会存入s[i]*/
if(ch=='\n'){
s[i]='\n';
++i;
}
s[i]='\0';
}
关于Ctrl+Z
这里引用博主乌托对Ctrl+Z的理解
Ctrl+Z的ASCII码值
#include<stdio.h>
int main()
{
int c;
while((c=getchar())!=EOF)
printf('%c %d\n',c,c);
}
输入ab ctrl+z
可见在终端windows系统中ctrl+z的ASCII值为26,键入ctrl+z其实输入的是一个ASCII值为26的字符。
对于单词计数程序
#include<stdio.h>
#define IN 1 /*在单词内*/
#define OUT 0 /*在单词外*/
int main()
{
int ch,nw,nl,nc,state;
state=OUT;
while((ch=getchar())!=EOF){
++nc;
if(ch=='\n')
++nl;
if(ch==' '||ch=='\n'||ch=='\t')
state=OUT;
if(state==OUT){
state=IN;
++nw;
}
}
printf("%d %d %d\n",nl,nw,nc);
}
Ctrl+Z前没有其他字符
输入abcd+回车+(ctrl+z+回车)
而当ctrl+z前面没有其他字符时,系统此时会检测到ctrl+z,此时getchar()就会读取失败,返回EOF。所以如果需要终端输入ctrl+z终止输入,需要另起一行输入ctrl+z才行。
Ctrl+Z前有其他字符
输入abcd+(ctrl+z+回车)+回车+(ctrl+z+回车)
当ctrl+z前面有其他字符时,此时系统认为缓冲区中有可读的数据,系统不会检测ctrl+z(因为有要读的数据,还不能认为到了流的末尾)
在while循环中添加显示
printf("%c",c);
输入abcd+(ctrl+z+回车),显示后+(ctrl+z+回车)
1.对于前面有数据的^z getchar()将其当做ASCII码为26的字符读入ch,显示为‘->’
2.第一个^z后的回车没有读入ch中