10903:英语全字母句
题目
判断空终止字节字符串是否至少包含英语字母 a 到 z 各一次。忽略大小写和非字母字符;空指针返回 false。
解析
直接使用 tolower(c) - 'a' 作为下标,隐含了英文字母连续编码的假设。更稳妥的做法是:
- 将每个字节先转换为
unsigned char,再传给tolower; - 在字面量
"abcdefghijklmnopqrstuvwxyz"中查找转换后的字符; - 用查找结果的位置标记该字母是否出现。
这样既满足 <ctype.h> 的实参要求,也不依赖字母编码连续。
解析
c
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include <ctype.h>
bool is_english_pangram(const char *text) {
if (text == NULL) {
return false;
}
static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz";
bool seen[sizeof alphabet - 1] = {false};
size_t remaining = sizeof alphabet - 1;
const unsigned char *cursor =
(const unsigned char *)text;
while (*cursor != '\0') {
int lower = tolower(*cursor);
const char *match = strchr(alphabet, lower);
if (match != NULL) {
size_t index = (size_t)(match - alphabet);
if (!seen[index]) {
seen[index] = true;
--remaining;
if (remaining == 0) {
return true;
}
}
}
++cursor;
}
return false;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
复杂度
字母表长度固定为 26,因此每个输入字节只进行常数次工作。长度为
来源与改编
题型改编自 Exercism C Track 的 Pangram,采用 MIT 许可。本题增加了空指针语义和执行字符集可移植性要求,完整说明见习题来源与许可。