栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

《C程序设计语言》笔记 第7章 输入与输出

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

《C程序设计语言》笔记 第7章 输入与输出

本章讲讲述标准库,介绍输出/输出、字符串处理、存储管理与数学函数以及其他一些服务的函数。本章的重点将放在输入/输出上。

7.1 标准输入/输出

如第1章所述,标准库实现了简单的文本输入/输出模型。文本流由一系列行组成,每一行以一个换行符结尾。如果系统没有遵循这种模型,则标准库会通过一些措施使其看起来遵循了这种模型。例如,标准库可能在输入时将回车符(carriage return, CR, r)和换行符(line feed, LF, n)都转换为换行符,而在输出时进行反向转换。

注:不同操作系统的默认换行符是不同的,Windows是CRLF (rn),Unix/Linux是LF (n),macOS是CR (r),参考:

  • Carriage Return, Line Feed and New Line
  • The Great Newline Schism

最简单的输入机制是使用getchar函数从标准输入(一般为键盘)一次读取一个字符。getchar函数在每次被调用时返回下一个输入字符,如果遇到文件结尾则返回EOF。符号常量EOF定义在中,其值一般为-1,但程序中应该使用名字EOF来测试从而不依赖于特定值。

函数putchar(c)将字符c送至标准输出(默认为屏幕)。putchar返回输出的字符,如果发生错误则返回EOF。函数printf也将输出发送到标准输出,可以和putchar函数交替使用。

使用输入/输出库函数的源文件必须包含#include 。

在命令行中,可以使用<符号来重定向输入,将键盘输入替换为文件输入:如果程序prog中使用了函数getchar,则命令行

prog  

将使得程序prog从输入文件infile(而不是键盘)读取字符。

类似地,可以使用>符号来重定向输出:

prog >outfile

将程序prog的标准输出重定向到文件outfile。

字符串 “outfile” 不包含在命令行参数argv中。

管道(pipe)机制也可以用于重定向标准输入/输出:

prog | otherprog

将程序prog的标准输出重定向到程序otherprog的标准输入。

注:Windows CMD和Linux Shell命令行都支持输入/输出重定向和管道机制。

对于只从一个输入流读取数据、只向一个输出流写入数据的程序,使用getchar、putchar和printf函数实现输入/输出就足够了。考虑程序lower,将输入转换为小写形式:

将输入转换为小写形式

例如,假设编译出的可执行文件为lower.out,则命令行

./lower.out  

将文件a.txt的内容转换为小写并打印到标准输出;

利用打印文件的Linux命令cat或Windows命令type(1.5.1节编写过类似功能的程序)和管道机制,以下命令和上面的等价:

cat a.txt | ./lower.out  # Linux
type a.txt | lower.exe  # Windows

输入/输出重定向可以同时使用:

./lower.out b.txt

将文件a.txt的内容转换为小写并输出到文件b.txt。

练习7-1 编写一个程序,根据它被调用的名字(argv[0])实现将大写字母转换为小写或将小写字母转换为大写的功能。

7.2 格式化输出——printf

输出函数printf将内部值(整数、浮点数等)转换为字符。本节将介绍该函数最典型的用法。

int printf(char *format, arg1, arg2, ...)

printf函数在format的控制下,对其参数进行转换与格式化,并在标准输出上打印出来。它返回打印的字符数。

格式字符串包含两种对象:普通字符和转换说明(conversion specification)。普通字符将被原样复制到输出流,而每一个转换说明将转换并打印printf的下一个参数。每个转换说明以%开始、以转换字符结束。在%和转换字符之间可能依次包含:

  • 负号,指定左对齐
  • 数字,指定最小宽度,如果大于实际宽度则用空格填充(默认右对齐)
  • 小数点,用于分隔宽度和精度
  • 数字,指定精度,即字符串要打印的最大字符数、浮点数小数点后的位数,或者整数要打印的最少数字数目
  • 字母h或l,h表示将整数作为short类型打印,l表示将整数或浮点数作为long类型打印

下表列出了所有的转换字符。如果%后面的字符不是转换说明,则行为是未定义的。

转换字符参数类型输出形式
d, iint十进制整数
oint无符号八进制整数(没有前导0)
x, Xint无符号十六进制整数(没有前导0x或0X)
uint无符号十进制整数
cint字符
schar *字符串,直到遇到''或由精度指定的字符数为止
fdouble浮点数,其中小数位数由精度指定(默认为6)
e, Edouble浮点数科学记数法,小数位数由精度指定(默认为6)
g, Gdouble浮点数,有效数字位数由精度指定(默认为6),如果指数小于-4或大于等于精度则使用%e或%E,否则使用%f,尾部的0和小数点不打印
pvoid *指针
%不转换参数,打印一个%

在转换说明中,宽度或精度可以指定为*,此时宽度或精度的值由下一个参数(必须是int类型)指定。例如,下列语句打印字符串s的至多max个字符:

printf("%.*s", max, s);

(注:转换说明%.*s将“消耗”两个参数)

下表展示了在打印字符串"hello, world"(12个字符)时不同转换说明的效果(在两端添加了冒号):

%s        :hello, world:
%10s      :hello, world:
%15s      :   hello, world:
%-10s     :hello, world:
%-15s     :hello, world   :
%.10s     :hello, wor:
%.15s     :hello, world:
%15.10s   :     hello, wor:
%-15.10s  :hello, wor     :

下表是打印浮点数1234.5678时不同转换说明的效果:

%f        :1234.567800:
%8f       :1234.567800:
%15f      :    1234.567800:
%-8f      :1234.567800:
%-15f     :1234.567800    :
%.2f      :1234.57:
%.8f      :1234.56780000:
%15.2f    :        1234.57:
%-15.2f   :1234.57        :

%e        :1.234568e+03:
%8e       :1.234568e+03:
%15e      :   1.234568e+03:
%-8e      :1.234568e+03:
%-15e     :1.234568e+03   :
%.2e      :1.23e+03:
%.8e      :1.23456780e+03:
%15.2e    :       1.23e+03:
%-15.2e   :1.23e+03       :

%g        :1234.57:
%8g       : 1234.57:
%15g      :        1234.57:
%-8g      :1234.57 :
%-15g     :1234.57        :
%.2g      :1.2e+03:
%.8g      :1234.5678:
%15.2g    :        1.2e+03:
%-15.2g   :1.2e+03        :

下表是打印整数12345678时不同转换说明的效果:

%d        :12345678:
%6d       :12345678:
%15d      :       12345678:
%-6d      :12345678:
%-15d     :12345678       :
%.6d      :12345678:
%.10d     :0012345678:
%15.10d   :     0012345678:
%-15.10d  :0012345678     :

注意:printf函数使用第一个参数(格式字符串)判断后面参数的个数及类型。如果参数的个数不够或者类型错误,则将得到错误的结果。注意下面两个函数调用之间的区别:

printf(s);        
printf("%s", s);  

函数sprintf执行与函数printf相同的转换,但将结果保存到一个字符串中,而不是标准输出:

int sprintf(char *output, char *format, arg1, arg2, ...);

字符串output必须足够大以存放输出结果。

练习7-2 编写一个程序,以合理的方式打印任意输入。该程序至少能够根须用户习惯以八进制或十六进制打印非图形字符,并截断长文本行。

7.3 变长参数表

本节通过实现printf函数的一个最简单版本minprintf来介绍如何以可移植的方式编写处理变长参数表的函数。由于重点关注参数处理,minprintf只处理格式字符串和参数,而通过调用printf函数实现格式转换。

printf函数的正确声明形式为

int printf(char *format, ...);

其中省略号表示这些参数的数量和类型是可变的。省略号只能出现在参数表的尾部。

minprintf函数声明为

void minprintf(char *format, ...);

编写minprintf函数的关键在于如何处理一个甚至连名字都没有的参数表。 标准头文件 包含一组宏定义,它们定义了如何遍历参数表。该头文件在不同机器上的实现是不同的,但提供的接口是一致的。

  • va_list类型用于声明一个变量,该变量将依次引用各参数(在minprintf中,该变量称为ap,意思是“参数指针”)
  • 宏va_start将ap初始化为指向第一个无名参数的指针。在使用ap之前,该宏必须被调用一次。参数表必须至少包括一个有名参数,因为va_start将最后一个有名参数作为起点。
  • 每次调用va_arg都将返回一个参数,并将ap指向下一个参数
  • va_end完成必要的清理工作,它必须在函数返回之前调用

简化的printf函数实现如下:

minprintf函数

练习7-3 改写minprintf函数,是它能完成printf函数的更多功能。

7.4 格式化输入——scanf 7.5 文件访问 7.6 错误处理——stderr和exit 7.7 行输入和输出 7.8 其他函数
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/947633.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号