在重新分配后无法打印字符串数组?

时间:2017-06-19 12:07:28

标签: c arrays pointers split c-strings

下面的代码读取字符并在遇到分隔符时将它们拆分为C风格的字符串,然后它将字符串(以空格分隔的字符序列)存储在字符串数组中,直到遇到哨兵为止;更新字符串数组的大小:

#include <stdio.h>      // printf()
#include <stdlib.h>     // malloc(); realloc()
#include <string.h>     // strcmp()
#include <stddef.h>     // size_t

void print_array(char* arr[ ], size_t size); // forward declaration to use in to_array()

char* get_word(char delimiter)
{
    size_t size = 8;
    size_t index = 0;

    int c = 0;
    char* word = 0;
    char* expand_word = 0;

    word = (char*) malloc(sizeof(char) * size);
    if (word == NULL)
    {
        perror("get_word::bad malloc!\n");
        exit(-1);
    }

    while ((c = getchar()) != EOF && c != delimiter && c != '\n')
    {
        if (index >= size)
        {
            size *= 2;

            expand_word = (char*) realloc(word, sizeof(char) * size);
            if (expand_word == NULL)
            {
                perror("get_word::bad realloc!\n");
                exit(-1);
            }

            word = expand_word;
        } 

        word[index++] = c;
    }

    word[index] = 0;

    return word;
}

//-------------------------------------------------------------------------------------
void to_array(char* arr[ ], size_t* size, char* sentinel)
{
    size_t index = 0;
    char* word = 0;
    char** expand_arr = 0;
    char delimiter = ' ';

    while ((word = get_word(delimiter)) && strcmp(word, sentinel) != 0)
    {
        if (index >= (*size))
        {
            (*size) *= 2;

            expand_arr = (char**) realloc(arr, sizeof(char*) * (*size));
            if (expand_arr == NULL)
            {
                perror("to_array::bad realloc!\n");
                exit(-1);
            }  

            arr = expand_arr;
        }

        arr[index++] = word;
    }

    (*size)  = index;

    // print_array(arr, *size); // <---- here, all words printed OK.
    // getchar();
}

//-------------------------------------------------------------------------------------

void print_array(char* arr[ ], size_t size)
{
    size_t i = 0;

    printf("{ ");
    for (i; i < size; ++i)
    {
        printf("%s", arr[i]);

        if (i < size - 1)
        {
            printf(", ");
        }
    }
    printf(" }\n");
}

//-------------------------------------------------------------------------------------

int main()
{
    size_t size = 4;
    char** arr = 0;
    char* sentinel = "quit";

    arr = (char**) malloc(sizeof(char*) * size);
    if (arr == NULL)
    {
        perror("array of strings::bad malloc!\n");
        exit(-1);
    }

    printf("Type a sentence and get each word as an array element:\n");
    to_array(arr, &size, sentinel);

    printf("Words:\n");
    print_array(arr, size);   // <--------- here, error!

    getchar();
}

尝试打印字符串数组时,我得到:

  

Access violation reading location 0xcd007361.

为什么我不能在arr打印字符串?

P.S。:我猜这个问题来自指针算法和函数char** arrto_array()的重新分配。 (如果之前的权利)我不确定处理它的标准方法是什么?

1 个答案:

答案 0 :(得分:0)

问题:

void to_array()中的第一个参数,即char* arr[ ]将指针的副本传递给char数组。函数内部指针的每次更改都不会影响到char数组外部的实际指针,特别是函数realloc()可能会将初始内存块移动到新位置,这会使传入的指针无效第一个参数。

解决方案:

修改函数void to_array()以返回修改后的arr,或者将函数的第一个参数修改为char** arr[ ] }。选择了后者,修改后的代码如下所示:

void to_array(char** arr[ ], size_t* size, char* quit)
{
    size_t index = 0;
    char* word = 0;
    char** expand_arr = 0;
    char sentinel = ' ';

    while ((word = get_word(sentinel)) && strcmp(word, quit) != 0)
    {
       if (index >= (*size))
       {
           (*size) *= 2;

           expand_arr = (char**) realloc((*arr), sizeof(char*) * (*size));

           if (expand_arr == NULL)
           {
                perror("to_array::bad realloc!\n");
               exit(-1);
           }

           (*arr) = expand_arr;
        }

        (*arr)[index++] = word;
    }  

    (*size)  = index;
}

然后函数调用必须完成:

to_array(&arr, &size, quit);