11.3 字符串输出
C有3个标准库函数用于打印字符串:puts()、fputs()和printf()。
11.3.1 puts()函数
只需把字符串的地址作为参数传递给puts()函数即可使用。
/* put_out.c -- using puts() */
#include
#define DEF "I am a #defined string."
int main(void)
{
char str1[80] = "An array was initialized to me.";
const char * str2 = "A pointer was initialized to me.";
puts("I'm an argument to puts().");
puts(DEF);
puts(str1);
puts(str2);
puts(&str1[5]);
puts(str2+4);
return 0;
}
/* 输出:

*/
puts()会自动在字符串末尾添加一个换行符。
用双引号括起来的内容是字符串常量,且被视为该字符串的地址。另外,存储字符串的数组名也被看作是地址。
puts()在遇到空字符时就停止输出,所以必须确保有空字符。
/* nono.c -- no! */
#include
int main(void)
{
char side_a[] = "Side A";
char dont[] = {'W', 'O', 'W', '!' };
char side_b[] = "Side B";
puts(dont); /* dont is not a string */
return 0;
}
/* 输出:

*/
dont缺少一个表示结束中的内容,所以它不是一个字符串,因此puts()不知道在何处停止。它会一直打印dont后面内存中的内容,直到发现一个空字符为止。为了让puts()尽快找到空字符,我们把dont放在side_a和side_b之间。下面是该程序的一个运行示例:
WOW!Side A
你所使用的编译器输出的内容可能不同,这取决于编译器如何在内存中存储数据。通常内存中有许多空字符,如果幸运的话,puts()很快就会发现一个,但是,这样做很不靠谱。
11.3.2 fputs()函数
fputs()函数是puts()针对文件定制的版本。它们的区别如下:
*fputs()函数的第2个参数指明要写入数据的文件。如果要打印在显示器上,可以用定义在stdio.h中的stdout(标准输出)作为该参数。
*与puts()不同,fputs()不会再输出的末尾添加换行符。
假设要编写一个循环,读取一行输入,另起一行打印出该输入。可以这样写:
char line[81];
while( gets( line ) ) //与while( gets(line) != NULL )相同
puts();
如果gets()读到文件结尾会返回空指针。对空指针求值为0(即为假),这样便可结束循环。或者,可以这样写:
char line[81];
while( fgets( line, 81, stdin ) )
fputs( line, stdout );
注意,如果混合使用fgets()输入和puts()输出,每个待显示的字符串末尾就会有两个换行符。这里关键要注意:puts()应与gets()配对使用,fgets()和fputs()配对使用。
这里提到废弃的gets(),并不是鼓励使用它,而是为了让用户了解它的用法。如果今后遇到包含该函数的代码,不至于看不懂。
11.3.3 printf()函数
printf()函数可以格式化不同的数据类型。
printf()不会自动在每个字符串末尾加上一个换行符。因此,必须在参数中指明应该在哪里使用换行符。例如:
printf( "%s\n", string );
和下面的语句效果相同:
puts( string );
计算机执行printf()函数的时间比puts()更长,然而,使用printf()打印多个字符串更加简单。例如:
printf( "Well, %s, %s\n", name, MSG );