C语言的gets和puts

C语言的gets和puts前言 在之前介绍了 C 语言中 printf 和 scanf 和 C 语言中 getchar 和 putchar 本篇文章介绍 puts 相关函数和 gets 相关函数 puts 和 printf 函数一样 puts 函数也属于 stdio h 系列的输入 输出函数 但是与 printf 函数不同的是 puts 函数仅仅显示字符串

大家好,我是讯享网,很高兴认识大家。

前言

在之前介绍了C语言中printf和scanf和C语言中getchar和putchar,本篇文章介绍puts相关函数和gets相关函数

puts

和printf函数一样,puts函数也属于stdio.h系列的输入/输出函数,但是与printf函数不同的是,puts函数仅仅显示字符串,并且会自动在显示的字符串末尾添加换行符。看下面的例子:

#include <stdio.h> int main(int argv, char argc) { puts("this is line 1."); puts("this is line 2."); return 0; } 

讯享网

输出

讯享网this is line 1. this is line 2. 

与puts相比,gets可就没那么幸运了

gets

之前介绍过scanf函数,scanf函数会从输入流stdin中读取数据,知道碰到空字符(空格 换行符 制表符)或者EOF会停止,并且把空字符放回输入流中,而gets函数呢,也是从输入流中读取数据,但是除了碰到换行符或者EOF之外,不会停止,这对于我们读取一行数据来说很方便,看下面的例子

#include <stdio.h> int main(int argv, char argc) { char inputData[5]={'s','s','s','s','s'}; scanf("%s",inputData); gets(inputData); printf("%hhu,%hhu,%hhu,%hhu,%hhu\n",inputData[0],inputData[1],inputData[2],inputData[3],inputData[4]); printf("%c,%c,%c,%c,%c\n",inputData[0],inputData[1],inputData[2],inputData[3],inputData[4]); return 0; } 

如果我输入

讯享网1234 5回车 

输出的结果为

32,53,0,52,0 ,5,,4, 

分析一下:

  • 输入1234 5以后回车,这是输入流中一共有7个字符,1,2,3,4,空格,5,回车,inputData的数据应该是[s,s,s,s,s]
  • scanf方法开始读取数据,从非空字符开始读,一直读取到空格为止,这时候inputData的数据应该是[1,2,3,4,'\0'],注意,scanf在末尾添加了空字符作为输入的结束
  • 然后gets函数继续从输入流中读取数据,注意,这个时候空格还在输入流中,所以gets函数把inputData的第一个字符改成了空格,第二个字符是5,覆盖了原先的2,5后面就是换行符了,gets函数会丢弃换行符,并添加一个空字符,我想,这也是puts函数添加换行符的原因,所以空字符覆盖了3。

我们看scanf和gets函数都有一个问题,就是读取数据的话并没有考虑存放数据的字符串的大小,所以这两个函数都存在缓冲区溢出的问题,实际上

  • 如果在visual studio上,gets函数压根就找不到,scanf使用的话也会报C4996的错误
  • 如果在mac上,gets函数会报下面的警告
    warning: this program uses gets(), which is unsafe.

通常,我们有三种方法来解决这个问题:

  1. 使用fgets
  2. 使用gets_s
  3. 自定义一个函数

fgets

fget函数看起来就是读取文件用的,事实上确实如此,gets_s是C11标准才添加的函数,对于之前的C程序,我们可以使用fgets

  • fgets一般有三个参数,第一个参数是读取数据的字符指针,第二个参数设置读取字符的最大值,如果该参数的值是n,则最多只能读取n-1个字符,或者遇到换行符
  • fgets函数读取到换行符后会把他存储到目标字符串中,这点与gets不一样,gets会丢弃换行符,所以,我们输出fgets读取的字符串一般使用fputs,因为fputs不会自动添加换行符。
  • fget的第三个参数指明要读取的文件,对于键盘的输入,我们使用stdio即可
  • fputs通常有两个参数,第一个参数是要打印的字符串指针,第二个参数是指明输出的文件,对于显示器标准输出,我们使用stdout
    下面是一个例子:
讯享网#include <stdio.h> int main() { char inputData[5]; fgets(inputData, 4, stdin); fputs(inputData, stdout); printf("thanks!!"); return 0; } 

如果输入


讯享网

12345 

输出

讯享网123thanks!! 

因为n=4,所以最多输出三个字符123

如果输入

12 

输出

讯享网12 thanks!! 

因为输入了两个字符,还没有达到三个字符的限制,所以后面的换行符也输入进来了

fgets的返回值

fgets返回第一个参数的指针,但是如果fgets读取文件到文件尾的时候,会返回NULL。比如下面例子:

#include <stdio.h> int main(void) { char inputData[1024]; while(fgets(inputData, 1024, stdin)) { fputs(inputData,stdout); } printf("thanks!!\n"); getchar(); return 0; } 

我们使用文件重定向,参考C语言中getchar和putchar
test <src >des
src文件内容如下:

讯享网1 22 333 4444 55555     0000000000 

des文件内容如下:

1 22 333 4444 55555     0000000000thanks!! 

gets_s

C11标准增加的gets_s函数只需要两个参数,第一个参数和gets一致,第二个参数限制大小

  • gets_s相对于fgets,只能从标准输入获取数据
  • gets_s遇到换行符,丢弃他而不是存储他,这点和gets倒是一致
  • 如果gets_s没有遇到换行符并且已经到了最大字符数。该函数会把目标数组的首字符设置为空字符,读取并丢弃后面的数据直到换行符或文件结尾,返回空指针,然后会终止程序

sk_gets

sk_gets是我们要实现的一个处理函数,该函数是gets和fgets的综合体,我实在是对gets_s不感冒

  • sk_gets有两个参数,这个与gets_s一致,sk_gets返回读取到的有效字符数,不包括换行符和EOF
  • sk_gets函数读取到换行符后丢弃换行符,并添加一个空字符
  • sk_gets函数读取到最大值后添加一个空字符并返回
  • sk_puts会自动添加一个换行符

完整代码如下:

讯享网#include <stdio.h> / * 读取一行字符数据 * param:des,目标字符串指针 * param:max,最大读取的字符数据为max-1 * return:返回读取到的有效字符 */ int sk_gets(char* des, int max); / * 输出字符串,输出完成后会自动添加换行符 * param:des,目标字符串指针 * return:返回输出的有效字符个数 */ int sk_puts(char* des); int main(void) { char inputData[1024]; while(sk_gets(inputData, 1024)>0) { sk_puts(inputData); } printf("thanks!!\n"); getchar(); return 0; } int sk_gets(char* des, int max) { char c; int res = 0; while((c=getchar())!='\n' && c!=EOF && --max > 0) { res++; *(des++) = c; } *(des++) = '\0'; return res; } int sk_puts(char* des) { int res=0; while((*des)!='\0') { res++; putchar(*(des++)); } putchar('\n'); return res; } 
小讯
上一篇 2025-01-11 07:58
下一篇 2025-04-11 13:38

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/124389.html