C 编程/简单输入和输出
机器处理事物。我们把东西放进机器,然后得到不同的东西。锯子把树木变成木板。内燃机把汽油变成旋转能量。计算机也不例外。但是,计算机处理的信息不是物理材料,而是信息。
我们把信息输入计算机,告诉计算机用它做什么,然后得到一个结果。我们输入计算机的信息叫做输入,我们从计算机接收的信息叫做输出。输入可以来自几乎任何地方。键盘上的按键、来自互联网连接的数据或被转换为电信号的声波都是输入的例子。输出也可以采取多种形式,例如显示器上播放的视频、终端上显示的一串文本或我们保存到硬盘上的数据。输入和输出的集合被称为输入/输出,简称I/O,是计算机的核心功能。
有趣的是,C 编程语言本身没有 I/O 功能。但是,它为我们提供了一个包含 I/O 函数的外部库,我们可以将其编译并链接到我们的程序中。我们已经在本文开头处的Hello, World!示例中使用了一个输出库函数:printf()
。你可能还记得这个函数位于stdio.h
库文件中。正如该文件名称所暗示的那样,stdio.h
包含标准化的 I/O 函数,用于为我们的程序添加输入和输出功能。本文的这一部分将探讨其中的一些函数。
回想本文开头处的演示程序,如下所示
#include <stdio.h>
int main(void)
{
printf("Hello, World!");
return 0;
}
如果你编译并运行这个程序,你会看到下面的句子出现在你的屏幕上
Hello, World! |
这个惊人的成就是通过使用函数 printf()
实现的。函数就像一个“黑盒子”,它为你做一些事情,而不暴露内部的东西。我们可以在 C 中自己编写函数,但我们将在后面介绍。
你已经看到,要使用 printf()
,需要在括号之间放入用引号括起来的文本。我们把用引号括起来的文本称为字面字符串(或简称为字符串),我们把这个字符串称为 printf
的参数。
作为解释说明,在函数名称后面有时包含一个开括号和闭括号,以提醒我们它确实是一个函数。但是,通常情况下,当我们讨论的函数名称是已知的时,就不需要这样做。
如你所见,在上面的示例中,使用 printf()
可以像在双引号中输入一些文本一样简单(注意,这些是双引号,而不是两个单引号)。因此,例如,你可以通过将任何字符串作为 printf()
函数的参数来打印它
printf("This sentence will print out exactly as you see it..."); |
一旦它包含在一个适当的 main()
函数中,它就会显示
This sentence will print out exactly as you see it... |
printf()
函数是一个强大的函数,可能是 C 程序中最常用的函数。
例如,让我们看看一个问题。假设我们要计算:19 + 31。让我们用 C 来得到答案。
我们开始写
#include <stdio.h> // this is important, since printf
// can't be used without this header
int main(void)
{
printf("19+31 is");
但在这里我们卡住了!printf()
只能打印字符串!幸运的是,printf
有打印数字的方法。我们要做的是在字符串中放入一个占位符格式代码。我们写
printf("19+31 is '''%d'''", 19+31);
占位符 %d
从字面上“占位”实际的数字,它是 19 加 31 的结果。
这些占位符称为格式说明符。许多其他格式说明符与 printf()
配合使用。如果我们有一个浮点数,我们可以使用 %f
打印一个浮点数,包括小数点。其他格式说明符有
%d
- int(与 %i 相同)%ld
- long int(与 %li 相同)%f
- float%lf , %g
- double[1]%c
- char%s
- string%x
- 十六进制
printf()
的所有格式说明符的完整列表可在维基百科上找到。
如果我们想实现一些看起来像这样的输出
1905 312 + -----
printf()
不会在每个语句的末尾添加换行符:我们必须自己添加。但怎样才能做到呢?
我们可以做的是使用换行符转义字符。转义字符是一个特殊的字符,我们可以写入它,但它会在屏幕上执行一些特殊操作,例如发出蜂鸣声、写入制表符等等。要写入换行符,我们写 \n
。所有转义字符都以反斜杠开头。
因此,要实现上述输出,我们写
printf(" 1905\n312 +\n-----\n");
或者更清楚一点,我们可以将这个很长的 printf
语句拆分成几行。因此,我们的程序将是
#include <stdio.h>
int main(void)
{
printf(" 1905\n");
printf("312 +\n");
printf("-----\n");
printf("%d", 1905+312);
return 0;
}
我们还可以使用其他转义字符。另一个常见的转义字符是使用 \t
写入制表符。你可以使用 \a
使计算机发出蜂鸣声,但你应该尽量不要在程序中使用它,因为过多的声音对用户并不友好。
当没有占位符或变量需要关心时,puts()
函数是将字符串发送到屏幕上的一个非常简单的方法。它与我们在“Hello, World!”示例中看到的 printf()
函数非常相似
puts("Print this string.");
将打印到屏幕
Print this string.
后面跟着换行符(如上所述)。(puts
函数在它的输出中追加一个换行符。)
scanf()
函数是输入方法,与 printf()
输出函数等效——简单而强大。在其最简单的调用中,scanf
的格式字符串包含一个表示用户将输入的类型的值的占位符。这些占位符与 printf()
函数基本相同——%d
表示整数,%f
表示浮点数,%lf
表示双精度浮点数。
然而,与printf()
相比,scanf()
有一个变体。scanf()
函数需要您要保存输入值的变量的内存地址。虽然可以使用*指针*(存储内存地址的变量),但这是文本后面才会涉及的概念。相反,简单的技巧是使用*取地址*运算符&。现在,在讨论指针之前,最好将此视为“魔法”。
一个典型的应用可能是这样的
#include <stdio.h>
int main(void)
{
int a;
printf("Please input an integer value: ");
scanf("%d", &a);
printf("You entered: %d\n", a);
return 0;
}
如果您要描述上面scanf()
函数调用的效果,它可能读作:“从用户那里读取一个整数并将其存储在变量a的地址处”。
如果您尝试使用scanf输入一个字符串,则不要包含&运算符。下面的代码将产生运行时错误,程序很可能崩溃
scanf("%s", &a);
正确的用法应该是
scanf("%s", a);
这是因为,当您使用字符串的格式说明符(%s
)时,您用来存储值的变量将是一个数组,而数组名(在本例中为a)本身指向其基本地址,因此,取地址运算符是不需要的。
请注意,使用scanf()
收集用户的键盘输入可能会使您的代码容易受到缓冲区溢出问题的影响,并导致其他不良行为,如果您不十分小心。考虑使用fgets()
而不是scanf()
。
关于输入的说明:当数据在键盘上输入时,信息不会直接进入正在运行的程序。它首先存储在一个称为缓冲区的地方 - 为输入源保留的一小块内存。有时,当程序要从输入源读取时,缓冲区中会留下数据,scanf()
函数将读取这些数据,而不是等待用户输入。有些人可能会建议您使用函数fflush(stdin)
,它在某些计算机上可能按预期工作,但并不被认为是好的做法,正如您将在后面看到的那样。这样做有一个缺点,如果您将代码移植到具有不同编译器的另一台计算机上,您的代码可能无法正常工作。
- ↑ 实际上
%f
也打印double
,但%f
用于输入是不同的。有关更多详细信息,请参阅关于C数据类型的维基百科文章。