zoukankan      html  css  js  c++  java
  • 【linux C】C语言中常用的几个函数的总结【二】

    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, 末尾是''的字符数组来存储字符串*/
    5     printf("请输入一个字符串:");
    6     fgets(str, 7, stdin);  /*从输入流stdin即输入缓冲区中读取7个字符到字符数组str中*/
    7     printf("%s
    ", str);
    8     return 0;
    9 }

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

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

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

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

     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中不需要添加'
    ', 因为字符串中已经有了
     9     return 0;
    10 }

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

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

    所以 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);  //后面不要加'
    '
     9     scanf("%c", &ch);
    10     printf("ch = %c
    ", 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可以是字符指针变量名、字符数组名,或者直接是一个字符串常量。功能是将字符串输出到屏幕。输出时只有遇到 '' 也就是字符串结束标志符才会停止

    下面写一个程序:

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

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

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

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

    1 printf("输出结果是:%s
    ", 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(" ");”换行呢?看情况!如果输入时使用的是 gets(),那么就要添加 printf 换行;但如果输入时用的是 fgets(),则不需要

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

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

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

    1 # include <stdio.h>
    2 int main(void)
    3 {
    4     char str[20];  /*定义一个最大长度为19, 末尾是''的字符数组来存储字符串*/
    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, 末尾是''的字符数组来存储字符串*/
    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 头文件中

  • 相关阅读:
    HDU 1874 畅通工程续(dijkstra)
    HDU 2112 HDU Today (map函数,dijkstra最短路径)
    HDU 2680 Choose the best route(dijkstra)
    HDU 2066 一个人的旅行(最短路径,dijkstra)
    关于测评机,编译器,我有些话想说
    测评机的优化问题 时间控制
    CF Round410 D. Mike and distribution
    数字三角形2 (取模)
    CF Round410 C. Mike and gcd problem
    CF Round 423 D. High Load 星图(最优最简构建)
  • 原文地址:https://www.cnblogs.com/xuelisheng/p/10169019.html
Copyright © 2011-2022 走看看