预计阅读本页时间:-
现在让我们把注意力从字符串的输入转移到字符串的输出。这里再次要用到库函数。C有三个用于输出字符串的标准库函数:puts()、fputs()和printf()。
11.3.1 puts()函数
puts()函数的使用很简单,只需要给出字符串参数的地址。程序清单11. 8列出了输出字符串的多种方式。
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
程序清单11.8 put_out.c程序
输出如下:
注意,每一个字符串都单行显示。与printf()不同,puts()显示字符串时自动在其后添加一个换行符。
这个例子让人想起双引号中的字符是字符串常量,并被看作地址。同样,字符数组字符串的名字也被看作是地址。表达式&strl[5]是数组strl的第6个元素的地址。这个元素包含字符‘r’,它也正是puts()输出字符串的起点。与之类似,str2+4指向包含‘i’(“pointer”中的‘i’)的那个内存单元。puts()如何知道何时停止?遇到空字符时它就会停下来,所以应该确保有空字符存在。不要模仿程序清单11.9中的程序!
程序清单11.9 nono.c程序
dont缺少一个表示结束的空字符,因此它不是一个字符串,这样puts()就不知道应该到哪里停止。它只是一直输出内存中dont后面的字符,直到发现一个空字符。为了使这个空字符不太遥远,程序把dont存储在两个真正的字符串之间。下面是一个运行示例:
这里用到的特定的编译器在内存中把side_a数组存储在dont数组之后。因此,put()函数继续执行直到遇到了side_a中的空字符。运行该程序时编译器在内存中存储数据的方式不同,得到的结果也不同。如果程序漏掉了side_a和side_b怎么办呢?通常内存中有很多空字符,如果幸运的话,puts()可能会很快发现一个,但这是很不可靠的。
11.3.2 fputs()函数
fputs()函数是gets()的面向文件版本。两者之间的主要区别是:
● fputs()需要第二个参数来说明要写的文件。可以使用stdout(代表standard output)作为参数来进行输出显示,stdout在stdio.h中定义。
● 与puts()不同,fputs()并不为输出自动添加换行符。
注意,gets()丢掉输入里的换行符,但是puts()为输出添加换行符。另一方面,fgets()存储输入中的换行符,而fputs()也不为输出添加换行符。假定写一个循环,读取一行并把它回显在下一行,可以这么写:
回忆一下,如果遇到文件结尾,gets()就返回空指针。空指针的值为0(也即假),这样就结束了循环。或者也可以这么做:
在第一个循环中,line数组中的字符串被显示在单独的一行上,这是由于puts()为它添加了一个换行符。第二个循环,line数组中的字符串同样被显示在单独的一行上,这是由于fgets()存储了一个换行符。注意,如果把fgets()输入和puts()输出结合使用,每个字符串后就会显示两个换行符。关键在于puts()是为和gets()一起使用而设计的,而fputs()是为和fgets()一起使用而设计的。
11.3.3 printf()函数
在第4章“字符串和格式化输入/输出”中我们详细讨论了printf() 。如同puts()一样,printf()需要一个字符串地址作为参数。printf()函数使用起来没有puts()那么方便,但是它可以格式化多种数据类型,因而更通用。
它们的区别之一就是printf()并不自动在新行上输出每一个字符串。相反,您必须指明需要另起一行的地方。因此:
与下面语句的效果一样:
正如您所见,第一种形式需要键入更多代码,此外计算机的执行时间也更长(但您觉察不到)。不过,printf()使在一行上输出多个字符串变得更为简单。例如,下面的语句把Well、用户名和一个用#define定义的字符串统统显示在一行上: