《你必须知道的495个C语言问题》笔记--标准输入输出

来源:互联网 发布:阿里云注销 编辑:程序博客网 时间:2024/05/01 13:27

getchar的返回值

这样的代码有什么问题:

char c;

while((c = getchar()) != EOF)....

getchar返回值变量必须是int型。因为EOF通常定义为-1,二十进制为255的字符会被符号扩展,和EOF比较时会相等,从而

过早第结束输入。


feof函数的使用

为什么这些代码最后一行复制了两遍?
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2. #include <unistd.h>  
  3. #include <fcntl.h>  
  4.   
  5. #define MAXLINE 256  
  6.   
  7. int main(void)  
  8. {  
  9.         char buf[MAXLINE];  
  10.         FILE* fp = fopen("1.txt","r");  
  11.         while(!feof(fp)){  
  12.                 fgets(buf,MAXLINE,fp);  
  13.                 printf("%s",buf);  
  14.         }  
  15.         return 0;  
  16. }  
在c语言中只有输入例程试图读取并失败以后才能得到EOF,也就是说fgets读到最后一行内容,此时调用feof时,feof并
不能返回非零值(即检测不到EOF),while循环继续执行,fgets执行后,返回值为NULL,但是buf还是上次读取的内容,
所以此时printf再次打印了最后一行内容。等到再次执行feof时,此时feof函数检测到EOF,跳出while循环。
所以我们的可以修改成一下来避免上述的问题:
if(fgets(buf, MAXLINE, fp) != NULL){
printf("%s",buf);
}
其实feof函数都是在fgets失败以后才使用的,应为该函数出错还是出错还是达到文件结尾都返回NULL,为了
区分这两种情况,必须调用ferror或者feof函数。


有人说不能在printf中使用%lf,为什么printf中用%f输出double型,而scanf却用%lf呢?

printf的%f说明符既可以输出float型又可以输出double型。根据默认参数提升规则,float型会被提升为double型,因此
printf只会看到双精度数。
独有scanf,情况就完全不一样了,它接收指针,这里没有类似的类型提升,向float存储和向double存储大小不一样,因此
scanf区分%f和%lf。

对于size_t那样的类型定义,到底是long还是其他类型,应该使用什么样的prinf格式?

把那个值转换为一个已知长度够大的类型,然后使用与之对应的printf格式,例如输出某种类型的长度,可以使用:
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. printf("%lu", (unsigned long)sizeof(thetype));  

怎样从特定格式的字符串中读取数据?

可以使用sscanf,例如123ABC5.678,可以用”%d%3s%f“读取。
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2.   
  3. int main(void)  
  4. {  
  5.         char str[] = "1234ABC5.678";  
  6.         int i;  
  7.         float f;  
  8.         char s[10];  
  9.         sscanf(str,"%d%3s%f",&i,s,&f);  
  10.         printf("%d,%s,%f\n",i,s,f);  
  11.         return 0;  
  12. }  
运行结果:
1234,ABC,5.678000

用"%d\n"调用scanf的问题

下面的代码:
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int n;  
  2. scanf("%d\n",&n);  
  3. printf("%d\n",n);  
为什么要多输入一行才返回,为什么?
\n在scanf格式中不表示等待换行符,而是读取并放弃连续的空白字符。因此”%d\n“中的\n会让scanf读到非空白字符为止,
而它可能需要读到下一行才能找到这个非空白字符。应该去掉\n,仅适用%d即可。

scanf和gets一起用的副作用

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int n;  
  2. char str[80];  
  3.   
  4. scanf("%d",&n);  
  5. gets(str);  
  6. printf("%d,%s\n",n, str);  
以上的代码,好像编译器跳过了gets的调用。

如果你向问题中的程序输入两行:
42
a string
scanf会读取42,但却不会读到紧接其后的换行符,换行符会保留在输入流中,然后被gets读取,后者会读取一个空行,二
第二行的字符串根本不会被读取。
0 0