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

getchar的返回值

这样的代码有什么问题:

char c;

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

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

过早第结束输入。

feof函数的使用

为什么这些代码最后一行复制了两遍?

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

#define MAXLINE 256

int main(void)
{
        char buf[MAXLINE];
        FILE* fp = fopen("1.txt","r");
        while(!feof(fp)){
                fgets(buf,MAXLINE,fp);
                printf("%s",buf);
        }
        return 0;
}

在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格式,例如输出某种类型的长度,可以使用:

printf("%lu", (unsigned long)sizeof(thetype));

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

可以使用sscanf,例如123ABC5.678,可以用”%d%3s%f“读取。

#include <stdio.h>

int main(void)
{
        char str[] = "1234ABC5.678";
        int i;
        float f;
        char s[10];
        sscanf(str,"%d%3s%f",&i,s,&f);
        printf("%d,%s,%f\n",i,s,f);
        return 0;
}

运行结果:

1234,ABC,5.678000

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

下面的代码:

int n;
scanf("%d\n",&n);
printf("%d\n",n);

为什么要多输入一行才返回,为什么?

\n在scanf格式中不表示等待换行符,而是读取并放弃连续的空白字符。因此”%d\n“中的\n会让scanf读到非空白字符为止,

而它可能需要读到下一行才能找到这个非空白字符。应该去掉\n,仅适用%d即可。

scanf和gets一起用的副作用

int n;
char str[80];

scanf("%d",&n);
gets(str);
printf("%d,%s\n",n, str);

以上的代码,好像编译器跳过了gets的调用。

如果你向问题中的程序输入两行:

42

a string

scanf会读取42,但却不会读到紧接其后的换行符,换行符会保留在输入流中,然后被gets读取,后者会读取一个空行,二

第二行的字符串根本不会被读取。

《你必须知道的495个C语言问题》笔记--标准输入输出,布布扣,bubuko.com

时间: 2024-11-03 01:19:29

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

《你必须知道的495个C语言问题》笔记--库函数

怎样把数字转为字符串(与atoi相反)?有itoa函数吗? 用sprintf就可以了: sprintf(string, "%d", number); 同理,也可以同sprintf把long型或浮点型转换成字符串(使用%ld或%f),也就是说,可以把sprintf看成是atol或者atof的 反函数. 怎样在日期上加n天?怎样取得两个日期的时间间隔? 第一个问题,mktime接受没有规范话的日期,所以可以用一个日期的struct tm结构,直接在tm_mday域上进行加减,然后 调用mk

《你必须知道的495个C语言问题》笔记--杂项

如何进行移位操作? 因为左移操作(<<)不会导致符号位出现缺位,不考虑符号位,低位补0即可.所以对于无符号和有符号数来说,均为逻辑左移. 右移操作(>>)会涉及到符号位出现缺位的问题,所以在有符号数的右移操作时要考虑符号位怎么补的问题.对于无符号数来说, 最左侧补0,即逻辑右移:对于有符号来说,最左侧补符号位,即符号右移. 实践: #include <stdio.h> int main(void) { unsigned rui; int ri; unsigned int

你必须知道的495个C语言问题,学习体会五

本文是 你必须知道的495个C语言问题 系列的第五篇,主要还是来了解下字符和字符串相关的东西,同时也会涉及内存相关的知识. 一般来说,字符串以及字符的处理都是编程语言中的常客,在C语言中,我们被给予了很好的灵活性,但是同时字符也成了最诡秘的处理单元. 在指针的内容里,我基本上讲解了字符串和字符数组的差异,所以这里就不再赘述了. 我们知道字符的英语翻译是character,这也是为什么字符类型为char的原因,我们使用单引号''来标示一个字符而使用双引号""来标示字符串.实际上,在C语言

《你必须知道的495个C语言问题》笔记--数组和指针

一.如何动态分配多维数组? 1.分配一个指针数组,然后把每个指针初始化为动态分配的行 代码如下: int **array = (int **)malloc(ROW * sizeof(int*)); int i = 0; for(i=0; i<ROW; i++){ array[i] = (int *)malloc(COL * sizeof(int)); } 2.让数组的内容连续,但在后来重新分配行. 代码如下: int **array = (int**)malloc(ROW * sizeof(in

《你必须知道的495个C语言问题》笔记--表达式

1.怎样才能避免这些未定义的求值顺序问题呢? 有几条简单的规则: 1.确保一个表达式最多只修改一个对象:一个简单变量.一个数组或者一个指针指向的位置. 2.如果一个对象在一个表达式中出现一次以上而且在表达式中被修改,则要确保对该对象的所有读访问都被用于计算它的 最终值.这条规则允许表达式i=i+1,尽管i出现了两次而且被修改了,但对i的旧值读取是用于计算i的新值. 3.如果想破坏第一条规则,就要确保修改的对象互不相同.同时,尽量限制到最多2至3个修改并参照下面例子的风格.在 这条规则下,c=*p

《你必须知道的495个C语言问题》读书笔记之第2章:结构、联合和枚举

1. Q:下面两个声明有何区别? struct x1 {...}; typedef struct {...} x2; A:第一种形式声明了一个“结构标签”,第2种形式声明了一个“类型定义”.前者在声明结构的实例时必须使用struct关键字,如"struct x1 a;",后者则不需要使用struct关键字,如"x2 b;".但这个区别在C++编译器和某些模仿C++的C编译器中已经完全不存在了,在C++中结构标签在本质上都自动声明为类型定义. 2. Q:在C语言中是否

《你必须知道的495个C语言问题》读书笔记之第4-7章:指针

1. Q:为什么我不能对void *指针进行算术运算? A:因为编译器不知道所值对象的大小,而指针的算法运算总是基于所指对象的大小的. 2. Q:C语言可以“按引用传参”吗? A:不可以.严格来说,C语言总是按值传参,你可以模拟按引用传参,定义接受指针的函数,然后在调用时使用&操作符.但C没有任何真正等同于按引用传参的东西. 3. Q:怎样在整型和指针之间进行转换?能否暂时把整数放入指针变量,或者相反? A:C标准中规定整数与指针之间的相互转换是实现定义的,因此没有了指针和整数之间无法修改就相互

《你必须知道的495个C语言问题》笔记

1.10 对于没有初始化的变量的初始值可以作怎样的假定?如果一个全局变量初始值为 "零", 它可否作为空指针或浮点零? 答: 具有 "静态" 生存期的未初始化变量 (即, 在函数外声明的变量和有静态存储类型的变量) 可以确保初始值为零, 就像程序员键入了 "=0" 一样. 因此, 这些变量如果是指针会被初始化为正确的空指针, 如果是浮点数会被初始化为 0.0 (或正确的类型, 参见第 5 章).具有 "自动" 生存期的变量 (

C#刨根究底:《你必须知道的.NET》读书笔记系列

一.此书到底何方神圣? <你必须知道的.NET>来自于微软MVP-王涛(网名:AnyTao,博客园大牛之一,其博客地址为:http://anytao.cnblogs.com/)的最新技术心得和感悟,将技术问题以生动易懂的语言展开,层层深入,以例说理.全书主要,包括了.NET基础知识及其深度分析,以.NET Framework和CLR研究为核心展开.NET本质论述,涵盖了.NET基本知识几乎所有的重点内容.全书分为5个部分,第1部分讲述.NET与面向对象,从底层实现角度分析了.NET如何实现面向