c - 如何有效地解决 C 中的差一错误?

标签 c off-by-one

我编写了一个程序来反转字符数组以及反转该数组中的单词。该程序几乎按预期工作,但我相信这是一个相差一错误。我尝试过搞乱涉及循环计数器的数学,但无法弄清楚这一点。我可以使用什么工具或技术来解决此类问题?我尝试过 printf 语句,还使用 ​​gdb 并在计数器变量上放置了一个监视。

#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;
}

此代码返回熟能生巧。显然,这是一个相差一的错误,但我已经花了一些时间在这上面,并且在其他程序中的 C 语言中也遇到了类似的错误。

最佳答案

该错误位于 reverse_words 。有时tail在单词的最后一个字符之后对字符进行索引,有时是 tail索引单词本身的最后一个字符。

调用reverse_array来自reverse_words是:

reverse_arr(&arr[start], tail - start);

如果 start 则此方法有效索引单词的第一个字符,如果有 tail - start单词中的字符。所以tail必须对单词最后一个字符之后的字符进行索引。

条件arr[tail] == ' '与此一致,但结束条件不是:(1) 循环退出太快,以及 (2) 测试 tail == len-1也减少了一位。

可以通过再迭代一次并在尝试访问 arr[tail] 之前检查结束条件来解决此问题。 (以避免索引超过末尾):

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;
        }
    }
}

请注意,循环退出条件现在为 <=而不是< ,循环内结束测试移了一位,并且循环内的检查顺序颠倒了。

关于c - 如何有效地解决 C 中的差一错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56404682/

相关文章:

java - 循环的行为不符合我的预期

c++ - 循环不处理字符串的最后一个字符

c++ - 如何解决 for 循环中的差一问题

python - 使用 ctypes 模块将 blake 哈希函数 C 实现包装到 Python 中,还包括简单的 python ctypes testvector 脚本

父进程退出后,子进程无法从终端读取

C指针取消引用

javascript - 为什么我的 DP 解码数字和字母解决方案不能适用于所有测试用例?

java - 隐写术后第一个字节的位相差一位

python - HDF5 : storing NumPy data

c - 在函数中传递结构