fgets函数
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
fgets函数
从流中读一行或指定个字符,
原型是char *fgets(char *s, int n, FILE *stream);
从流中读取n-1个字符,除非读完一行,参数s是来接收字符串,如果成功则返回s的指针,否则返回NULL。
形参注释:*string结果数据的首地址;n-1:一次读入数据块的长度,其默认值为1k,即1024;stream文件指针
例:如果一个文件的当前位置的文本如下
Love ,I Have
But ........
如果用
fgets(str1,4,file1);
则执行后str1="Lov",读取了4-1=3个字符,
而如果用
fgets(str1,23,file1);
则执行str="Love ,I Have",读取了一行(不包括行尾的'n')。
序 例:
#include
#include
int main(void)
{
FILE *stream;
char string[] = "This is a test";
char msg[20];
/* open a file for update */
stream = fopen("DUMMY.FIL", "w+");
/* write a string into the file */
fwrite(string, strlen(string), 1, stream);
/* seek to the start of the file */
fseek(stream, 0, SEEK_SET);
/* read a string from the file */
fgets(msg, strlen(string)+1, stream);
/* display the string */
printf("%s", msg);
fclose(stream);
return 0;
}
fgets函数用来从文件中读入字符串。fgets函数的调用形式如下:fgets(str,n,fp);此处,fp是文件指针;str是存放在字符串的起始地址;n是一个int类型变量。函数的功能是从fp所指文件中读入n-1个字符放入str为起始地址的空间内;如果在未读满n-1个字符之时,已读到一个换行符或一个EOF(文件结束标志),则结束本次读操作,读入的字符串中最后包含读到的换行符。因此,确切地说,调用fgets函数时,最多只能读入n-1个字符。读入结束后,系统将自动在最后加'\0',并以str作为函数值返回。
-----------------------------------------------------------------------------------------------------
fgets() 2010-01-22 14:18:45| 分类: 默认分类 | 标签: |字号大中小 订阅 .
在C语言,常用的同类函数还有fscan()和gets(),不过这两种函数都有其缺点,或
者可以说是制约性。
fscan()函数不能读取带有空格的字符串,当字符串中含有空格时,函数只能读取
空格之前的字符串,空格之后的全部忽略。
gets()函数虽然可以操做带有空格的字符串,不过容易引起溢出,因为C语言是将
字符串当做一种数组操做的,既然是数组,就有长度,如果gets ()函数读取的字
符串长度大于被赋值数组的长度,就会引起溢出,而且新版的GCC已经不能正确编
译gets()函数了,会报错。
fgets()函数的基本用法为:
fgets(char * s,int size,FILE * stream);
括
号中,第一个参数为将被赋值的数组名,这里需要注意的是,其中不用写数组名
称后面的方括号以及其中的数组长度。
第二个参数是将要读取字符串的长度,这里需要注意的是,这里长度的数值是“字
符串实际长度+1”,加1是因为,字符串最后面还有一个/0位。
最后一个参数为输入设备或者变量。一般情况下,我们都是从键盘输入,也就是
stdin。(从文件读取的这里暂不说明)
OK!现在举一个例子!下面的这段代码作用在于,属于一个字符串,然后计算出字
符串中单词的个数。
#include
main()
{
char dia[80];
char t,m;
int i=0,num=0,flag=0;
fgets(dia,80,stdin);
fputs(dia,stdout);
for (i=0;dia[i]!=’\0′;i++)
{
if (dia[i]==’ ‘)
flag=0;
else
if (flag==0)
{
flag=1;
num++;
}
}
printf("%d\n",num);
}
这段代码的工作原理是,使用一个用于标示的变量flag,还有一个用于统计单词个
数的变量num。然后逐一读取字符串中的每一个字符,当遇到字母时flag的值为1,
当遇到空格时,flag的值为0。如果遇到一个字母,并且此时flag值为0(说明这个
字母之前的一个字符是空格),给num加1,直到遇到空格时,将flag重新赋值为
0。
在fgets()使用中需要注意,其中第二个参数规定的字符串长度应该与字符串长度
相等,否则运行程序时会有溢出的错误。当输入的字符串大于限定的字符串长度时
(本例中限定的是80),限定长度之后的字符串会被丢弃。
fgets()函数遇到换行终止~
----------------------------------------------------------------------------------------------------
区分C语言中getch、getche、fgetc、getc、getchar、fgets、gets
首先,这两个函数不是C标准库中的函数,
int getch(void) //从标准输入读入一个字符,当你用键盘输入的时候,屏幕不显示你所输入的字符。也就是,不带回显。
int getche(void) //从标准输入读入一个字符,键盘输入的时候,屏幕显示所输入的字符。带回显。
这两个函数包含在头文件conio.h中,需要记住的是conio.h不是C标准库中的头文件。Micorsoft 和 Borland的 C编译器提供了conio.h,用来创建控制台文本用户界面。一般在Windows系统下安装了VS、VC等,就可以包含conio.h头文件。但是一般在Unix、Linux系统中,/usr/include/中都没有这个头文件。
getch和getche在等待用户从键盘输入的时候,用户按下一个键后,不需要按回车,程序自动往下执行。在Linux中,终端输入在缺省情况下是被“一锅端”的,也就是说整行输入是被一起处理的。通常,
这是一种人们所希望的方便的办法,但它也意味着在读入数据时必须按一下回车键表示输入行结束后才能得到输入的数据。在游戏中,很多都提供了“老板键”,它的实现,就是利用了这两个函数。
其次,除了getch和getche,其他的都是C标准库中的头文件,包含在头文件stdio.h中。
int fgetc ( FILE * stream ); //从流stream中读一个字符。可以将标准输入stdin作为它的实参,这时候从标准输入读取一个字符。
int getc(FILE * stream); //和fgetc等效,由fgetc通过宏实现。
int getchar ( void ); //从标准输入stdin读入一个字符,程序等待你输入的时候,你可以输入多个字符,回车后程序继续执行。 //但getchar只读入一个字符说明:getc、getchar都是通过宏定义借助fgetc实现。如getchar的实现为,#define getchar() fgetc(stdin)。 char * fgets (char * str, int num, FILE *stream); //从流stream中读入最多num个字符到字符数组str中,当遇到换行符时、或读到num-1个字符时停止。 //自动加上'\0'空字符结尾
char * gets ( char * str ); //从标准输入stdin读取一个字符串,遇到换行或结束时候终止。
//不同于fgets,他没有指定num,所以需要注意字符数组str的大小。
说明: fgets和gets之间没有宏定义的关系,彼此各自有自己的实现。蠕虫病毒的实现就是函数gets的“功劳”。gets函数的任务是从流中读入一个字符串。它的调用者会告诉它把读入的字符串放在什么地方。但是,gets()函数并不检查缓冲区大小,如果调用者提供了一个指向堆栈的指针,并且get()函数读入的字符数量超过了超过了缓冲区的空间大小,get()会愉快地将多出来的字符继续写入到堆栈中,这就覆盖了堆栈中原来的内容。如:main(){ char line[512]; //在程序的堆栈上分配512个字符的空间 ... gets(line); //蠕虫病毒的入口,可以将恶意代码通过多出来的数据写入堆栈}
建议不要用getch和getche,因为它们不是C标准库中的函数。用它们写出的程序可移植性差,不同的编译器不保证可以包含conio.h。建议用fgets函数彻底替代gets函数。
另外,绝大多数的这些get函数,都有对应的put版本。
int fputc ( int character, FILE * stream );
int putc ( int character, FILE * stream ); //通过宏定义和fputc实现
int putchar ( int character ); //通过宏定义实现:#define putchar(c) fputc(c, stdout)
int fputs ( const char * str, FILE * stream );
int puts ( const char * str );
说明:两者之间无宏定义实现关系。puts(const char *str)近似等
效于fputs(cosnt char *str, stdout),不同点是前者还输出一个'\n'
最后,关于EOF
EOF是在stdio.h文件中定义的符号常量,值为-1。如,
fputc函数返回一个值:如果输出成功则返回值就是输出的字符;如果输出失败,则返回一个EOF。
fgetc函数读字符时遇到文件结束符,函数返回一个文件结束标记EOF。如果想从一个磁盘文件顺序读入字符并在屏幕上显示,可以:
ch = fgetc(fp);
while(ch != EOF){
putchar(ch);
ch = fgetc(fp);
}
注意,EOF不是可输出字符,因此不能在屏幕上显示。由于ASCII码不可能出现-1,因此EOF定义为-1是合适的。当读入的字符值等于-1(即EOF)时,表示读入的已不是正常的字符,而是文件结束符。但以上只适用于读取文本文件的情况。现在ANSI C 已经允许用缓冲文件系统处理二进制文件,而读入某一个字节中的二进制数据的值有可能是-1,而这又恰好是EOF的值。这就出现了需要读入有用数据,却处理为“文件结束”。feof(fp) 用来测试fp所指向的文件当前状态是否是“文件结束”。如果想顺序读入一个二进制文件数据,可以:
while(!feof(fp)){
c = fgetc(fp);
...
}
-------------------------------------------------------------------------------------------------------
函数名: fgets
功 能: 从流中读取一字符串
用 法: char *fgets(char *string, int n, FILE *stream);
形参注释:*string结果数据的首地址;n-1:一次读入数据块的长度,其默认值为1k,即1024;stream文件指针
序 例:
#include
#include
int main(void)
{
FILE *stream;
char string[] = "This is a test";
char msg[20];
/* open a file for update */
stream = fopen("DUMMY.FIL", "w+");
/* write a string into the file */
fwrite(string, strlen(string), 1, stream);
/* seek to the start of the file */
fseek(stream, 0, SEEK_SET);
/* read a string from the file */
fgets(msg, strlen(string)+1, stream);
/* display the string */
printf("%s", msg);
fclose(stream);
return 0;
}
fgets函数fgets函数用来从文件中读入字符串。fgets函数的调用形式如下:fgets(str,n,fp);此处,fp是文件指针;str是存放在字符串的起始地址;n是一个int类型变量。函数的功能是从fp所指文件中读入n-1个字符放入str为起始地址的空间内;如果在未读满n-1个字符之时,已读到一个换行符或一个EOF(文件结束标志),则结束本次读操作,读入的字符串中最后包含读到的换行符。因此,确切地说,调用fgets函数时,最多只能读入n-1个字符。读入结束后,系统将自动在最后加'\0',并以str作为函数值返回。
编辑本段]
fgets(由文件中读取一字符串)
相关函数
open,fread,fscanf,getc
表头文
件
include
定义函数
har * fgets(char * s,int size,FILE * stream);
函数说明
fgets()用来从参数stream所指的文件内读入字符并存到参数s所指的内存空间,直到出现换行字符、读到文件尾或是已读了size-1个字符为止,最后会加上NULL作为字符串结束。
返回值
gets()若成功则返回s指针,返回NULL则表示有错误发生。
范例
#include
main()
{
char s[80];
fputs(fgets(s,80,stdin),stdout);
}
执行
this is a test /*输入*/
this is a test /*输出*/
--------------------------------------------------------------------------------------------------------------------------------
字符和字符串(字符数组)处理
2009-09-16 15:48
几个常见特殊字符的整型数字
描述 char int
空格 ' ' 32
TAB键 '\t' 9
回车换行 LF 10
文件结束 EOF -1
字符串结束符号 '\0' 40
TAB字符处理要小心,经过到记事本copy/paste后,TAB键被转化成几个空格
for(;str[i]==' '||str[i]==' ';i++);
但经过到记事本copy/paste后,TAB键被转化成几个空格
所以系统总报warning:
tmp.c:58: warning: comparison is always false due to limited range of data type
tmp.c:59:27: warning: character constant too long for its type
‘a’与” a”的区别(实际就是字符和字符串的区别)
‘a’
1字节 ‘a’
” a”
2字节
‘a’’\0’
字符串数组char str[20],至少有一个str[n]是0
strcpy(str,”123”);
str[0]=’1’
str[1]=’2’
str[2]=’3’
str[3]=0
字符串指针=字符串数组名=字符串数组第一个元素的地址(&)
char *s;
char str[20];
s = str = &str[0]
字符串数组和字符串指针的相同和不同
作为函数参数 ,字符串数组名和字符串指针没区别
showtable(char s[50]);
showtable(char *s);
在printf上 ,字符串数组和字符串指针没区别
char s[20];
char *p ;
p="a point";
sprintf(s,"a char arrage");
printf("p's value is : %s \n",p );
printf("s's value is : %s \n",s );
p's value is : a point
s's value is : a char arrage
字符串数组和字符串指针在赋值上不同
字符串数组无法直接赋值,只能用sprintf,strcpy,strcat char s[20];
char *p;
char s[20];
p="a p
oint";
sprintf(s,"a char arrage");
strcpy(s,"a char arrage");
字符串指针只支持printf,不支持scanf,scanf还是建议用字符串数组
对指针初始赋值,不分配空间,可以支持printf
char *p;
p="ppp";
printf("p's value is : %s\n",p);
[macg@localhost mysqltmp]$ ./tt
p's value is : ppp
对指针初始赋值,不分配空间,不支持scanf
char *p;
p="ppp";
scanf("%s",p);
[macg@localhost mysqltmp]$ ./tt
Segmentation fault
如何使字符串指针支持scanf操作,必须用malloc分配字节
#include
main()
{
char s[20];
char *p;
int ret;
p=malloc(20);
scanf("%s",p);
printf("p's value is : %s\n",p);
free(p);
[macg@localhost mysqltmp]$ ./tt
dddd
p's value is : dddd
对malloc要求:
#include
malloc返回指针 p=malloc(20);
记着要free(指针) free(p);
虽然也可以用字符串数组初始化字符串指针,但不建议
实际就等于操作的是字符串数组了,多此一举
char s[20];
char *p;
p=s;
字符串不建议直接赋值和比较,用函数strcpy
strcpy(char*,char *)
字符串拷贝函数
后者拷贝到前者
strcat(char*,char *)
字符串追加函数
后者追加到前者后
strcmp(char*,char *)
对字符串是不允许做==或!=的运算
只能用字符串比较函数
字符串比较只能采用strcmp
不能用同一个字符串数组赋值给多个字符串指针,这样会造成两个字符串指向同一空间 .
char *name,*media,a[30],s[80],c;
name=media=a;
以后修改meida,name也会跟着改变
gets读字符串也有”连读”问题, 不过这个影响的不是scanf前面剩下的'\n',而是前面剩下的0
Char a[20];
gets(a)
while (a[0]==0) gets(a);
scanf读字符串,只能读到空格,所以scanf只能读单个单词的字符串,不能读"句子"
char s[80];
scanf("%s",s);
printf("your input is :%s",s);
[macg@localhost mysqltmp]$ ./tt
abc def hig
your input is :abc
gets能克服scanf的缺陷,读字符串包含空格
char a[30];
gets(a);
printf("your input is :%s\n",a);
[macg@localhost mysqltmp]$ ./tt
abc efd sdd
your input is :abc efd sdd
fgets字符串指针改成字符串数组,消灭了Segmentation fault错误
char *re,*rec ;
re=fgets(rec,100 ,srcstream);
出Segmentation fault错误
改成
char *re,rec[100];
re=fgets(rec,100, srcstream);
Powered by 1.5 ? 2001-2009 Comsenz Inc.
------------------------------------------------------------------------------------------------------------------
fgets使用注意事项
fgets (buf, size, fp) 其行为方式如下:
(1)遇到换行或文件结束EOF则返回。
(2)按行读取。
(3)每一行结束处的换行字符‘\n’也算该行字符。
(4)对于大小为size的buf,最多只读取size-1
个字符。
(5)自动地把buf中最后一个字符(通常是换行符)的后面一个字节填充零结束符('\0')。
因此如果想把buf中的换行符去掉,可以这样:
if(buf[strlen(buf)-1] =='\n')
buf[strlen(buf)-1] = '\0';
当然前提是buf足够大,可以容纳完整的一行(包括最后的那个换行符)。
fputs (str, fp)
(1)把str中零结束符之前的全部文字输入到文件中。
(2)输入完成后,不会增加额外的特殊字符,如换行符等。
如果想输入完str后,就换行,则应该在上述调用后,再调用fputc('\n',fp);才行。
--------------------------------------------------------------------------------------------------------------------
fgets函数与fputs函数
.
作者:陈刚,华清远见嵌入式培训中心讲师。
#include
char *fgets(char *s, int size, FILE *stream);
功能:从文件流读取一行,送到缓冲区,使用时注意以下几点:
返回值:成功时s指向哪返回的指针就指向哪,出错或者读到文件末尾时返回NUL
fgets函数,参数s是缓冲区的首地址,size是缓冲区的长度,该函数从stream所指的文件中读取以'\n'结尾的一行(包括'\n'在内)存到缓冲区s中,并且在该行末尾添加一个'\0'组成完整的字符串。
fgets()函数中,第一个参数指针需要我们事先分配好大小。另外,fgets()函数不适合取二进制的文件,这样,容易发生错误。
注:fgets从指定的文件中读一行字符到调用者提供的缓冲区中,gets从标准输入读一行字符到调用者提供的缓冲区中。
1.当遇到换行符或者缓冲区已满,fgets就会停止,返回读到的数据,值得注意的是不能用fgets读二进制文件,因为fgets会把二进制文件当成文本文件来处理,这势必会产生乱码。
2.每次调用,fgets都会把缓冲区的最后一个字符设为null,这意味着最后一个字符不能用来存放需要的数据,所以如果有一行,含有LINE_SIZE个字符(包括换行符),要想把这行读入缓冲区,请把参数n设为LINE_SIZE+1
3. 由结论1可推出:给定参数n,fgets只能读取n-1个字符(包括换行符),如果有一行超过n-1个字符,那么fgets返回一个不完整的行,也就是说,只读取该行的前n-1个字符,但是,缓冲区总是以null字符结尾,对fgets的下一次调用会继续读该行。
注意,对于fgets来说,'\n'是一个特别的字符,而'\0'并无任何特别之处,如果读到'\0'就当作普通字符读入。如果文件中存在'\0'字符(或者0x00字节),调用fgets之后就无法判断缓冲区中的'\0'究竟是从文件读上来的字符还是由fgets自动添加的结束符,所以fgets只适合读文本文件而不适合读二进制文件,并且文本文
件中的所有字符都应该是可见字符,不能有'\0'。
#include
int fputs(const char *s, FILE *stream);
int puts(const char *s);
返回值:成功返回一个非负整数,出错返回EOF
fputs向指定的文件写入一个字符串,puts向标准输出写入一个字符串。
缓冲区s中保存的是以'\0'结尾的字符串,fputs将该字符串写入文件stream,但并不写入结尾的'\0'。与fgets不同的是,fputs并不关心的字符串中的'\n'字符,字符串中可以有'\n'也可以没有'\n'。puts将字符串s写到标准输出(不包括结尾的'\0'),然后自动写一个' \n'到标准输出。
----------------------------------------------------------------------------------------------------------------
标准I/O库函数:fgets与gets比较分析
函数名:fgets
功能:从流中读取一个字符串
用法:CHAR *fgets(CHAR *string,int n,FILE *stream);
形参注释:
*string:结果数据的首地址;n-1:一次读进数据块的长度,其默认值为1k,即1024;stream文件指针,指向一个文件
函数说明:
fgets()用来从参数stream所指的文件内读进字符并存到参数s所指的内存空间,直到出现换行字符、读到文件尾或是已读了size-1个字符为止,最后会加上NULL作为字符串结束。
假如在未读满n-1个字符之时,已读到一个换行符或一个EOF(文件结束标志),则结束本次读操纵,读进的字符串中最后包含读到的换行符。
示例:
#include
#include
int main(void)
{
FILE *stream; //FILE 是一种数据类型,是治理文件流的一种结构
CHAR string[] = "This is a test";
CHAR msg[20];
/* open a file for update */
stream = fopen("DUMMY.FIL", "w+");
/* write a string into the file */
fwrite(string, strlen(string), 1, stream);
/* seek to the start of the file */
fseek(stream, 0, SEEK_SET);
/* read a string from the file */
fgets(msg, strlen(string)+1, stream);
/* display the string */
printf("%s", msg);
fclose(stream);
return 0;
}
代码分析:
操纵成功时返回的是msg的值,假如碰到文件结束或错误的时候,fgets返回NULL;由于输进的过程中一般只会按下回车,很少会是EOF的,所以不会是碰到文件结束,而错误是当你传进msg是NULL的时候才会碰到,所以基本上是不可能返回NULL的。而且输进超过了长度n的时候,fgets会自动截断的,属于操纵成功。
函数名:gets
功能:从stdin流中读取字符串,直至接受到换行符或EOF时停止,并将读取的结果存放在str指针所指向的字符数组中。换行符
不作为读取串的内容,读取的换行符被转换为null值,并由此来结束字符串。
示例:
#include"stdio.h"
void main()
{
CHAR str1[5];
gets(str1);
printf("%s\n",str1);
}
留意:本函数可以无穷读取,不会判定上限,所以程序员应该确保str的空间足够大,以便在执行读操纵时不发生溢出。
代码分析:
用gets函数时,编译器会有报警提示,由于gets函数不安全,没有限制输进缓冲区的大小,轻易造成溢出。这就似乎养金鱼,你投多少鱼食它就吃多少,自己不知道控制,但它的胃容量是有上限的(默认值),喂的太多金鱼就会撑死(溢出)。
总结:
1 尽量不使用gets
2 内存越界是有题目隐患,但并不是一定会体现出题目,要看具体情况。