C语言

【C语言入门到精通 03】格式化输入/输出

2020-03-28  本文已影响0人  不会编程的程序圆

03 格式化输入/输出

A programming language is low level when its programs require attention to the irrelevant.[1]

码字不易,对你有帮助 点赞:thumbsup:/转发:arrow_right_hook:/关注 :eyes: ** 支持一下作者
微信搜公众号:
不会编程的程序圆**
看更多干货,获取第一时间更新

想看更好的文章排版,可以阅读原文:

【C语言入门到精通】03 格式化输入/输出

请将本片与下一节《数据类型》 联系起来一起“食用”。

注:本教程含有超纲内容!!!如果你看不懂,不要丧失信心,可以“不求甚解”一些,关键是要多写代码!然后继续学习下面的内容!

:world_map:思维导图


image

:email:写在前面


如果只是写个人学习总结的博客很容易,简单写一些感悟然后贴上代码走人就可以了,甚至不用校审。但是我命名本系列为【C语言必知必会】帮助你从入门到精通 C语言,那势必要“事无巨细”一些:既要考虑到没有基础的初学者,又不能止于基础。所以本教程适合各类人群学习,只要你看就一定会有帮助。

本教程是本人纯手打并排版,校审由我与我的搭档汤圆君一起完成的。你们看这一篇文章我要写好几个小时。如果文章对你有帮助,请不要“白嫖”。支持一下作者,作者会发更多干货好文。

特别鸣谢:汤圆君(公众号:【Cc听香水榭】 长期更新高质量英语教学)关注她表示对她工作的认可吧!

:arrow_forward: 此符号表示该内容以后的章节会讲解,此章节内不要求理解。

:globe_with_meridians:目录


@[toc]

printf 函数

printf()函数打印数据的指令要与待打印数据的类型相匹配。例如,打印整数时使用 %d,打印字符时使用 %c 。这些符号被称为转换说明(conversion specification),它们指定了如何把数据(以2进制形式)转换成可显示的形式。

例如:

printf("I am %d years old", 18);
image

这是 printf()的格式:

printf(格式字符串,待打印项1,待打印项2,...);

待打印项都是要打印的的项。它们可以是变量,常量,甚至是在打印之前计算的表达式。上例中,只有一个待打印项: 18 。

格式字符串包含两种不同信息:


:warning:

C语言的编译器不会检测格式字符串中转换说明中的数量与待打印项总个数是否相匹配。

1.缺少参数

printf("%d %d\n", i); // wrong

printf 会正确显示 i 的值,然后显示一个无意义的整数值。

2.参数过多

printf("%d\n", i, j);// wrong

而在这种情况下,printf 函数会显示变量 i 的值,但是不会显示变量 j 的值


printf 转换说明

转换说明这部分我做了很久,比较详细,配合下一章数据类型才能看懂大部分,剩下的就需要你在不断使用的过程中领悟了。

image

printf() 返回值

返回值:传输到输出流(显示器)的字符数,若出现输出错误或编码错误(对于字符串和字符转换指定符)则为负值

返回类型:int

使用场景:检查输出错误。(看输出的字符数是否正确)

#include<stdio.h>

int main(void) {

   int count;
   
   count = printf("Hello!\n");

   printf("%d\n", count);

   return 0;
}

输出:

Hello!
7

打印较长字符串

允许的换行方式:

printf("Hello %s\n", 
       XiaoHuang);//为了让读者知道该行未完,可以使用缩进

错误的换行方式:

printf("Hello 
       %s\n", XiaoHuang);

如果想在双引号括起来的格式字符串中换行,应该这样写:

  1. printf("Hello");
    printf (" %s\n", XiaoHuang);
    
  2. printf("Hello\
    %s\n", XiaoHuang);
    
  3. printf("Hello"
     " %s\n", XiaoHuang);// ANSI C
    

方法1:使用多个 printf 语句

方法2:在要换行的地方加上反斜杠( \ )来断行。但是,下一行的代码必须从该行最左端开始,不然输出会包含你所缩进的空白字符。

方法3:ANSI C 引入的字符串连接。C 编译器会将多个字符串看作一个字符串。

scanf() 函数

我们从键盘输入的都是文本,因为键盘只能生成文本字符:字符,数字和标点符号。如果要输入整数 2014,就要键入2,0,1,4.如果要将其存储为数值而不是字符串,程序就必须要把字符依次转换成数值,这就是 scanf() 要做的。

scanf() 把输入的字符串转换成整数,浮点数,字符和字符串,而 printf() 正好与之相反,把整数,浮点数,字符,字符串转换成显示在屏幕上的文本。

scanf() 与 printf() 类似,也要使用 格式字符串 和 参数列表。scanf() 中的格式字符串表明字符输入流的目标数据类型。两个函数的主要区别在于参数列表中。printf() 函数使用变量,常量和表达式,而 scanf() 函数使用指向变量的指针​(:arrow_forward:)。这里不需要了解指针,只需要记住一下简单的两条:

用 scanf 读取

下面的程序演示了这两条规则:

input.c —— 何时使用 &

#include<stdio.h>
int main(void){
    
    int age;
    float assets;
    char pets[30];//字符数组,存放字符串
    
    printf("Enter you age, assets and you favorite pet.\n");
    scanf("%d %f", &age, &assets); // 这里要用 &
    scanf("%s", pets);// 字符数组不使用 &
      
    return 0;
}

:warning:

初学者在使用 scanf 时,在应该写 & 的时候容易忽略 & ,所以每次使用 scanf 的时候一定要格外小心。通常情况下,必要的地方缺少 & 会让程序崩溃(编译器没有警告),但是也有时候程序并不会崩溃,这时候找 bug 可能会让你头痛。


scanf 的 长度修饰符 和 转换说明符 与 printf 几乎相同。主要的区别如下:

进一步思探究 scanf()

在上面了解了 scanf 的基本情况后,我们进一步探究 scanf 函数。

上面的例 2,为何只是输出了 "123", 我们明明还输入了一组 123,为什么没有输出呢?

scanf 函数如果发生了 输入失败(没有字符输入)或 匹配失败 (即输入字符和格式串不匹配),那么...scanf 会提前返回。返回就意味着这个 scanf 的读入结束。

scanf 返回的又是什么呢?

成功赋值的接收参数的数量(可以为零,在首个接收用参数赋值前匹配失败的情况下),或者若输入在首个接收用参数赋值前发生失败,则为EOF(EOF 的值是 -1)。

在C程序中测试 scanf 函数的返回值的循环很普遍。例如,下面的循环逐一读取一串整数,在首个遇到问题的符号处停止:

while(scanf("%d", &i) == 1){
    ...
}

对于 scanf 部分最开始的程序 input.c

如果我们这样先输入:

18 98.5
diandian

再这样输入:

  18
98.5


    diandian

如果你添加上 printf 语句输出这三项,会发现,这两种输入的输出是一样的。

在寻找起始位置时,scanf 函数会忽略空白字符(white-space character,包括空格符,水平和垂直制表符,换页符和换行符),但是%[ , %c, %n除外。例 5

例 5:

#include<stdio.h>
int main(void) {

    char ch = 'a';
    char str[10] = "hi";

    scanf("%c", &ch);
    scanf("%[123]", str);

    printf("%c %s", ch, str);


    return 0;
}
//输入: b (输入的是:空格 + b,然后按下回车键想接着输入下一个 scanf)
//输出: hi

这个例子除了证明了上面的结论,还说明了:

但是 scanf 函数会忽略最后的换行符,实际上它没有读取它,这个换行符时下一次 scanf 函数读入的第一个字符。

scanf 函数遵循什么规则来识别整数或浮点数呢?

在要读入整数时,scanf 函数首先会寻找正号或负号,然后从读入一个数字开始直到读入一个非数字为止。

当要求读入浮点数时,scanf 函数首先会寻找正号或负号(可选),然后是一串数字(可能含有小数点),再后是一个指数(可选)。指数由一个字母e,可选的符号,一个或多个数字组成。

当 scanf 函数遇到一个不可能输入当前项的字符时,它会把此字符“放回原处”,以便在扫描下一项或下一次调用 scanf 时再次读入。思考下面(公认有问题的)4个数的排列:

1-20.3-4.0e3回车

然后我们用这个 scanf 函数来读入:

scanf("%d%d%f%f", &i, &j, &x, &y);

scanf 会如何处理这组输入呢?

使用 %s 转换说明,scanf 会读取除了空白字符以外的所以字符。scanf 跳过空白字符并开始读入第一个非空白字符,保存非空白字符直到再遇到空白字符结束。这意味着,scanf 最多只能读取一个单词。无法利用字段宽度使得 scanf 读取多个单词,scanf 会在字段宽度结束或遇到空白字符处停止。scanf 将字符串放入数组时,会在字符串序列末尾加上一个 \0

格式串中的普通字符

**空格你可以随便空,换行都可以随便换,但是一定要打 ''-'' 符号。**

易混淆的 printf() 与 scanf()

  1. printf("%d", &i);
    

    输出的并不是 i 的值 (而是 i 的地址的十进制数值)

  2. scanf("%d, %d", &i, &j);
    

    scanf 在第一个 %d 读入一个整数后,试图把逗号与输入流中的下一个字符相匹配,如果这个字符不是 ,,那 scanf 就会终操作,而不再读取变量 j 的值。

  3. scanf("%d\n", &i);
    

    printf 函数中经常有 \n ,但是如果在 scanf 格式串结尾放一个 \n 通常会引发你预期之外的问题。

    对于 scanf 函数来说,\n 等同于空格,那么 scanf 就会在流中寻找空白字符,但是我们上面说过,scanf 格式串中的空白字符会与 输入流中的零个或多个空白字符匹配。所以当你输入完成后按下回车,这个回车会与 scanf 中的 \n 匹配,之后你无论打多少回车都不会使 scanf 结束,除非你输入一个非空字符,使 scanf 因匹配失败而退出。

参考资料:《C Primer Plus》《C语言程序设计:现代方法》


本文GitHub已收录,所有教学和练习代码都会上传上去。

https://github.com/hairrrrr/C-CrashCourse

如果对你有帮助,请点一个 star:star: 呦~ ​ 感谢!:love_letter:

以上就是本次的内容。

如果文章有错误欢迎指正和补充,感谢!

最后,如果你还有什么问题或者想知道到的,可以在评论区告诉我呦,我可以在后面的文章加上你们的真知灼见:eye:。

关注我,看更多干货!

我是程序圆,我们下次再见。:fallen_leaf:


  1. 任何编程语言在处理无关事务时都是低级语言。

上一篇 下一篇

猜你喜欢

热点阅读