裘宗燕 从问题到程序(2003 年修订),第十一章 标准库
strerror 的情况比较简单。本章开始时讲过,在程序里可以检查 C 标准库中表达式
errno 的值,当这个表达式非 0 时,可以通过 strerrno(errno)得到一个字符指针,它
指向系统提供的一个有关当时错误的信息串。
字符串长度
函数 strlen 返回字符串中的实际字符个数,这一长度不包括表示结束的空字符。
char ss[] = "there is an island in the sea.";
int n;
n = strlen(ss);
执行这个语句后 n 的值将是 30。
有时我们会需要为保存得到的字符串而动态分配一块存储区。在需要这样做时,就可以
用函数 strlen 求出字符串长度,但分配时一定要注意加上空字符的位置。下面函数建立
参数字符串的一个副本,返回指向这个副本字符串的指针:
char *makecopy(char *s) {
char *p = (char*)malloc((strlen(s)+1));
strcpy(p, s);
return p;
}
如果没有+1,调用 strcpy 复制字符串时就会越界,可能造成严重问题。在上面分配中计
算大小时不必去乘 sizeof(char),因为 C 语言规定 char 类型的大小为 1。
字符和子串查找
函数 strchr 和 strrchr 查找一个字符在一个字符串里出现的位置,它们分别从字符
串得左边和右边开始查寻。函数 strpbrk 将一个串看作字符的集合,查找其中任何一个字
符在另一个字符串里出现的位置,函数 strstr 查找一个串(这时称为子串)在另一个字
符串里出现的位置。如果查找成功,这些函数就返回指向所确定位置的指针,失败(没有找
到)时返回空指针值。例如:
char ss[] = "there is an island in the sea.";
char *p1, *p2, *p3;
p1 = strchr(ss, 'n');
p2 = strrchr(ss, 'n');
p3 = strstr(ss, "is");
执行这几个语句后,p1 将指向 ss 里单词 an 中的 n(这是 ss 里从左边起的第一个 n);p2
将指向单词 in 中的字符 n(ss 里从右边起的第一个 n);p3 将指向 ss 里的单词 is 的第
一个字符(虽然后面还有另一个 is 出现,作为单词 island 的一部分)。
如果要确定在某个字符在一个字符串里的所有出现位置,我们可以写一个循环。例如,
下面循环将输出字符串 ss 里所有 i 的位置:
p = ss;
while (1) {
if ((p1 = strchr(p1, 'i')) == NULL) break;
printf("%d ", p1 - ss);
}
在找到需要的字符位置后,我们当然可以做任何需要做的事情。这里将找到得位置输出只是
作为一个例子。对于子串查找也可以写出类似的循环。
特定的最长前缀
字符串的一个前缀是指该串前面的一段。函数 strspn 和 strcspn 都可用于确定一个
字符串中满足某种要求的最长前缀的长度。strspn 查找的是所有字符都属于某个集合(字
符集合用另一个字符串表示)的最长前缀,而 strcspn 查找的是所有字符都不属于某个集
合的最长前缀。下面程序片断确定输入的一行中从头开始最长数字序列的长度:
char s[256];
fgets(s, 256, stdin);
n = strspn(s, "0123456789");
5