在C Primer Plus这本书里, s_gets函数出现了很多次,对此函数不理解的话可以阅读下面的解析和例程,相信你会豁然开朗

1. s_gets函数原型

char *s_gets(char *st, int n)
{  char *ret_val;  char *find;  ret_val = fgets(st, n, stdin);    // 从stdin中读取n-1个字符if(ret_val)  {  find = strchr(st, '\n');    // 查找换行符if(find)  {  *find = '\0';  }  else  {  while(getchar() != '\n')  continue;  }  }  return ret_val;
}

接下来对内部的函数进行分析

fgets()

虽然用 gets() 时有空格也可以直接输入,但是 gets() 有一个非常大的缺陷,即它不检查预留存储区是否能够容纳实际输入的数据,换句话说,如果输入的字符数目大于数组的长度,gets 无法检测到这个问题,就会发生内存越界,所以编程时建议使用 fgets()。

fgets() 的原型为:

# include <stdio.h>
char *fgets(char *s, int size, FILE *stream);

它的功能是从 stream 流中读取 size 个字符存储到字符指针变量 s 所指向的内存空间。它的返回值是一个指针,指向字符串中第一个字符的地址。

/*** @brief fgets()函数获取一整行输入:*          读取输入直达换行符(换行符也被读取),或者读到文件结尾,或者读取(n-1)个字符*          读取完成后,再在读取内容末尾添加空字符'\0',使读取内容成为一个字符串* @param str 指向一个字符数组,该数组存储了要读取的字符串。* @param n 这是要读取的最大字符数* @param stream FILE*指针,指明要读入的文件,如果是键盘输入,则以stdin(标准输入)作为参数* @return char* 如果返回成功,则返回值与char* str参数相同,如果到达文件末尾或者没有读取到任何字符,str 的内容保持不变,并返回一个空指针*               如果发生错误,返回一个空指针。*/
char *fgets(char *str, int n, FILE *stream)

示例程序:

# include <stdio.h>
int main(void)
{char str[20];  /*定义一个最大长度为19, 末尾是'\0'的字符数组来存储字符串*/printf("please input:");fgets(str, 7, stdin);  /*从输入流stdin即输入缓冲区中读取7个字符到字符数组str中*/printf("%s\n", str);return 0;
}

输出的结果只保留了六个char,因为还有一个是结束字符。

strchr

/*** @brief strchr()函数寻找参数 str 所指向的字符串中搜索第一次出现字符 c(一个无符号字符)的位置* * @param str * @param c * @return char* 该函数返回在字符串 str 中第一次出现字符 c 的位置,如果未找到该字符则返回 NULL*/
char *strchr(const char *str, int c)

示例程序:

#include <stdio.h>
#include <string.h>
int main ()
{const char str[] = "http://www.runoob.com";const char target = '.';char *ret;ret = strchr(str, target);  // 从str中寻找ch,返回值为一个指向ch的指针printf("|%c| after - |%s|\n", target, ret);   // |.| after - |.runoob.com|return(0);
}

回到s_gets()

s_gets函数主要做的就是将回车找出并转换为字符串结尾标志’\0’,便于输出结果。

测试例程:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>char *s_gets(char *st, int n)
{char *ret_val;char *find;ret_val = fgets(st, n, stdin);    // 从stdin中读取n-1个字符,保存在st中if(ret_val)  // 如果发生错误,则会返回空指针,所以进入if的条件是成功读取了n-1个字符{find = strchr(st, '\n');    // 查找换行符if(find)  // 找到了换行符,说明输入的字符不足n-1个{*find = '\0';  // 替换为结束字符}else  // 输入的字符多于n-1{while(getchar() != '\n')  continue;}}return ret_val;
}
int main(int argc, char *argv[])
{char test[10] = {};while(1){s_gets(test, 10);printf("output: %s \n", test);}return 0;
}
// 运行结果是每次只读取一行中前九个字符

else中对应的情况是键盘输入的字符串长度大于(n-1),那么st存储了(n-1)个字符后,再加上1个 ‘\0’ ,成为字符串。此时在输入输出缓冲区中,还存在着没被st存储的剩余的字符,如果不处理这些字符,那么在主程序的下一次读取中,会从缓冲区读取这些剩余字符。

s_gets函数详解相关推荐

  1. C语言网络编程:accept函数详解

    文章目录 前言 函数描述 代码实例 如何得到客户端的IP 和 端口号 前言 当使用tcp服务器使用socket创建通信文件描述符,bind绑定了文件描述符,服务器ip和端口号,listen将服务器端的 ...

  2. 【FFmpeg】函数详解(三)

    FFmpeg函数详解 14.av_write_frame 15.av_interleaved_write_frame 16.av_write_trailer 17.avio_close 18.av_i ...

  3. 【FFmpeg】函数详解(二)

    FFmpeg函数详解 9.av_dump_format 10.avio_open 11.avformat_write_header 12.avcodec_send_frame 13.avcodec_r ...

  4. 【FFmpeg】函数详解(一)

    FFmpeg函数详解 一.错误码相关 1.AVERROR 2.av_strerror 3.其他错误码解释 二.编解码 1.获取编解码器 2.申请.释放上下文环境 3.打开编码器avcodec_open ...

  5. 【ES6】Generator函数详解

    [ES6]Generator函数详解 一.Generator函数简介 基本概念 函数写法 yield关键字介绍 二.next方法的参数 三.for...of循环 四.关于普通throw()与Gener ...

  6. mysql的聚合函数综合案例_MySQL常用聚合函数详解

    一.AVG AVG(col) 返回指定列的平均值 二.COUNT COUNT(col) 返回指定列中非NULL值的个数 三.MIN/MAX MIN(col):返回指定列的最小值 MAX(col):返回 ...

  7. python平方数迭代器_对python中的高效迭代器函数详解

    python中内置的库中有个itertools,可以满足我们在编程中绝大多数需要迭代的场合,当然也可以自己造轮子,但是有现成的好用的轮子不妨也学习一下,看哪个用的顺手~ 首先还是要先import一下: ...

  8. python基础知识~ 函数详解2

    python~函数详解2  1 生成器函数    定义 如果函数有yield这个关键字,就是生成器函数.生成器函数() 获取的是生成器,不执行函数   须知 yield和return一样,都可以返回数 ...

  9. scanf函数详解与缓冲区

    1.基本信息 函数原型: int scanf( char *format, args, ...); 函数返回值: 读入并赋给args的数据个数,遇到文件结束返回EOF,出错返回0. 函数功能: sca ...

最新文章

  1. 2021年大数据Hadoop(十五):Hadoop的联邦机制 Federation
  2. count http://www.cplusplus.com/reference/algorithm/count/
  3. 加载cv2调用摄像头_用Python获取摄像头并实时控制人脸
  4. Java8 Optional类
  5. 【Python】Matplotlib绘制带颜色标尺的彩色曲面
  6. java变量传递给asp,我应该如何将多个参数传递给ASP.Net Web API GET?
  7. 香港中文大学(深圳)张大鹏教授项目组招聘PhD
  8. keil及iar调试解释
  9. 推荐个我在用的免费翻译软件,支持多家翻译API整合
  10. linux安装rz sz命令不能用,Linux下如何安装rz和sz命令
  11. 重磅报告 | 《中国企业2020:人工智能应用实践与趋势》
  12. H5前端实现微信分享(处理二次分享问题)
  13. 关于LNK2005 _main 已经在 某某某.obj 中定义的问题
  14. Postgres-XL集群的搭建和测试详解
  15. 原生app登录 后台方案(token方案)
  16. springboot的jsp应该放在哪_七、SpringBoot项目集成JSP以及项目不同启动方式及访问路径配置...
  17. 超级玛丽2号max即将停售定期?是谣言还是确有其事,有啥影响
  18. 编程语言是怎么发展的?
  19. java 读取excel模板_java如何读取excel表格的信息,java读取excel模板
  20. 网易游戏如何做到不停服维护?

热门文章

  1. 文字转换为语音VB.NEt实现
  2. 从金拱门餐厅联想到的分布式系统设计思维
  3. python实现图片切正方形
  4. Lenovo联想笔记本电脑 拯救者Legion Y7000P 2019(81Q5)原装Win10系统恢复出厂OEM系统
  5. 读书笔记_011《肖申克的救赎》
  6. 新手入门启动光盘制作最详细的教程
  7. linux ntfs分区转换,Ubuntu下将NTFS分区转换成Linux的ext3分区格式
  8. 【Ware】Guide下载
  9. bcftools csq分析基因突变对蛋白水平的影响
  10. 史上对当今中国医院最强的讽刺