如何在C语言中实现忽略单双引号内内容的字符串分割函数?
实现忽略引号内分隔符的split函数
我自己重写了一个按指定分隔符分割字符串的split函数,想要修改它,让它忽略单引号或双引号内的分隔符,但始终没能实现预期效果。尝试用标志位处理引号状态,但逻辑过于复杂,导致部分测试用例通过,其他用例失败。
原调试代码
void quote_state(char c , int *inquotes) // 检查引号状态 { if (c == '\'' || c == '\"') { if(!(*inquotes)) *inquotes = 1; else if (*inquotes == 1) *inquotes = 0; } } char **ft_split2(char *s, char c) { char **str; int i; int j; int start; int inquotes; // 分配所需内存 //... while (s[j]) { while (s[j] == c && !inquotes) j++; start = j; quote_state(s[j], &inquotes); while (s[j] != c && s[j]) { quote_state(s[j], &inquotes); j++; if (inquotes) break; } if ((s[j] == "\"" || s[j] == "\'") && inquotes) j++; if (j > start) str[i++] = wordp(s, start, j); // 分配内存并存储元素.. } str[i] = NULL return(str); }
测试用例
- 输入字符串:
" kaka koko " waah waah " lla " - 当前输出:
kaka\0koko\0"\0waah waah "\0lla\0 - 期望输出:
kaka\0koko\0" waah waah "\0lla\0NULL
问题分析与修正方案
原代码存在几个关键问题:
- 引号转义错误:C语言中双引号直接用
'"'表示,无需转义成'\"';字符串比较== "\""是错误的,应该用字符比较== '"'。 - 变量未初始化:
inquotes、i、j等变量没有初始值,会导致未定义行为。 - 引号状态逻辑错误:内层循环遇到引号就break,无法完整遍历引号内的内容;且未区分当前处于单引号还是双引号,无法正确处理引号闭合。
- 单词截取逻辑混乱:没有正确处理引号的开始和结束位置,导致截取内容不符合预期。
修正后的代码
#include <stdlib.h> #include <string.h> // 辅助函数:计算分割后的单词数量 static int count_words(char *s, char c) { int count = 0; int in_quotes = 0; char quote_type = 0; int i = 0; while (s[i]) { // 跳过不在引号内的分隔符 while (s[i] == c && !in_quotes) i++; if (s[i] == '\0') break; count++; // 遍历到单词结束(遇到分隔符且不在引号内,或字符串结束) while (s[i]) { if ((s[i] == '\'' || s[i] == '"') && !in_quotes) { in_quotes = 1; quote_type = s[i]; } else if (s[i] == quote_type && in_quotes) { in_quotes = 0; quote_type = 0; } if (s[i] == c && !in_quotes) break; i++; } } return count; } // 辅助函数:截取子字符串 static char *wordp(char *s, int start, int end) { char *word = malloc(end - start + 1); if (!word) return NULL; strncpy(word, s + start, end - start); word[end - start] = '\0'; return word; } char **ft_split2(char *s, char c) { if (!s) return NULL; int word_count = count_words(s, c); char **str = malloc((word_count + 1) * sizeof(char *)); if (!str) return NULL; int i = 0; // 结果数组索引 int j = 0; // 原字符串索引 int start; int in_quotes = 0; char quote_type = 0; while (s[j]) { // 跳过不在引号内的分隔符 while (s[j] == c && !in_quotes) j++; if (s[j] == '\0') break; start = j; // 遍历到当前单词结束 while (s[j]) { // 更新引号状态 if ((s[j] == '\'' || s[j] == '"') && !in_quotes) { in_quotes = 1; quote_type = s[j]; } else if (s[j] == quote_type && in_quotes) { in_quotes = 0; quote_type = 0; } // 遇到分隔符且不在引号内,结束当前单词 if (s[j] == c && !in_quotes) break; j++; } // 截取并存储单词 str[i++] = wordp(s, start, j); } str[i] = NULL; return str; }
关键修正点说明
- 精准处理引号状态:用
quote_type记录当前处于单引号还是双引号,确保只有遇到相同类型的引号时才退出引号状态,避免误判。 - 变量明确初始化:所有变量都赋予初始值,杜绝未定义行为。
- 完善单词计数逻辑:先遍历字符串统计单词数量,确保内存分配准确。
- 清晰的遍历逻辑:先跳过分隔符,再完整遍历引号内的内容,直到遇到闭合引号或字符串结束,最后截取正确的子字符串。
内容的提问来源于stack exchange,提问作者Omar Jebbari
相关产品推荐
相关产品推荐

