• 标准输出printf与标准输入scanf


    一、标准输出printf

      头文件: stdio.h

      原型: int printf(const char *format, ...);

      参数:    

               format: 格式控制字符串

          ...: 可变参数列表

      返回值:输出字符的数量。

      注意点:

        对于标准输出printf,我们需要注意的是返回值,很多人会忽略返回值的类型和代表的含义。

    二、标准输入scanf

      头文件:stdio.h

      参数:

        format:格式控制字符串

        ...:可变参数列表

      返回值:成功读入的参数个数

      注意点:

        1)分隔符,scanf中,默认会把空格,回车换行,tab字符当成是分隔符,对格式控制字符串分隔称子串来并与后面的可变参数列表进行匹配,如果需要修改分隔符,需要用正则表达式来指定。

        2)返回值,scanf函数的返回值表示成功读入的参数的个数,类型为int型。

    三、例程

    1,请使用printf函数,求解一个数字n的十进制表示的数字位数

     1 //1.test.c
     2 #include <stdio.h>
     3 
     4 int main(void) {
     5     int n;
     6     while (scanf("%d", &n) != EOF) {
     7         printf(" has %d digits!
    ", printf("%d", n));
     8     }
     9     
    10     return 0;
    11 } 

      首先,上述代码需要注意的点为EOF(end of file),Linux有一句名言--一切皆文件,对于二进制值EOF,表示的是文件结尾,对于标准输入而言,就是输入已经到达结尾,在Linux中我们用ctrl+D表示EOF,window为ctrl+Z。

           ydq@ubuntu:20201013$ gcc 1.test.c
           ydq@ubuntu:20201013$ ./a.out
           1234
           1234 has 4 digits!                --》如果想结束输入,可以按下键盘ctrl+D表示输入结束(EOF)。
           ydq@ubuntu:20201013$

      现在1.test.c就是用来测printf返回值的代码,通过运行结果我们可以知道printf函数返回值就是代表输出的字符数量。

    2.请写一个程序,读入一行字符串(可能包含空格),输出这个字符串(可能包含空格),输出这个字符串中字符的数量。

      例如

      输入:Hello world!

      输出:Hello world!

      首先我们给出version1代码。

     1 //2.test_version.c
     2 #include <stdio.h>
     3 
     4 int main(void) {
     5     char str[100] = {0};
     6     while (scanf("%s", str) != EOF) {
     7         printf("str: %s
    ", str);
     8     }
     9     return 0;
    10 }

      ydq@ubuntu:20201013$ g++ 2.test_version1.c
      ydq@ubuntu:20201013$ ./a.out   
      Hello world!
      str: Hello
      str: world!
      ydq@ubuntu:20201013$

      第一个版本,我们运行出来的结果是分开的两个字符串,分别为Hello和world!,在这里就是默认分隔符起的作用,所以我们得在version2解决这个问题。

     1 //2.test_version2.c
     2 #include <stdio.h>
     3 
     4 int main(void) {
     5     char str[100] = {0};
     6     while (scanf("%[^
    ]s", str) != EOF) { //[] -- 指定匹配模式,[^
    ]表示除了换行符之外,其他字符全部读入 
     7         printf("str: %s
    ", str);
     8     }
     9     return 0;
    10 }

      ydq@ubuntu:20201013$ ./a.out > output.txt
      Hello world!
      ^C

      在这里我们把输出结果重定向到文件output.txt,再通过vim命令去打开该文件查看它里面的内容。

      ydq@ubuntu:20201013$ vi output.txt
      1 str: Hello world!, ret = 1
      2 str: Hello world!, ret = 0
      3 str: Hello world!, ret = 0
      4 str: Hello world!, ret = 0
      5 str: Hello world!, ret = 0
      6 str: Hello world!, ret = 0
      7 str: Hello world!, ret = 0
      8 str: Hello world!, ret = 0  --》不止怎么多行,文件接下来有很多行。

      首先ret是scanf的返回值,这里我们第一次就已经成功把Hello world!读入并赋值到str数组中,其中返回值为0,接下来scanf还是一直返回0,表示成功读入0个参数,这时候是不是很奇怪,其实在标准输入和标准输入有缓冲区的概念,首先我们在键盘输入的字符串Hello world!最先开始的时候是存储到输入缓冲区,当遇到是遇到换行符或缓冲区满之后或程序结束后才输出缓冲,当我们在键盘输入Hello world!跟回车 的时候,这些字符串首先会被存入到输入缓冲区中,而由于我们在格式控制字符串中指定[^ ](除了换行符之外,其他字符全部输入),在缓冲区中,只能成功读出缓冲区的Hello world!赋值给str,而 永远都存在缓冲区中,只要缓冲区中有数据,scanf函数就会一直会返回。接下来我们会给出version3,解决 一直存在缓冲区的问题。

     1 //2.test_version3.c 
     2 #include <stdio.h>
     3 
     4 int main(void) {
     5     char str[100] = {0};
     6     int ret;
     7     while ((ret = scanf("%[^
    ]s", str)) != EOF) { //[] -- 指定匹配模式,[^
    ]表示除了换行符之外,其他字符全部读入
     8         getchar(); //强制从输入缓冲区中读出一个字符.
     9         printf("str: %s, ret = %d
    ", str, ret);
    10     }
    11     return 0;
    12 }

      这里,我们调用getchar()函数,强制从缓冲区中读出一个字符,这样就可以解决 一直存在输入缓冲区的情况了。

      ydq@ubuntu:20201013$ ./a.out
      Hello world!
      str: Hello world!, ret = 1
      ydq@ubuntu:20201013$

      至此,我们version3版本已经可以完成题目的要求。

  • 相关阅读:
    .NET 低版本调用高版本DLL问题
    防止SQL注入攻击
    Vue集成vue-pdf进行pdf预览
    VS2017序列号|Visual Studio 2017 激活码 序列号
    Java 使用word文档模板下载文件(内容为表格)
    接收sql语句的返回值
    ajax返回数据之前的loading等待
    在客户端展示本地图片
    C# 使用cookie实现登录
    C#请求http向网页发送数据,网页接收
  • 原文地址:https://www.cnblogs.com/ydqblogs/p/13823910.html
Copyright © 2020-2023  润新知