scanf( )
字符串输入
特点:
- 键盘输入
- 回车代表输入结束
- 遇到空格结束读取
- 回车符不保存
- 若 (字符串长度<最大字节数) 则自动添加空字符在字符串结尾,否则不添加。
示例:
#include <stdio.h>
#define MAX 8
void pLoop(char *, char *);
int main(void)
{
char buf[MAX]={8,8,8,8,8,8,8,8};
scanf("%s",buf);
pLoop("%c ",buf);
return 0;
}
void pLoop(char *mode, char *arr)
{
int i;
printf("character: ");
for(i=0;i<MAX;i++)
{
printf(mode,arr[i]);
}
printf("(ASCII: ");
for(i=0;i<MAX;i++)
{
printf("%d ",arr[i]);
}
printf(")\n");
}
/*运行*/
【12345】
character: 1 2 3 4 5 (ASCII: 49 50 51 52 53 0 8 8 )
可以看到自动添加了空字符0在字符串结尾
再看一条:
/*运行*/
【12345abc】
character: 1 2 3 4 5 a b c (ASCII: 49 50 51 52 53 97 98 99 )
长度刚刚好为最大字节数的时候,空字符就没有了,如果输入再多一些,就溢出了。
所以说,只有当(字符串长度<最大字节数)才自动添加空字符在字符串结尾,
键盘输入的回车符自始至终都木有见着,就是舍弃掉了。
输入一串字符测试一下:
#include <stdio.h>
#define MAX 10
void pLoop(char *, char *);
int main(void)
{
char buf_1[MAX]={0};
char buf_2[MAX]={0};
char buf_3[MAX]={0};
char buf_4[MAX]={0};
scanf("%s",buf_1);
pLoop("%c ",buf_1);
scanf("%s",buf_2);
pLoop("%c ",buf_2);
scanf("%s",buf_3);
pLoop("%c ",buf_3);
scanf("%s",buf_4);
pLoop("%c ",buf_4);
return 0;
}
void pLoop(char *mode, char *arr)
{
int i;
printf("character: ");
for(i=0;i<MAX;i++)
{
printf(mode,arr[i]);
}
printf("(ASCII:");
for(i=0;i<MAX;i++)
{
printf("%d ",arr[i]);
}
printf(")");
printf("\n");
}
/*运行*/
【1121a b c】 //输入
character: 1 1 2 1 a (ASCII:49 49 50 49 97 0 0 0 0 0 )
character: b (ASCII:98 0 0 0 0 0 0 0 0 0 )
character: c (ASCII:99 0 0 0 0 0 0 0 0 0 )
【xixi】
character: x i x i (ASCII:120 105 120 105 0 0 0 0 0 0 )
从程序上可以看到scanf函数碰到空格就自动结束输入了,并且下一个scanf函数直接读取输入缓存区的数据,直到全部读取完毕,才能再次输入。
基于以上特点,它只适合单词输入,不适合英文语句输入。
如何避免这种影响下次输入的情况呢,有一个小方法:
scanf("%s",buf_1);
pLoop("%c ",buf_1);
while(getchar()!='\n')
continue;
scanf("%s",buf_2);
pLoop("%c ",buf_2);
while(getchar()!='\n')
continue;
scanf("%s",buf_3);
pLoop("%c ",buf_3);
while(getchar()!='\n')
continue;
scanf("%s",buf_4);
pLoop("%c ",buf_4);
while(getchar()!='\n')
continue;
/*运行*/
【1121a b c】 //输入
character: 1 1 2 1 a (ASCII:49 49 50 49 97 0 0 0 0 0 )
【b b b】
character: b (ASCII:98 0 0 0 0 0 0 0 0 0 )
【c c d】
character: c (ASCII:99 0 0 0 0 0 0 0 0 0 )
【xixi】
character: x i x i (ASCII:120 105 120 105 0 0 0 0 0 0 )
只要在下一次输入前加上
while(getchar()!='\n')
continue; //可以只保留分号
就可以清除掉未读取完的数据咯,记住这个方法,以后会有大用。
整型值输入
#include <stdio.h>
#define MAX 10
void pLoop(char *, int *);
int main(void)
{
int buf_1[MAX]={0};
int buf_2[MAX]={0};
int buf_3[MAX]={0};
int buf_4[MAX]={0};
scanf("%d",buf_1);
pLoop("%d ",buf_1);
scanf("%d",buf_2);
pLoop("%d ",buf_2);
scanf("%d",buf_3);
pLoop("%d ",buf_3);
scanf("%d",buf_4);
pLoop("%d ",buf_4);
return 0;
}
void pLoop(char *mode, int *arr)
{
int i;
for(i=0;i<MAX;i++)
{
printf(mode,arr[i]);
}
printf("\n");
}
/*运行*/
【1121a 2242 3】
1121 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
咦,一下子就运行完毕了,并且后面的数据都没有输出,这是肿么肥事。。。
再次尝试,去掉字符‘a’
/*运行*/
【1121 2242 3】
1121 0 0 0 0 0 0 0 0 0
2242 0 0 0 0 0 0 0 0 0
3 0 0 0 0 0 0 0 0 0
【a】
0 0 0 0 0 0 0 0 0 0
这一次正常识别到后续的数值了,再次输入‘a’发现没有输出来。
明白了整型数据输入碰到字符型数据会一直卡住,后续的输入全部都失效了。
浮点型输入
暂无,后续再补充。
gets( )
安全性低,不建议使用。
字符串输入
字符串输入的常用函数,形参为字符串的地址。
#include <stdio.h>
#define MAX 10
int main(void)
{
char str[MAX] = {0};
gets(str);
puts(str);
return 0;
}
/*运行*/
【12345ssdlhhhdbdddxss】
12345ssdlhhhdbdddxss
gets函数不限制输入的字符串长度,只要缓冲区够大就可以。这样子其实是很危险的,不限制长度,缓冲区也有上限啊,难怪编译的时候告警了
temp.c:(.text+0x32): 警告: the `gets’ function is dangerous and should not be used.(“gets”函数很危险,不应使用。)
建议使用fgets( ),虽然麻烦了一点,但是安全性高。
看上面的运行结果,我只分配了10个字节,它居然输出了这么多,我感觉已经内存溢出了。。。
fgets( )
字符串输入
fgets(目标地址,最大长度,输入);
遇到回车或最大长度-1结束输入,添加空字符结尾。
#include <stdio.h>
#define MAX 10
int main(void)
{
char str[MAX] = {0};
fgets(str,MAX,stdin);
fputs(str,stdout);
printf("\n");
return 0;
}
/*运行*/
【12345ssdlhhhdbdddxss】
12345ssdl
到第9个字符就结束了,MAX-1=9。
再运行一次:
/*运行*/
【12345】
12345
<空>
分析一下刚刚的2种情况:
第一种长度超过缓存区的情况
输入:12345ssdlhhhdbdddxss\n
输出:12345ssdl\0
第二种长度未超缓存区的情况
输入:12345\n
输出:12345\n\0
总之,回车符可以不要,空字符是一定要留在末尾的。
和之前的gets( )一对比,谁更赞一目了然了。。。
文件输入
/*test_file.c*/
#include <stdio.h>
#define MAX 10
int main(void)
{
char str[MAX] = {0};
FILE *fp;
fp = fopen("/home/yu/test_file.txt","a+");
if(fp == NULL)
{
return -1;
}
fseek(fp,0L,SEEK_SET);
fgets(str,MAX,fp);
fputs(str,stdout);
printf("\n");
return 0;
}
/*test_file.txt*/
12345ssdlhhhdbdddxss
/*运行*/
12345ssdl
getchar( )
字符输入
先输入一些字符,然后输出一下,看看它有什么特点
#include <stdio.h>
#define MAX 10
void pLoop(char *, int *);
int main(void)
{
char str_1[MAX] = {0};
char str_2[MAX] = {0};
char str_3[MAX] = {0};
char str_4[MAX] = {0};
char str_5[MAX] = {0};
char str_6[MAX] = {0};
str_1[0] = getchar();
str_2[0] = getchar();
str_3[0] = getchar();
str_4[0] = getchar();
str_5[0] = getchar();
str_6[0] = getchar();
printf("%c\n",str_1[0]);
printf("%c\n",str_2[0]);
printf("%c\n",str_3[0]);
printf("%c\n",str_4[0]);
printf("%c\n",str_5[0]);
printf("%c\n",str_6[0]);
return 0;
}
/*运行*/
【1a 3】
【%2】
1
a
<空>
3
<空>
<空>
%
和scanf()有点相似,都是会读取缓存区中的数据的,大多数字符都可以读取,遇到空格不会跳过,遇到回车符结束,并且下次还会读取回车符。
从上面运行的结果中我发现了一个问题,怎么3和%之间有2个空行呢,改进一下代码看看情况。
printf("%c",str_1[0]);
printf("(%#x)\n",str_1[0]);
printf("%c",str_2[0]);
printf("(%#x)\n",str_2[0]);
printf("%c",str_3[0]);
printf("(%#x)\n",str_3[0]);
printf("%c",str_4[0]);
printf("(%#x)\n",str_4[0]);
printf("%c",str_5[0]);
printf("(%#x)\n",str_5[0]);
printf("%c",str_6[0]);
printf("(%#x)\n",str_6[0]);
/*输出*/
【1a 3】
【%2】
1(0x31)
a(0x61)
(0x20)
3(0x33)
<空>
(0xa)
%(0x25)
查询了一下ASCII码表,发现0xa是换行符,仔细思考了一下,就是printf()输出了2次换行导致的,
printf("%c\n",str_5[0]);
相当于
printf("\r\n");
总结
输入
scanf( )
键盘输入,各种类型数据输入,遇回车则换行并结束输入,不保留回车符。int数据遇空格下一个函数读取,遇非数字型字符则卡住;char数据遇空格则下一个函数读取。可指定输入格式。
gets( )
键盘输入,字符串输入,遇回车则换行并结束输入,不保留回车符。
fgets( )
键盘、文件输入,遇回车符或MAX-1字节结束输入,会保留回车符。
getchar( )
键盘输入,字符输入,遇回车则换行并结束输入,保留回车符。
输出
printf( )
屏幕输出,变量、数组、结构体等数据输出,不自动换行。
puts( )
屏幕输出,字符串输出,自动换行。
fputs( )
屏幕、文件输出,字符串输出,不自动换行。
putchar( )
屏幕输出,字符输出,不自动换行。
| 输入 | scanf( ) | gets( ) | fgets( ) | getchar( ) |
|---|---|---|---|---|
| 输入方式 | 键盘 | 键盘 | 键盘、文件 | 键盘 |
| 存储类型 | 整型、浮点型、字符型 | 字符串 | 字符串 | 字符 |
| 存储回车符 | 否 | 否 | 是 | 是 |
| 结束方式 | 回车 | 回车 | 回车 | 回车 |
| 输出 | printf( ) | puts( ) | fputs( ) | putchar( ) |
|---|---|---|---|---|
| 输出方式 | 屏幕 | 屏幕 | 屏幕、文件 | 屏幕 |
| 自动换行 | 否 | 是 | 否 | 否 |
持续改进更新中。。。
本文详细解析了C语言中的输入函数,包括scanf(), gets(), fgets(), getchar()的特点和使用场景,对比了它们在键盘和文件输入时的行为差异,以及如何避免常见陷阱。

1218

被折叠的 条评论
为什么被折叠?



