fgets ,gets, getchar, scanf函数
1.scnaf()
函数原型
#include <stdio.h>
int scanf(const char *format, …);
功能:将从键盘输入的字符转化为“输入控制符”所规定格式的数据,然后存入以输入参数的值为地址的变量中。
scanf进行输入时,遇到空格符或者换行符就会表示一次读取结束,但是空格符和换行符并不会输入,而是留在缓冲区等待下一次的读取。
例
#include <stdio.h>
int main()
{
char buf[5];
char c;
int a;
scanf("%s", buf);
scanf("%c", &c);
scanf("%d", &a);
printf("---------\n");
printf("%s\n", buf);
printf("%d, %c!\n", a, c);
return 0;
}
结果显示
由以上结果可知,第一个输入的是字符串,空格,数字,结果显示空格也被读入,第二个输入的是字符串,回车,数字,结果显示回车也被读入。
众所周之,scanf以空白字符为定界符,但如果输入的字符串是以其它字符为定界符的,那怎么办?[]就是专门处理这个问题的转换说明符。
2.scanf("%[^abcd]", a);
在输入中限定用abcd这四个字符,如输入其他的字符,则输入结束,其他的字符在缓存读数区里留给下一个输入或丢掉。
•scanf("%[abcd]"%s, a, b)
输入abcdefg时,abcd进入a字符串,当输入e时跳出a字符串的输入,efg进入b字符串。
2.scanf("%[^abcd]", a);
除abcd以外的数可以输入,如输入abcd这四个其中任意一个,则跳出输入字符串。
3.scanf("%10[^abcd]", ptr);
输入的字符串中最多只能有10个字符,多出来的字符进入缓存区留给下一个输入或丢掉。
4.scanf("%[a-zA-Z]", a);
扫描列表由大小写各26个字母组成。
对于减号-,只有在紧贴[字符或抑扬字符以及作为扫描列表最后一个成员时,-字符才会被视为扫描列表的成员。c标准把其余情况规定为编译器相关的。大多数编译器把这种情况的减号定义为连字符
2.fgets()
虽然用 gets() 时有空格也可以直接输入,但是 gets() 有一个非常大的缺陷,即它不检查预留存储区是否能够容纳实际输入的数据,换句话说,如果输入的字符数目大于数组的长度,gets 无法检测到这个问题,就会发生内存越界,所以编程时一般建议使用 fgets()。
fgets()原型
#include <stdio.h>
char *fgets(char *s, int size, FILE *stream);
fgets() 虽然比 gets() 安全,但安全是要付出代价的,代价就是它的使用比 gets() 要麻烦一点,有三个参数。它的功能是从 stream 流中读取 size 个字符存储到字符指针变量 s 所指向的内存空间。它的返回值是一个指针,指向字符串中第一个字符的地址。
param:s 代表要保存到的内存空间的首地址,可以是字符数组名,也可以是指向字符数组的字符指针变量名。
param:size 代表的是读取字符串的长度。
param:stream 表示从何种流中读取,可以是标准输入流 stdin,也可以是文件流,即从某个文件中读取。标准输入流就是输入缓冲区。所以如果是从键盘读取数据的话就是从输入缓冲区中读取数据,即从标准输入流 stdin 中读取数据,所以第三个参数为 stdin。
返回值:返回读入的字符的个数。
例1
# include <stdio.h>
int main(void)
{
char str[10]; /*定义一个最大长度为19, 末尾是'\0'的字符数组来存储字符串*/
printf("请输入一个字符串:");
fgets(str, 5, stdin); /*从输入流stdin即输入缓冲区中读取5个字符到字符数组str中*/
printf("%s\n", str);
return 0;
}
输出结果:
请输入一个字符串:abcdef
abcd
实际上输出的结果是abcd这4个字符,而我们实际上是输入了abcdef这6个字符。原因是 fgets() 只指定了读取 5 个字符放到字符数组 str 中,这5个字符中还包括系统自动加上的’\0’字符,所以缓冲区里是abcdef\n这7个字符而数组里实际上是abcd\0这5个字符。如果我们设定读取的字符大于我们要输入的内容时,问题就很好解决了。
fgets() 函数中的 size 如果小于字符串的长度,那么字符串将会被截取;如果 size 大于字符串的长度则多余的部分系统会自动用 ‘\0’ 填充。所以假如定义的字符数组长度为 n,则 fgets() 中的 size 就为 n–1,留一个给 ‘\0’ 就行了
如果输入的字符串长度没有超过 n–1,那么系统会将最后输入的换行符 ‘\n’ 保存进来,保存的位置是紧跟输入的字符,然后剩余的空间都用 ‘\0’ 填充。所以此时输出该字符串时 printf 中就不需要加换行符 ‘\n’ 了,因为字符串中已经有了。
3.gets()
gets()函数原型
#include <stdio.h>
char *gets(char *str);
param:str, 可以是一个字符指针变量名,也可以是一个字符数组名。
返回值:返回读入的字符个数。
功能:从输入缓冲区读取一个字符串存储到字符指针变量str所指向的内存空间。
例2.1
# include <stdio.h>
int main(void)
{
char str[20] = "\0"; //字符数组初始化\0
printf("请输入字符串:");
gets(str);
printf("%s\n", str);
return 0;
}
输出结果:
请输入字符串:i am a handsome boy
i am a handsome boy
由此可见gets()函数比下面的scanf函数简洁,而且输入的字符串中有空格也可以直接输入。
gets(str); <=========> scanf("%s", str);
此外,关于使用 gets() 函数需要注意:使用 gets() 时,系统会将最后从键盘输入的换行符从缓冲区中取出来,然后丢弃,所以缓冲区中不会遗留换行符。这就意味着,如果前面使用过 gets(),而后面又要从键盘给字符变量赋值的话就不需要吸收回车清空缓冲区了,因为缓冲区的回车已经被 gets() 取出来扔掉了。
例2.2
#include <stdio.h>
int main()
{
char str[30], shr[30];
char ch, sh;
printf("请输入字符串1:");
gets(str);
printf("str: %s\n", str);
printf("请输入字符串2:");
scanf("%s", shr);
printf("shr:%s\n", shr);
printf("请输入字符串3:");
scanf("%c", &ch);
printf("ch = %c\n", ch);
printf("请输入字符串4:");
scanf("%c", &sh);
printf("sh: %c\n", sh);
return 0;
}
输出结果:
从结果中我们可以看出,gets把从键盘中输入的换行符吃掉了,而相比的scanf则碰到空格或者换行符就结束,并且没有被scanf读入的数据会停留在缓冲区中等待着下一次的输入。
4.getchar()
当程序调用getchar时.程序就等着用户按键.用户输入的字符被存放在键盘缓冲区中.直到用户按回车为止(回车字符也放在缓冲区中).当用户键入回车之后,getchar才开始从stdio流中每次读入一个字符.
getchar有一个int型的返回值.getchar函数的返回值是用户输入的第一个字符的ASCII码,如出错返回-1,且将用户输入的字符回显到屏幕.如用户在按回车之前输入了不止一个字符,其他字符会保留在键盘缓存区中,等待后续getchar调用读取。