Код для хранения строк файла в двойном указателе символа хранит одну и ту же строку во всех элементах - PullRequest
0 голосов
/ 10 ноября 2019

Я хочу создать код, который читает файл и сохраняет каждую его строку в строку. С другой стороны, я храню эти строки в другом массиве, который делает двойной указатель на символ. Код правильно печатает файл, но когда я пытаюсь напечатать строку (одну из строк) случайным образом, он всегда выводит последнюю строку файла ("{").

#include <stdio.h>
#include <stdlib.h>

int main()
{
    //I Open the file
    FILE* file_1 = fopen ("Caso2.ll", "r");
    char string[1000];
    //I create a double pointer to char of size 1000 (big enough to store any string)
    char ** string_2 = (char**) malloc(sizeof(char *)*1000);
    int i =0;
    //While fgets is different from NULL
    while (fgets(string, 1000, file_1)!= NULL)
    {
        //I define each element of string_2 as a char pointer (string)
        string_2[i] = (char *)malloc(sizeof(char)*1000);
        //and attribute string to string_2, thus storing the read line into it
        string_2[i] = string;
        //I print string_2
        printf("%s", string_2[i]);
        i++;
    }
    //Until now everything is okay. The code is printing the file okay.
    printf("\n\n\n\n\n\n\n");
    //Here is where the error is. When I try to print a random element of 
    //string_2, it always prints "{", the last line of the file
    fputs(*(string_2 + 5), stdout);
    system("pause");
    return 0;
}

Ответы [ 2 ]

2 голосов
/ 10 ноября 2019

относительно:

string_2[i] = string;

Это всегда копирует (ТОЛЬКО) указатель на string, поэтому все записи в string_2 указывают на string, а string содержит то, что когда-либо читалось последним.

Предложите заменить это утверждение на:

strcpy( string_2[i], string );

относительно:

fputs(*(string_2 + 5), stdout);

, когда будет реализован strcpy(), тогда вызов fputs() не будетработа из-за дополнительной де-ссылки. предложить:

fputs( string_2 + 5, stdout );

Опубликованный код содержит значительную утечку памяти. Чтобы исправить это, предложите: замените:

string_2 = (char *)malloc(sizeof(char*)*1000);

на

string_2 = calloc( sizeof( char *), 1000 );

, чтобы все указатели в string_2 содержали NULL, а затем вставьте следующее непосредственно перед оператором return:

for( int i=0; i<MAX_INPUT_LINES; i++ )
{
    free( string_2[i] );
}
free( string_2 );

Примечание: функция: free() без проблем обрабатывает NULL-параметр.

для надежного кода относительно этого вида оператора:

string_2[i] = (char *)malloc(sizeof(char)*1000);

всегдапроверьте (! = NULL) возвращаемое значение, чтобы убедиться, что операция прошла успешно.

Примечание: 1000 - это «магическое» число. Чтобы использовать осмысленное имя, предложите:

#define MAX_INPUT_LINES 1000

Затем используйте имя: MAX_INPUT_LINES при вызове calloc()

Сделайте подобное имя при выделении места для каждой строки из входного файла.

Код должен прекратить ввод строк, если во входном файле более 1000 строк. предложить заменить:

while (fgets(string, 1000, file_1)!= NULL)

на:

while ( i < MAX_INPUT_LINES && fgets(string, 1000, file_1)!= NULL)
1 голос
/ 10 ноября 2019

Проблема в том, как вы присваиваете данные массиву string_2. В вашем цикле чтения вы делаете это:

string_2[i] = string;

, который присваивает указателю , который равен string_2[i] значению указателя , равному string. Поэтому, когда вы позже измените данные в string, вы также измените данные, на которые указывает каждый ранее назначенный указатель string_2[i]. Таким образом, когда ваш цикл заканчивается, все указатели string_2[] будут указывать на (одинаковые) данные string.

Что вы должны сделать вместо этого, в вашем цикле:

strcpy(string_2[i], string);

Это скопирует текущие данные в string в ваш проиндексированный и (правильно) выделенный новый string_2[i] буфер.

Не стесняйтесь спрашиватьдальнейшие разъяснения и / или объяснения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...