c/test/string_api.c · 3628 字节 · 下载原文
/* string_api.c —— `Lib/c/string.h` 里那 9 个**从前只有声明、没有实现**的标准 C 函数的判据。
* string_api.c — criterion for the nine standard C functions that used to be declared with no body.
*
* ## 为什么单独立一个
* ## Why a dedicated probe
*
* 它们从前是「**照着头写能编过、链接时才报 `未解析标签`**」(本仓点名过这是最难查的一类错)。
* 2026-10-08 补了实现 —— 而"补上了"这件事**必须有一条会响的判据**:这 9 个函数各自有
* 明确的边界(`strncat` 的截断、`strrchr` 找结尾 0、`strtok` 的跨调用游标…),
* 写错一半照样能编过。
*
* They compile fine either way; only their edge behaviour tells whether the bodies are right.
*
* 跑法(桌面,秒级):
* dotnet scripts/vmlcli/bin/Release/net10.0/vmlcli.dll third_party/vml/Examples/c/test/string_api.c
*/
#include <string.h>
int fails = 0;
/* 比字符串:`got` 与 `want` 相等记 OK —— ⚠ 一律 `strcmp` 比**内容**,不比指针
* (两个内容相同的字面量地址不同,比指针会全假红)。 */
void ck_s(char* name, char* got, char* want) {
if (strcmp(got, want) == 0) {
printf("OK %s = %s\n", name, got);
} else {
printf("FAIL %s: got %s, want %s\n", name, got, want);
fails = fails + 1;
}
}
void ck_i(char* name, int got, int want) {
if (got == want) {
printf("OK %s = %d\n", name, got);
} else {
printf("FAIL %s: got %d, want %d\n", name, got, want);
fails = fails + 1;
}
}
int main(void) {
char b[64];
char t[64];
char* p;
int n;
/* ① strncat:只接 n 个字符 */
strcpy(b, "abc");
strncat(b, "defgh", 2);
ck_s("strncat(n=2)", b, "abcde");
/* ② strrchr:找**最后**一个(不是第一个) */
strcpy(b, "a/b/c");
p = strrchr(b, '/');
ck_s("strrchr", p, "/c");
/* ③ strrchr 找 0 ⇒ 指向结尾(标准语义) */
strcpy(b, "abc");
n = (int)strrchr(b, 0) - (int)b;
ck_i("strrchr(0) 指向结尾", n, 3);
/* ④ strpbrk:第一处出现在 accept 里的字符 */
strcpy(b, "hello world");
p = strpbrk(b, "ow");
ck_s("strpbrk", p, "o world");
/* ⑤ strspn:开头连续属于 accept 的长度 */
ck_i("strspn", strspn("aabbcc", "ab"), 4);
/* ⑥ strcspn:开头连续**不**属于 reject 的长度 */
ck_i("strcspn", strcspn("aabbcc", "bc"), 2);
/* ⑦ memchr:在给定的 n 字节内找 */
strcpy(b, "abcdef");
p = memchr(b, 'd', 6);
ck_s("memchr", p, "def");
p = memchr(b, 'd', 3);
ck_i("memchr 越界内找不到", p == 0, 1);
/* ⑧ strcoll:本平台就是 strcmp */
ck_i("strcoll 相等", strcoll("abc", "abc"), 0);
ck_i("strcoll 小于", strcoll("abc", "abd") < 0, 1);
/* ⑨ strxfrm:拷贝 + 返回需要的长度 */
strcpy(b, "-------");
n = strxfrm(b, "hello", 64);
ck_s("strxfrm 拷贝", b, "hello");
ck_i("strxfrm 返回长度", n, 5);
/* ⑩ strtok:连续切分(游标要跨调用保住)*/
strcpy(t, "a,bb,ccc");
p = strtok(t, ",");
ck_s("strtok 第 1 段", p, "a");
p = strtok(0, ",");
ck_s("strtok 第 2 段", p, "bb");
p = strtok(0, ",");
ck_s("strtok 第 3 段", p, "ccc");
p = strtok(0, ",");
ck_i("strtok 到头返回 0", p == 0, 1);
printf("STRING_API %s (fails=%d)\n", fails == 0 ? "PASS" : "FAIL", fails);
return fails;
}