【问题标题】:Removing an element in an array and shifting the elements left to close the gap删除数组中的元素并将元素向左移动以缩小间隙
【发布时间】:2013-10-18 17:16:16
【问题描述】:

这是我的代码。该函数应该删除字符串数组中的一个字符串,然后将所有元素向左移动以缩小差距。

void removeWord(char ***array, int *count){

    char word[41];

    printf("Enter a word: ");
    fscanf(stdin, " ");
    fscanf(stdin, "%s", word);
    bool wordFound = false;
    int indexOfWord = 0;
    for(int i = 0; i < *count; i++){
            if(strcasecmp(word, (*array)[i]) == 0){
                    wordFound = true;
                    indexOfWord = i;
                    break;
            }
    }
    if(wordFound == false){
            fprintf(stderr, "Word not found in dictionary.\n");
    }
    else{
            free((*array)[indexOfWord]);
            // Decrement count
            (*count)--;
            for(int i = indexOfWord; i < *count; i ++){
                    // Shift elements over to the left by 1 to close the gap
                    (*array)[i] = (*array)[i+1];
            }
            // If the word to remove isn't the last element, remove the last element to prevent duplicate words
            if(indexOfWord != *count) free((*array)[*count]);

    }
}

当我删除数组中的最后一个单词时,该函数可以正常工作......但是当我删除倒数第二个单词时,它会删除它,但也会将最后一个元素设置为某个奇数值/null。我一直在努力解决这个问题,如果有人能指出我正确的方向,我将不胜感激......谢谢,如果需要更多信息,请随时询问。

-----------更新

答案是删除最后的if语句,没必要:

void removeWord(char ***array, int *count){

    char word[41];

    printf("Enter a word: ");
    fscanf(stdin, " ");
    fscanf(stdin, "%s", word);
    bool wordFound = false;
    int indexOfWord = 0;
    for(int i = 0; i < *count; i++){
            if(strcasecmp(word, (*array)[i]) == 0){
                    wordFound = true;
                    indexOfWord = i;
                    break;
            }
    }
    if(wordFound == false){
            fprintf(stderr, "Word not found in dictionary.\n");
    }
    else{
            free((*array)[indexOfWord]);
            // Decrement count
            (*count)--;
            for(int i = indexOfWord; i < *count; i ++){
                    // Shift elements over to the left by 1 to close the gap
                    (*array)[i] = (*array)[i+1];
            }
    }
}

【问题讨论】:

    标签: c arrays string memory-management


    【解决方案1】:

    在您的else 开头您的free() 您要删除的单词。然后,您将所有剩余的单词移过来。最终结果是您的array[count-1](最后一个有效元素)和array[count] 都包含相同的指针。然后释放array[count],使array[count-1] 包含指向已释放内存的指针。

    为什么是第二个free()?你想删除 1 个词,你 free() 那个词就完成了。

    另外,为什么是char *** array?无论你在哪里使用它,你都在做(*array) 取消引用一次。为什么不将char ** 指针数组传递给函数?

    【讨论】:

    • 和我写代码的方式是一样的。这个练习的目的是更加熟悉指针和数组,所以我想为什么不呢?第二个免费是删除任何重复项。如果我删除了 7 个元素数组中的第 5 个元素,然后用我的代码向左移动。第 7 个和第 6 个元素是相同的值,不是吗?
    • 我删除了那行,现在它可以工作了,当我写的时候一定是疯了......谢谢,现在工作正常。
    • @Riptyde4 啊,你需要了解指针和实际数据之间的区别。指针将是重复的,也就是说,您将有两个指针指向堆上的相同数据,但只有实际数据的 1 个副本。当您执行free() 时,它会删除数据,因此任何有指向它的指针的地方都有一个指向空的指针。您正在使用分配复制指针,但不是数据。您可能也应该设置为NULLarray[count] = NULLelse 的末尾。
    【解决方案2】:

    问题在于这段代码:

    if(indexOfWord != *count) free((*array)[*count]);
    

    问题是由于,您已经减少了*count,所以现在如果您使用修改后的*count 值引用,它将引用当前实际的最后一个值。 也不需要释放最后一个元素,因为当前最后一个元素和前一个最后一个元素指向同一个内存,所以只需将指针设置为NULL

    改成:

    if(indexOfWord != *count) (*array)[((*count) + 1)] = NULL;
    

    【讨论】:

    • 我之前进行了此更改,我在 valgrind 中收到了一堆大小为 1 的无效读取错误,以及一个错误说明条件跳转或移动取决于未初始化的值。我还得到了一个 ==3862== Invalid free() / delete / delete[] 单独执行
    • @Riptyde4:应该可以,我稍微编辑了代码。也检查一下。如果您收到任何错误,请将错误添加为注释。我会尽力帮助你的。
    猜你喜欢
    • 1970-01-01
    • 2021-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多