3、fgets

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

fgets() 的原型为:

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

fgets() 虽然比 gets() 安全,但安全是要付出代价的,代价就是它的使用比 gets() 要麻烦一点,有三个参数。它的功能是从 stream 流中读取 size 个字符存储到字符指针变量 s 所指向的内存空间。它的返回值是一个指针,指向字符串中第一个字符的地址

其中:s 代表要保存到的内存空间的首地址,可以是字符数组名,也可以是指向字符数组的字符指针变量名。size 代表的是读取字符串的长度。stream 表示从何种流中读取,可以是标准输入流 stdin,也可以是文件流,即从某个文件中读取。标准输入流就是前面讲的输入缓冲区。所以如果是从键盘读取数据的话就是从输入缓冲区中读取数据,即从标准输入流 stdin 中读取数据,所以第三个参数为 stdin。

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

输出结果是:
请输入一个字符串:i love you
i love

我们发现输入的是“i love you”,而输出只有“i love”。原因是 fgets() 只指定了读取 7 个字符放到字符数组 str 中。“i love”加上中间的空格和最后的 '\0' 正好是 7 个字符

那有人会问:“用 fgets() 是不是每次都要去数有多少个字符呢?这样不是很麻烦吗?”不用数!fget() 函数中的 size 如果小于字符串的长度,那么字符串将会被截取;如果 size 大于字符串的长度则多余的部分系统会自动用 '\0' 填充。所以假如你定义的字符数组长度为 n,那么 fgets() 中的 size 就指定为 n–1,留一个给 '\0' 就行了。

但是需要注意的是,如果输入的字符串长度没有超过 n–1,那么系统会将最后输入的换行符 '\n' 保存进来,保存的位置是紧跟输入的字符,然后剩余的空间都用 '\0' 填充。所以此时输出该字符串时 printf 中就不需要加换行符 '\n' 了,因为字符串中已经有了

 1 # include <stdio.h>
 2 int main(void)
 3 {
 4     char str[30];
 5     char *string = str;  //一定要先给指针变量初始化
 6     printf("请输入字符串:");
 7     fgets(string, 29, stdin);  //size指定为比字符数组元素少一就行了
 8     printf("%s", string);  //printf中不需要添加'\n', 因为字符串中已经有了
 9     return 0;
10 }

输出结果是:
请输入字符串:i love studying C语言
i love studying C语言

我们看到,printf 中没有添加换行符 '\n',输出时也自动换行了。

所以 fgets() 和 gets() 一样,最后的回车都会从缓冲区中取出来。只不过 gets() 是取出来丢掉,而 fgets() 是取出来自己留着。但总之缓冲区中是没有回车了!所以与 gets() 一样,在使用 fgets() 的时候,如果后面要从键盘给字符变量赋值,那么同样不需要清空缓冲区。下面写一个程序验证一下。

 1 # include <stdio.h>
 2 int main(void)
 3 {
 4     char str[30];
 5     char ch;
 6     printf("请输入字符串:");
 7     fgets(str, 29, stdin);
 8     printf("%s", str);  //后面不要加'\n'
 9     scanf("%c", &ch);
10     printf("ch = %c\n", ch);
11     return 0;
12 }

输出结果是:
请输入字符串:i love you
i love you
Y
ch = Y

4、puts

前面在输出字符串时都使用printf,通过“%s”输出字符串。其实还有更简单的方法,就是使用 puts() 函数。该函数的原型为:

1 # include <stdio.h>
2 int puts(const char *s);

这个函数也很简单,只有一个参数。s可以是字符指针变量名、字符数组名,或者直接是一个字符串常量。功能是将字符串输出到屏幕。输出时只有遇到 '\0' 也就是字符串结束标志符才会停止

下面写一个程序:

1 # include <stdio.h>
2 int main(void)
3 {
4     char name[] = "祖国!";
5     printf("%s\n", name);  //用printf输出
6     puts(name);  //用puts()输出
7     puts("我爱你!");  //直接输出字符串
8     return 0;
9 }

输出结果是:
祖国!祖国!我爱你!

可见使用 puts() 输出更简洁、更方便。而且使用 puts() 函数连换行符 '\n' 都省了,使用 puts() 显示字符串时,系统会自动在其后添加一个换行符

但是 puts() 和 printf() 相比也有一个小小的缺陷,就是如果 puts() 后面的参数是字符指针变量或字符数组,那么括号中除了字符指针变量名或字符数组名之外什么都不能写。比如 printf() 可以这样写:

1 printf("输出结果是:%s\n", str);

而 puts() 就不能使用如下写法:

1 puts(输出结果是:str);

因此,puts() 虽然简单、方便,但也仅限于输出字符串,功能还是没有 printf() 强大

5、fputs

fputs() 函数也是用来显示字符串的,它的原型是:

1 # include <stdio.h>
2 int fputs(const char *s, FILE *stream);

s 代表要输出的字符串的首地址,可以是字符数组名或字符指针变量名。

stream 表示向何种流中输出,可以是标准输出流 stdout,也可以是文件流。标准输出流即屏幕输出,printf 其实也是向标准输出流中输出的。

fputs() 和 puts() 有两个小区别:

(1) puts() 只能向标准输出流输出,而 fputs() 可以向任何流输出

(2)使用 puts() 时,系统会在自动在其后添加换行符;而使用 fputs() 时,系统不会自动添加换行符

那么这是不是意味着使用 fputs() 时就要在后面添加一句“printf("\n");”换行呢?看情况!如果输入时使用的是 gets(),那么就要添加 printf 换行;但如果输入时用的是 fgets(),则不需要

因为使用 gets() 时,gets() 会将回车读取出来并丢弃,所以换行符不会像 scanf 那样被保留在缓冲区,也不会被 gets() 存储;而使用 fgets() 时,换行符会被 fgets() 读出来并存储在字符数组的最后,这样当这个字符数组被输出时换行符就会被输出并自动换行。

但是也有例外,比如使用 fgets() 时指定了读取的长度,如只读取 5 个字符,事实上它只能存储 4 个字符,因为最后还要留一个空间给 '\0',而你却从键盘输入了多于 4 个字符,那么此时“敲”回车后换行符就不会被 fgets() 存储。数据都没有地方存放,哪有地方存放换行符呢!此时因为 fgets() 没有存储换行符,所以就不会换行了。

下面写一个程序验证一下:

1 # include <stdio.h>
2 int main(void)
3 {
4     char str[20];  /*定义一个最大长度为19, 末尾是'\0'的字符数组来存储字符串*/
5     printf("请输入一个字符串:");
6     fgets(str, 19, stdin);  /*从输入流stdin中读取19个字符到字符数组str中*/
7     fputs(str, stdout);  //将字符数组的内容输出到输出流stdout中
8     return 0;
9 }

输出结果是:
请输入一个字符串:i love you
i love you
Press any key to continue

我们看到读取 19 个字符足够存储“i love you”,所以 fgets() 最后会存储换行符。这样 fputs() 输出时这个换行符就能换行了。

下面再将读取的字符改小一点看看:

1 # include <stdio.h>
2 int main(void)
3 {
4     char str[20];  /*定义一个最大长度为19, 末尾是'\0'的字符数组来存储字符串*/
5     printf("请输入一个字符串:");
6     fgets(str, 5, stdin);  //从输入流stdin中读取4个字符到字符数组str中
7     fputs(str, stdout);  //将字符数组的内容输出到输出流stdout中
8     return 0;
9 }

输出结果是:
请输入一个字符串:i love you
i loPress any key to continue

我们看到并没有换行。

值得说明的是,虽然 gets()、fgets()、puts()、fputs() 都是字符串处理函数,但它们都包含在 stdio.h 头文件中,并不是包含在 string.h 头文件中

转载于:https://www.cnblogs.com/xuelisheng/p/10169019.html

【linux C】C语言中常用的几个函数的总结【二】相关推荐

  1. c语言中空格字符怎么表示_C语言中常用的字符串操作函数

    作者:陈太浪 出处:https://home.cnblogs.com/u/TomHe789/ C语言中提供了许多的字符串操作函数,常见的字符串操作函数有以下几种: 1.求字符串长度的函数 原型函数:s ...

  2. C语言中常用的字符数组函数

    所有的字符数组处理函数都包括在 <string.h>这个头文件中 一.strlen 函数 原型:size_t strlen(char const* string); 在C语言中如何计算一个 ...

  3. C语言中常用计时方法总结

    转自:http://blog.csdn.net/fz_ywj/article/details/8109368 C语言中常用计时方法总结 1. time() 头文件:time.h 函数原型:time_t ...

  4. c语言计时纳秒_C语言中常用计时方法总结

    转自:http://blog.csdn.net/fz_ywj/article/details/8109368 C语言中常用计时方法总结 1. time() 头文件:time.h 函数原型:time_t ...

  5. c语言中预处理指令的作用,C语言中常用预处理指令

    转载自 https://blog.csdn.net/farsight2009/article/details/58602886 姓名:张艳博 学号:17021223249 [嵌牛导读]: C语言中常用 ...

  6. c语言设置输出字符大小_C语言中常用的几个头文件及库函数

    点击上方"C语言中文社区",选择"设为星标★" 技术干货第一时间送达! 来源:https://www.jb51.net/article/124594.htm 这 ...

  7. 【网络安全入门大总结】—Java语言中常用的渗透漏洞大汇总

    Java语言中常用的漏洞大汇总,建议收藏. 准备好,上课了~~~ 目录 Servlet 简介 生命周期为 接口 Struts 2 . 简介 请求流程 相关CVE Spring 简介 Spring MV ...

  8. JAVA语言异常_Java语言中常用异常类EoFException是用来处理( )异常的类_学小易找答案...

    [填空题]Java语言中常用异常类ClassNotFoundException是用来处理 ( )的异常的类 [填空题]Java语言声明 ( ) 类为会产生"严重错误"的类 [简答题 ...

  9. c语言中常用的输入输出函数有哪些,C语言中常用的输入和输出函数

    C语言中常用的输入和输出函数 2020年03月11日 | 萬仟网IT编程 | 我要评论 1. scanf()函数 (Scan Format) + 函数原型: + 函数作用:从标准输入流 stdin ( ...

最新文章

  1. 全球IT支出保持稳定增长 中国IT支出将超2.3万亿元
  2. 关于卡券系统设计--待续
  3. python 异常和弹出框
  4. SQLServer知识:sqlcmd用法笔记
  5. python画散点图-Python:matplotlib绘制散点图
  6. Linux 如何查看是否开启journal
  7. aspmysql发布_ASP如何使用MYSQL数据库
  8. Machine Learning - week 4 - Non-linear Hypotheses
  9. 搭配-最全的配色方案和色彩搭配
  10. JAVA-CPU飙高问题排查
  11. 制造业数字化转型的意义是什么?
  12. 【游戏开发引擎】 实验3:Captain Blaster 2D 滚动射击游戏
  13. Markdown入门指南 --写博客,word必备技术
  14. Python networkx 根据节点坐标来画网络图
  15. EFM32G232F64时钟树
  16. matlab lms算法,LMS算法
  17. 火车票余票计算的一种方法
  18. 编译原理 --- 高级程序设计语言概述
  19. Java使用Openoffice将word、ppt转换为PDF
  20. Acwing算法基础【1】基础(三)前缀和与差分

热门文章

  1. 深度学习之正则化方法
  2. python_day29_通过类创建多线程_队列
  3. SQA计划和验收测试规程设计
  4. thinkphp5.0自定义验证器
  5. 把Excel中的数据转换成Sql语句
  6. Scalaz(1)- 基础篇:隐式转换解析策略-Implicit resolution
  7. JS设计模式——10.门面模式
  8. c# 去除字符串中的换行符 \r\n
  9. pattern recognition and machine learning基本思想1:最大似然估计
  10. tika提取html,TIKA内容提取