如何有效地排除C中的一个bug?
我已经编写了一个程序来反转一个字符数组,也反转该数组中的字。程序几乎按预期运行,但我相信这是一个一个错误。我尝试过搞乱涉及循环计数器的数学运算,但没能弄明白这一点。我可以使用什么工具或技术来解决此类问题?我尝试了printf语句,还使用了gdb,并在计数器变量上放置了一个手表如何有效地排除C中的一个bug?,c,off-by-one,C,Off By One,我已经编写了一个程序来反转一个字符数组,也反转该数组中的字。程序几乎按预期运行,但我相信这是一个一个错误。我尝试过搞乱涉及循环计数器的数学运算,但没能弄明白这一点。我可以使用什么工具或技术来解决此类问题?我尝试了printf语句,还使用了gdb,并在计数器变量上放置了一个手表 #include <stdio.h> #include <stdlib.h> #include <string.h> void reverse_arr(char *arr, size_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void reverse_arr(char *arr, size_t len);
void print_chars(char *arr, size_t len);
void reverse_words(char *arr, size_t len);
int main(int argc, char **argv)
{
char phrase[] = {'p','e','r','f','e','c','t',' ',
'm','a','k','e','s',' ','p','r',
'a','c','t','i','c','e'};
size_t i;
reverse_arr(phrase, sizeof(phrase));
reverse_words(phrase,sizeof(phrase));
print_chars(phrase, sizeof(phrase));
return EXIT_SUCCESS;
}
void reverse_arr(char *arr, size_t len)
{
size_t front, tail;
tail = len-1;
char tmp;
for(front = 0; front < len/2; front++, tail--)
{
tmp = arr[front];
arr[front] = arr[tail];
arr[tail] = tmp;
}
return;
}
// 1. Search for a space
// 2. When space is found, that space is the place to stop and indicates all between the start and it are a word
// 3. Now call reverse_arr on the word and calculate the length of the word by subtracting tail - start
//
void reverse_words(char *arr, size_t len)
{
size_t tail, start;
for(tail = start = 0; tail < len; tail++)
{
if(arr[tail] == ' ' || tail == len-1)
{
reverse_arr(&arr[start], tail - start);
start = tail+1;
}
}
}
void print_chars(char *arr, size_t len)
{
size_t i;
for(i = 0; i < len; i++)
{
putchar(arr[i]);
}
putchar('\n');
return;
}
#包括
#包括
#包括
无效反向排列(字符*排列,大小排列);
无效打印字符(字符*arr,大小长度);
无效反向字(字符*arr,大小\u t len);
int main(int argc,字符**argv)
{
字符短语[]={p','e','r','f','e','c','t','',
‘m’、‘a’、‘k’、‘e’、‘s’、‘p’、‘r’,
‘a’、‘c’、‘t’、‘i’、‘c’、‘e’};
尺寸i;
倒装(短语,sizeof(短语));
倒装词(短语,sizeof(短语));
打印字符(短语、大小(短语));
返回退出成功;
}
无效反向排列(字符*排列,大小排列)
{
前、后尺寸;
tail=len-1;
char-tmp;
用于(前部=0;前部<长度/2;前部++,尾部--)
{
tmp=arr[前];
arr[前]=arr[尾];
arr[tail]=tmp;
}
回来
}
// 1. 搜索空间
// 2. 当找到空格时,该空格是停止的位置,表示开始和结束之间的所有空格都是一个单词
// 3. 现在调用单词的reverse_arr并通过减去tail-start来计算单词的长度
//
无效反向字(字符*arr,大小\u t len)
{
尾的大小,开始;
对于(tail=start=0;tail
此代码返回
practice make-erfectp
。很明显,这是一个一个接一个的错误,但我在这方面花了一些时间,并且在其他程序的C中遇到了类似的错误。错误在反向词中。有时tail
索引单词最后一个字符之后的字符,有时tail
索引单词本身的最后一个字符
从reverse\u words
调用reverse\u array
是:
reverse_arr(&arr[start], tail - start);
如果start
索引单词的第一个字符,并且单词中存在tail-start
字符,则此操作有效。因此tail
必须在单词的最后一个字符之后索引该字符
条件arr[tail]=''
与此一致,但结束条件不一致:(1)循环过早退出,(2)测试tail==len-1
也关闭一次
可以通过再次迭代并在尝试访问arr[tail]
之前检查结束条件来修复此问题(以避免索引超过结束):
void reverse\u words(字符*arr,大小\u len)
{
尾的大小,开始;
对于(tail=start=0;tail您是否至少在main
中将其缩小为一个函数调用?(reverse\u arr
或reverse\u words
)这将是第一步,因为它们是完全分开的,您可以打印/使用调试器检查它们之间的短语。函数名称表明您的输出应该是ecitcarp sekam tcefrep
。这确实是您想要得到的吗?@goodstribration:反转单词反转每个单词对于“熟能生巧”的预期输出“代码”> ReaveSARR < /代码>?通过测试小的测试用例来清除它们,这种类型可以很容易地用调试器跟踪程序的执行。您不需要大于4个字符的任何东西来覆盖所有的条件。首先从一个空数组开始,先修复这个bug,然后考虑字符串可能是更好的选择。o我有一个问题。在语句if(tail==len | | arr[tail]=='')中,C是否保证在arr[tail]之前计算tail==len
?我试图在C标准中找到这一点,因为我想知道这一点已经有一段时间了。另外,您使用了什么调试方法来解决这个问题?@endian是的,它被称为短路。对于|
,只有当第一个操作数为false时,才会计算第二个操作数。对于&
,只有当第二个操作数为false时,才会计算第二个操作数第一个是真的。您可以通过将函数调用放入第二个操作数,并让该函数在调用时打印一些内容来测试它。关于调试,我只是查看了循环,并通过检查发现了问题。
void reverse_words(char *arr, size_t len)
{
size_t tail, start;
for (tail = start = 0; tail <= len; tail++)
{
if (tail == len || arr[tail] == ' ')
{
reverse_arr(&arr[start], tail - start);
start = tail+1;
}
}
}