C中的Posix正则表达式匹配。。。完全匹配异常?
所以我目前的作业是用C实现一个类似DBMS的系统,我决定使用linux POSIX正则表达式匹配库。我正在编写玩具代码来学习东西,这是我对DBMS“命令解析”部分的测试。这篇文章有点长,但请容忍我 因此,完整的程序代码基于: 我收到的输出是:C中的Posix正则表达式匹配。。。完全匹配异常?,c,regex,posix-ere,C,Regex,Posix Ere,所以我目前的作业是用C实现一个类似DBMS的系统,我决定使用linux POSIX正则表达式匹配库。我正在编写玩具代码来学习东西,这是我对DBMS“命令解析”部分的测试。这篇文章有点长,但请容忍我 因此,完整的程序代码基于: 我收到的输出是: Sweeping 'insert whatever bananana' for '([[:alpha:]]+)[[:blank:]]*([^\0]*)' Match block 0 @bytes 0:23 Match block 1 @bytes 0:5
Sweeping 'insert whatever bananana' for '([[:alpha:]]+)[[:blank:]]*([^\0]*)'
Match block 0 @bytes 0:23
Match block 1 @bytes 0:5
Match block 2 @bytes 7:23
$& --> insert whatever bananana!
$1 --> insert
$2 --> whatever bananana
根据,正则表达式的模式似乎没有问题,但请注意完整表达式末尾的错误“!”。尽管捕获组被正确解析,但(到目前为止)不寻常的字符发生在完整的表达式范围内,对于目前为止使用的测试用例,仅当其长度正好为24字节时才出现。这可能是一个非常愚蠢的错误,我为此感到抱歉
此外,任何关于如何用C语言更好、也许更优雅地处理正则表达式的建议都是非常受欢迎的事先非常感谢
编辑
因此,根据回答,这是toSubstring
内部的偏移错误。它现在是固定的,输出是平稳的,因为他们应该。正如评论中所建议的,我也对代码进行了一些清理
与之前发生的情况不同,使用valgrind进行的有点侵入性的运行显示没有错误或未定义的行为:
$ valgrind --leak-check=full --track-origins=yes --show-reachable=yes ./regex_drills "insert whatever bananana" "([[:alpha:]]+)[[:blank:]]*([^\0]*)" 3
==7051== Memcheck, a memory error detector
==7051== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7051== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==7051== Command: ./regex_drills insert\ whatever\ bananana ([[:alpha:]]+)[[:blank:]]*([^\\0]*) 3
==7051==
Sweeping 'insert whatever bananana' for '([[:alpha:]]+)[[:blank:]]*([^\0]*)'
Match block 0 @bytes 0:24
Match block 1 @bytes 0:6
Match block 2 @bytes 7:24
$0 --> insert whatever bananana
$1 --> insert
$2 --> whatever bananana
==7051==
==7051== HEAP SUMMARY:
==7051== in use at exit: 0 bytes in 0 blocks
==7051== total heap usage: 167 allocs, 167 frees, 18,458 bytes allocated
==7051==
==7051== All heap blocks were freed -- no leaks are possible
==7051==
==7051== For counts of detected and suppressed errors, rerun with: -v
==7051== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
我要感谢大家的快速响应。我从中学到了很多。您的
to substring
函数有一个off by one错误end
是独占绑定,因此子字符串的长度为len=end-start
。您必须分配一个以上的字符来存储终止空字符,但您应该只复制len
字符,更重要的是,您应该将终止空字符写入buffer[len]
,而不是buffer[len+1]
:
char *toSubstring(const char *str, int start, int end)
{
char *buffer = malloc(end - start + 1);
memcpy(buffer, str + start, end - start);
*(buffer + (end - start)) = '\0';
return buffer;
}
可能您并不打算将end
设置为独占,因为您在调用toSubstring
时对其进行了调整。您可以保留这些语义并分配end-start+2
字符(并保留其余的代码),但在C中,上限通常是独占的,因此我建议使用上述函数并像这样调用它:
*(*(m_array) + i) = toSubstring(r_text, start, stop);
与
(…,stop-1)
不同的是,这只是一个小问题:为什么要对argv
访问使用指针算法?通常使用常规数组索引语法,例如r\u text=argv[1]
。与其他指针相同。请删除C++标签,代码不是C++,C++解决方案看起来很不一样,因为C和C++是非常不同的语言。而sizeof(char)
被C规范定义为总是1
。当您在代码中写入超出分配内存限制的内容时。在toSubstring
函数中,您分配end start+1
字节,这意味着您可以在生成的内存中访问的最高索引是end start
,但您在end start+1
位置写入字符串终止符,该位置超出分配内存的末尾一个字节。至于不强制执行malloc
,请注意:,请按照链接阅读答案。关于指针算法,它不是由预处理器处理的,使用数组索引通常更容易读取(并且写入更少)。
char *toSubstring(const char *str, int start, int end)
{
char *buffer = malloc(end - start + 1);
memcpy(buffer, str + start, end - start);
*(buffer + (end - start)) = '\0';
return buffer;
}
*(*(m_array) + i) = toSubstring(r_text, start, stop);