
本文共 2946 字,大约阅读时间需要 9 分钟。
读取输入的方式
相关函数原型(从控制台获取输入,不考虑宽字符):
int scanf( const char *format, ... );int getchar(void);char *gets( char *str );char *gets_s( char *str, rsize_t n );char *fgets( char *str, int count, FILE *stream );
- scanf
- 如果解析错误,内容继续留在缓冲区供下次使用;
- 解析失败返回0,成功返回解析的参数个数,不会超过占位符个数,读到文件尾返回EOF(-1);
- 读取字符串,一次只能读取一个词,不能用scanf读取一行;
- getchar
- 可以读取到换行符;
- 常用于暂停程序,或丢弃缓冲区剩余字符;
- gets
- 读取一行,遇到换行符,直接丢弃换行符;
- 会自动在字符串末尾添加
\0
; - 返回字符串指针,读取失败返回null;
- gets_s
- 可以设置读取的字符串长度;
- 读到换行符,将换行符丢弃;
- 如果读取到最大字符数,还没有读取到换行符或文件结尾,读取并丢弃随后的输入直至遇到换行符或EOF;
- 返回字符串指针,读取失败返回null;
- c11的可选函数
- fgets
- 可以设置读取的字符串长度;
- 读到换行符不丢弃存到数组里;
- 不会自动清除行缓冲区剩余数据;
- 返回字符串指针,读取失败返回null;
scanf
该函数可以从标准输入读取内容,返回值为读取的参数个数,例如:
#includeint main(){ int seed; printf("%d\n", scanf("%d %d", &seed, &seed));}
运行程序,输入 两个整数,打印为 2,测试输入3个值仍然打印2,是因为这个"%d %d"指定了只解析两个int,多余的将留在缓冲区中,如果后面再写一个scanf,将从缓冲区中继续解析。
现在多加一个scanf
:
#includeint main(){ int seed; printf("%d\n", scanf("%d %d", &seed, &seed)); printf("%d\n", scanf("%d %d", &seed, &seed));}
case1:读取到文件尾部返回EOF
1
输出:
1-1
scanf从缓冲区中解析,返回解析成功的参数个数,因为只有一个1,所以第一个给scanf解析,第一行打印1,第二行解析的时候因读取到了文件结束表示EOF
返回-1。
case2:解析失败返回0
f
输出:
00
这说明,解析失败的内容还留在缓冲区给下次scanf用,所以两个scanf都返回的0。
因为无法解析的值会继续留在缓冲区供下次使用,所以如果是循环scanf
,程序就会跑飞,让你没有输入的机会,可以使用综上一节提供的示例测试一下,运行后直接输入f
。
case3:返回值最大为占位符个数
1 2 3 4 5 6 7
输出:
22
这表明,返回值最大是占位符的个数,剩下的内容还留在缓冲区。
综上
scanf
判断输入结束,只能在文件输入模式下利用EOF
判断,例如:
// qwer.c#includeint main(){ int a; while(scanf("%d", &a) != EOF) { printf("%d\n", a); } return 0;}
输入文件test.txt
内容:
1234
编译: gcc qwer.c -o main -std=c11
。
./main < test.txt
。 getchar
这个函数可以从输入缓冲区仅读取一个字符,返回int,后面结合fgets
使用。
gets
在读取字符串时,scanf()
和转换说明%s
只能读取一个单词,可是程序中经常要读取一整行输入。gets
函数简单易用,它读取整行输入,直到遇到换行符,然后丢弃换行符,存储其余字符,并在这些字符的末尾添加一个空字符使其成为一个c字符串。它经常和puts
函数配对使用,该函数用于显示字符串,并在末尾添加换行符。
#include#define STLEN 81int main(){ char words[STLEN]; puts("Enter a string, please."); gets(words); // 典型用法 printf("Your string twice:\n"); printf("%s\n", words); puts(words); puts("Done."); return 0;}
printf("%s\n", words);
和puts(words);
效果相同,但是编译的时候会产生警告,因为gets
读取整行输入,并不知道words
能存多少,如果输入字符串过长,会导致缓冲区溢出。
例如将STLEN
设置成5
,程序依然可以运行,尝试输入过长的数据就可能会发成溢出,最直观的就是可以看到发生段溢出后程序异常退出。
gets_s
该函数是c11才有的,且为拓展函数,使用方式除了可以设置读取的字符数之外和gets
函数用法一样。
fgets
这个函数除了可以从标准输入读取字符串之外,还可以从文件中读取,而且可以指定读取字符个数,比gets_s
更加灵活易用,利用fgets
,但是fgets
不会自动丢弃超过字符个数之外的行缓冲区数据,所以要配合getchar
将剩余的缓冲数据丢弃,否则可能造成程序运行以异常。
s_gets【自定义输入】
为满足以下几点编写自定义输入:
- 从标准输入读取数据;
- 能够指定读取字符个数;
- 丢弃换行符;
- 丢弃行缓冲区剩余数据;
char *s_gets(char *str, int n){ char *ret_var; int i = 0; ret_var = fgets(str, n, stdin); if(ret_var) { while(str[i] != '\n' && str[i] != '\0') { i++; } if(str[i] == '\n') str[i] = '\0'; else while(getchar() != '\n') continue; } return ret_var;}
使用方式
#include#define STLEN 8int main(){ char words[STLEN]; while(s_gets(words, STLEN) && words[0] != '\n') // 没有输入数据会自动退出程序 { puts(words); } return 0;}
发表评论
最新留言
关于作者
