【C语言天天练(十五)】字符串输入函数fgets、gets和scanf

引言:如果想把一个字符串读到程序中,必须首先预留存储字符串的空间,然后使用输入函数来获取这个字符串。

读取字符串输入的第一件事是建立一个空间以存放读入的字符串。

char *name;

scanf("%s", name);

这段代码虽然可能通过编译,但因为name可以指向任何地方,所以它的输入值可能覆盖以前name所指位置的值。

解决办法是声明一个固定大小的字符数组,或者使用C库里的分配存储空间的函数。

1、gets函数从系统标准输入获得一个字符串,读取字符串直到遇到一个换行符(\n),它读取换行符之前的所有字符,在这些字符后添加一个空字符(\0),然后把这个字符串交给调用它的程序。它把读取的换行符直接丢弃,而不是把它放入字符串中,这与下面讨论的fgets函数不同,下面再给出例子证明这一点。

#include <stdio.h>

char *gets(char *s);

示例:

#include <stdio.h>

#define MAX 18

int
main(int argc, char **argv)
{
	char name[MAX];
	char *ptr;
	printf("what't your name?\n");
	ptr = gets(name);		/*注意:gets()返回的指针与传递给它的是同一个指针*/
	printf("%s? Ah ! %s\n", ptr, name);
	return 0;
}

注意,如果gets出错时它返回一个空地址,因此在使用时一般使用如下技巧:

while((ptr = gets(name)) != NULL){
……
}

2、gets函数的一个不足是它不检查预留存储区是否能够容纳实际输入的数据。多出来的字符简单地溢出到相邻的内存区。fgets()函数改进了这个问题。它可以指定最大读入字符数。fgets()和gets()有3点不同:

a、它需要第二个参数来说明组大读入字符数。如果这个参数值为n,fgets()就会读取最多n-1个字符或者读完一个换行符为止。

b、如果fgets读取到换行符,就会把它存放在字符串里,而不是像gets()那样丢弃它。也就是说它在字符串的最后存放的是换行符(\n),而不是空字符(\0)。

c、它还需要第三个参数来说明读哪一个文件。

#include <stdio.h>

char *fgets(char *s, int size, FILE *strem);

示例

#include <stdio.h>

#define MAX 18

int
main(int argc, char **argv)
{
	char name[MAX];
	char *ptr;
	printf("what't your name?\n");
	ptr = fgets(name, MAX, stdin);
	printf("%s? Ah ! %s\n", ptr, name);
	return 0;
}

编译测试结果显示:

what't your name?
libing
libing
? Ah ! libing

它显示了fgets()的一个不足之处,fgets()把换行符存储到字符串里了,这样每次显示字符串时就会显示换行符。

下面对fgets()和gets()两个函数对于换行符不同处理的示例证明:

#include <stdio.h>

#define MAX 18

int
main(int argc, char **argv)
{
	char name1[MAX];
	char name2[MAX];
	char *ptr;
	printf("what't your name?\n");
	ptr = fgets(name1, MAX, stdin);
	ptr = gets(name2);
	if(strcmp(name1, name2)){<span style="white-space:pre">	</span>/*比较两个字符串,因为gets会在最后将\n改为\0存入字符串,而fgets会直接将\n存入字符串*/
		printf("name1 is not equal name2\n");
	}
	return 0;
}

3、scanf()和gets()主要的差别在于它们如果决定字符串何时结束。scanf()更给予获取单词而不是获取字符串;而gets()函数,会读取所有的字符,直到遇到第一个换行符为止。scanf()使用两种方法决定输入结束,如果使用%s格式,字符串读到下一个空白字符。如果指定了字段宽度,比如%10s,scanf()就会读入10个字符或直到遇到第一个空白字符,由二者中最先满足的哪一个终止输入。

#include <stdio.h>

int
main(void)
{
	char name1[11], name2[11];
	int count;

	while(1){
		printf("please input 2 names.\n");
		count = scanf("%5s %10s", name1, name2);
		printf("I read the %d names %s and %s.\n"
						,count, name1, name2);

	}
	return 0;
}

运行执行测试:

please input 2 names.
Jesse Jukes
I read the 2 names Jesse and Jukes.
please input 2 names.
Liza Applebottham
I read the 2 names Liza and Applebotth.
please input 2 names.
Portensia Callowit
I read the 2 names am and Portensia.
please input 2 names.
I read the 2 names Callo and wit.

【C语言天天练(十五)】字符串输入函数fgets、gets和scanf

时间: 2024-10-27 12:36:05

【C语言天天练(十五)】字符串输入函数fgets、gets和scanf的相关文章

【C语言天天练(五)】setjmp和longjmp

setjmp和longjmp组合可以实现跳转,与goto语句有相似的地方.但有以下不同: 1.用longjmp只能跳回到曾经到过的地方.在执行setjmp的地方仍留有一个过程活动记录.从这个角度看,longjmp更像是"从何处来"而不是"往何处去".longjmp接收一个额外的整型参数并返回它的值,这可以知道是由longjmp转移到这里的还是从上一条语句执行后自然而然来到这里的. 2.goto语句不能跳出C语言当前的函数,而longjmp可以跳的更远,可以跳出函数,

【C语言天天练(十八)】字符/字符串输入函数fgetc、fgets、getc、getchar和gets

#include <stdio.h> int fgetc(FILE *stream); char *fgets(char *s, int size, FILE *stream); int getc(FILE *stream); int getchar(void); char *gets(char *s); fgetc()读取文件指针stream所指向文件的下一个字符,返回值是所读取字符强制类型转换成整数的值,如果到达文件尾部或者出错,则返回EOF. getc()与fgetc()函数相同,只是它

【C语言天天练(十六)】字符串输出函数puts、fputs和printf

C有三个用于输出字符串的标准库函数puts().fputs()和printf(). 1.puts()函数只需要给出字符串参数的地址. #include <stdio.h> int puts(const char *s); 示例: #include <stdio.h> #define DEF "I am libing" int main(int argc, char **argv) { char str1[30] = "I am libing."

【C语言天天练(二十)】scanf函数详解

引言:scanf函数虽然是学习C语言时比较早就接触的一个函数,但在使用过程中,发现真正掌握它却并不容易.本文就通过各种例子来详细的总结一下该函数的各种用法,假设它的调用格式为 scanf("<格式化字符串>",<地址表>). 1.一般使用scanf函数时都是为某个变量赋值,不考虑它的返回值.但是任何函数都是需要返回的(即使返回类型用void,也可以认为只是调用了return语句,只是并没有返回什么东西而已),同样的scanf函数也是有返回的,它的返回值是成功读取

【C语言天天练(十七)】字符/字符串输出函数fputc、fputs、putc、putchar和puts

#include <stdio.h> int fputc(int c, FILE *stream); int fputs(const char *s, FILE *stream); int putc(int c, FILE *stream); int putchar(int c); int puts(const char *s); fputc()写一个字符c,强制转换成一个unsigned char类型字符,到文件stream. fputs()写一个字符串到stream,省略字符串尾部的'\0

【C语言天天练(十九)】restrict关键词

引言:在内核的系统调用函数里,经常遇到函数的参数使用restrict限定词限定的情况,下面就对该关键词做个总结. 1.restrict关键词是C99特性才添加的,因此在编译使用含有该限定词的程序时,一定要在后边添加-std=c99的标志,使得gcc能够支持c99标准. 2.restrict既然是个限定词,那么它限定什么变量呢?它只能限定指针变量!经过它限定的数据对象,表明指针时访问该数据对象的唯一且初始的方式.注意:这里的唯一表明了,由它限定的指针所指向的数据块,只能由该指针访问,不能由除它之外

【C语言天天练(十二)】命令行参数

C程序的main函数具有两个形参.第1个通常称为argc,它表示命令行参数的数目.第2个通常称为argv,它指向一组参数值. 指针数组:这个数组的每个元素都是一个字符指针,数组的末尾是一个NULL指针.argc的值和这个NULL值都用于确定实际传递了多少个参数.argv指向数组的第1个元素,这就是它为什么被声明为一个指向字符的指针的指针的原因.注意:通常第1个参数就是程序的名称. 示例: #include <stdio.h> int main(int argc, char **argv) {

【C语言天天练(十)】结构体

引言:数据经常以成组的形式存在.在C中,使用结构可以把不同类型的值存放在一起. 结构的声明有两种 1.struct SIMPLE{ int a; char b; float c; };然后用标签SIMPLE去声明结构体变量. 2.typedef struct{ int a; char b; float c; }Simple;然后用Simple去声明结构体变量.此时Simple是个类型名,而不像上面的SIMPLE是个标签. 结构成员可以是标量.数组.指针甚至是其他结构. 结构成员的直接访问用点操作

【C语言天天练(八)】字符串

字符串是一种重要的数据类型,但C语言中没有显式的字符串数据类型.头文件string.h中包含了大多数对字符串的操作函数.因此,有字符串的操作时,一般会包含string.h头文件. 1.字符串的长度:对字符串进行的操作中,经常要对它进行求长度的操作.字符串的长度就是它所包含的字符个数.size_t strlen(char const *string); 注意:strlen返回一个类型为size_t的值,它是一个无符号整数类型.在表达式中使用无符号数可能导致不可预料的结果. 如下面两条表达式并不相等