C语言检查字符是否存在于字符串中的最优方法是什么?
原代码问题定位
- 多余的错误转换逻辑:
char charC = c + '0';这行完全没有存在必要,将读取到的字符ASCII码加上'0'的ASCII值(通常为48)会直接改变原字符数值,导致后续换行判断完全失效。 - 换行判断逻辑错误:使用
strncmp(&charC, "\n", 1)判断换行属于冗余且错误的写法,charC已经被加了'0',不可能等于'\n'的ASCII值,所有换行都会被识别为非法字符,直接判断原读取到的c == '\n'即可实现换行合法校验。 - 可移植性隐患:
strchr要求传入的字符参数需要是unsigned char类型提升的int值,如果读取到的字符是负数(比如char为有符号类型的场景下读入了扩展ASCII字符),会导致未定义行为。
修复后的基础实现
#include <stdio.h> #include <string.h> #include <stdbool.h> bool check_bad_characters(FILE *inputFile) { int c; // 合法字符直接包含换行符,减少后续判断分支 const char valid_characters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ \n"; while ((c = fgetc(inputFile)) != EOF) { if (strchr(valid_characters, (unsigned char)c) == NULL) { // 存在非法字符 return false; } } return true; }
更高效的优化实现
如果文件体积较大,频繁调用strchr遍历合法字符数组会产生额外开销,可以用静态查找表实现O(1)复杂度的字符校验:
#include <stdio.h> #include <stdbool.h> #include <limits.h> bool check_bad_characters(FILE *inputFile) { int c; // 初始化查找表,所有字符默认标记为非法 static bool valid_table[UCHAR_MAX + 1] = {false}; // 仅第一次调用时初始化查找表 if (!valid_table['A']) { for (char ch = 'A'; ch <= 'Z'; ch++) { valid_table[(unsigned char)ch] = true; } valid_table[(unsigned char)' '] = true; valid_table[(unsigned char)'\n'] = true; } while ((c = fgetc(inputFile)) != EOF) { if (!valid_table[(unsigned char)c]) { return false; } } return true; }
内容的提问来源于stack exchange,提问作者Jorge Jones
相关产品推荐
相关产品推荐

