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()
函数需要你想要将输入值保存到的变量的内存地址。虽然指针(存储内存地址的变量)可以在这里使用,但这将在文本的后面部分讨论。相反,简单的方法是使用地址-of操作符&。现在最好将它视为"魔法",在我们讨论指针之前。
一个典型的应用可能像这样
#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
用于输入的方式不同。有关更多详细信息,请参阅Wikipedia 上有关 C 数据类型的文章。