第十四章:处理与 I/O
级别 2 — 认知
文本处理、格式化 I/O、字符编码——C 如何处理数据的流入和流出,以及 Auto 如何简化它。
输入和输出是程序与外界交互的地方。C 的 I/O 库以 stdio.h 为核心,提供了一组灵活但容易出错的工具。本章涵盖文本处理、格式化输入、字符编码和二进制流——以及 Auto 如何提供更安全的替代方案。
14.1 文本处理
C 在 <ctype.h> 中提供字符分类函数:
c
// C 深入:字符分类
#include <ctype.h>
int ch = 'A';
isalpha(ch); // 真:字母
isdigit(ch); // 假:不是数字
isupper(ch); // 真:大写
islower(ch); // 假:不是小写
isspace(ch); // 假:不是空白
toupper(ch); // 'A' -> 'A'
tolower(ch); // 'A' -> 'a'这些函数有一个关键警告:传递不能表示为 unsigned char 或 EOF 的值是未定义行为。实际上,这意味着在 char 为有符号的平台上传递值超过 127 的 char 可能导致 UB。
<string.h> 中的字符串操作:
c
// C 深入:字符串操作
strlen("hello"); // 5
strcpy(dst, src); // 复制——dst 必须足够大!
strcat(dst, src); // 连接——dst 必须足够大!
strcmp("abc", "def"); // 负数:abc < def
strncmp("abc", "abd", 2); // 0:前 2 个字符相等
strchr("hello", 'l'); // 指向第一个 'l' 的指针
strstr("hello", "ell"); // 指向 "ell" 的指针strcpy 和 strcat 函数是许多缓冲区溢出漏洞的根源。C11 添加了 strncpy_s 和 strcat_s 作为更安全的替代方案,但它们仍然使用不足。
Auto 的方法:安全的字符串操作。 Auto 字符串具有长度跟踪且不可变。可能溢出的操作根本不会出现:
auto
// Auto:安全的文本处理
fn count_words(text str) int {
var count int = 0
var in_word bool = false
for i in 0..len(text) {
let ch str = str(text[i])
if ch == " " {
in_word = false
} else {
if !in_word {
count = count + 1
}
in_word = true
}
}
count
}