Logo
Section 1 / 6

输入/输出流

深入探讨C标准库提供的输入输出方法,并学习如何与命令行终端进行交互。

导入

输入/输出流

深入探讨C标准库提供的输入输出方法,并学习如何与命令行终端进行交互。

C 中的流

标准 C 库(通过 #include <stdio.h> 引入)包含若干用于执行输入和输出操作的函数。

C 和 UNIX 使用一种称为 流 的概念,允许程序、设备与操作系统之间传输数据。我们可以区分两种类型的流:文本流和二进制流。

  • 文本流由行组成,每行包含零个或多个字符,并以换行符 \n 结尾。
  • 二进制流更为“原始”,由任意数量的字节组成。

所有 C 程序都内置了三个流:标准输入、标准输出 和 标准错误。以下是标准输入和标准输出流的一些使用示例:

  • 当我们在终端中与 C 程序交互并输入值传递给程序时,就是在使用标准输入。

  • UNIX 提供了 管道 的概念,可以将任意流(如某个程序或设备的输出)重定向为另一个进程(如你的程序)的输入。当我们把流重定向到程序并作为输入接收时,就是使用了标准输入流。

  • 当我们的程序使用 printf(见下文)向屏幕打印内容时,就是在使用标准输出。

  • 文件(如数据文件)也与流相关联,我们将在下面学习如何从文件读取数据和向文件写入数据。

我们不会在此讨论标准错误。有关标准错误的详细信息,请参考 UNIX 参考手册或 C 语言书籍。

字符 I/O:getchar 和 putchar

当我们需要逐个字符地读取数据时,可以使用 getchar 函数。putchar 函数则用于将单个字符逐个写入标准输出。在终端运行 ./main 可以看到效果:

No configuration found for ID: 7931d13f7d9e40e0c3ae334d3c0d5b0dac2a742fca363f8294bb4bb3ebc3430f

格式化 I/O:printf 和 scanf

我们可以读取符合特定格式的输入数据,也可以按需格式化输出内容。

printf 函数

在许多示例代码中,我们都使用了 printf 函数来向屏幕输出格式化内容。通常情况下,printf 函数接受两个参数:第一个是字符串参数,用于指定要输出的内容,包括格式说明符;第二个是变量列表,提供格式字符串中各部分所需的数据。

以下是一个示例,展示如何输出一个包含格式化整数、浮点数和字符串的句子:

1#include <stdio.h> 2 3int main(void) { 4 int i = 42; 5 char str[] = "the meaning of life"; 6 double p = 3.14159265; 7 printf("pi is about %10.8f and %s is %d\n", p, str, i); 8 return 0; 9}

让我们分析第 7 行的 printf 语句。格式字符串中包含三个数值格式说明符。第一个 %10.8f 表示我们要输出一个浮点数(f),保留 8 位小数(.8),并为其分配 10 列宽度(10)。第二个格式说明符 %s 对应字符串类型。第三个 %d 对应整数类型。

如需其他格式化需求,建议查阅参考手册。

scanf 函数

要从标准输入读取格式化的数据,可以使用 scanf 函数。与 printf 类似,它第一个参数是格式字符串,后续参数指定每个输入项的目标位置。但与 printf 不同的是,scanf 要求这些目标参数必须是内存中对应位置的地址(例如传入指针)。

以下是一个简单示例,用于从标准输入读取一个日期,预期输入格式如下:

输入的期望格式

121 May 2024

No configuration found for ID: 20cff75dd8b6e9c38cff56f829352f1f490ec611d80725d5e8939a7d51398bdb

注意第 7 行中,我们使用取地址符(&)传递了 day 和 year 的地址,但没有对 monthname 做同样处理。这是因为 monthname 本身就是一个指向字符数组的指针,已包含数组首地址。

scanf 函数会忽略格式字符串中的空格和制表符,并在查找输入值时跳过空白字符(空格、制表符、换行符等)。

程序输入后的预期输出

1$ ./main 2Enter day, month (name), and year: 321 May 2024 4The date is May 21, 2024

除了与终端进行数据交换外,我们还可以从文本文件读取数据并写入文件。下一课我们将继续学习相关内容!

C 字符串

文件的输入与输出