C: ошибка, вызванная назначением строки для массива struct с использованием strcpy - PullRequest
0 голосов
/ 04 октября 2019

Я читаю в текстовом файле, содержащем 10 строк и 3 столбца. Каждый элемент должен быть помещен в массив для дальнейшей манипуляции. Метод fileToArray выделяет каждую строку, и я могу успешно печатать каждую строку отдельно, однако я не могу назначить строки каждому индексу правильно.

Насколько я понимаю, у меня есть указатель на 10 dataArrays и мой переключательоператор, который по существу происходит, является dataArray [0] .pName = P1 ... dataArray [1] .pName = P2 ... и т. д. ... и аналогично для других переменных в структуре.

Текстовый файлимеет максимум 10 строк, поэтому инициализируется 10 массивов.

Является ли мое понимание ошибочным или есть какие-то явные ошибки в моем коде?

struct Processes
{
    char *pName;
    char *arvTime;
    char *srvTime;
};
void fileToArray(FILE *fp, struct Processes dataArray[])
{
    // temp[14] because 14 is the max size a line can be
    char temp[14];
    char delim[] = " \n";
    int count = 0;
    int a, b, c = 0;

    while(fgets(temp, 14, fp) != NULL)
    {
        char *ptr = strtok(temp, delim);

        while(ptr != NULL)
        {
            // printf("'%s'\n", ptr);
            // ^^^^ This line will successfully print out each string

            switch(count)
            {
            case 0:
                dataArray[a].pName = malloc(strlen(ptr + 1));
                strcpy(dataArray[a].pName, ptr);
                a++;
                count++;
                free(dataArray[a].pName);
                break;

            case 1:
                dataArray[b].arvTime = malloc(strlen(ptr + 1));
                strcpy(dataArray[b].arvTime, ptr);
                b++;
                count++;
                free(dataArray[b].arvTime);
                break;

            case 2:
                dataArray[c].srvTime = malloc(strlen(ptr + 1));
                strcpy(dataArray[c].srvTime, ptr);
                c++;
                count = 0;
                free(dataArray[c].srvTime);
                break;
            }


            ptr = strtok(NULL, delim);

        }
    }
}
int main(int argc, void *argv[])
{
    struct Processes dataArray[10];

    if(argc == 1)
    {
        FILE *fp;

        fp = fopen("process-data.txt", "r");

        fileToArray(fp, dataArray);

        fclose(fp);
    }
    return 0;
}
// Sample text file being read //
P1 1 5
P2 2 2
P3 11 5
P4 17 9
P5 3 1
P6 10 10
P7 4 3
P8 4 1
P9 7 8
P10 5 4

Запуск этого кода приводит к segfault, и я не уверен, почему. Глядя на другие подобные посты, похоже, что решение не использует malloc (), что заставляет меня думать, что я неправильно реализовал функцию.

Ответы [ 2 ]

2 голосов
/ 04 октября 2019

Этот бит кода делает полную противоположность тому, что вы думаете

malloc(strlen(ptr + 1))

Вместо того, чтобы выделять достаточно места для строки плюс 1 дополнительный для NUL в конце, он выделяет на единицу меньше, чемдлина строкиВы хотите переместить + 1 за пределы вызова на strlen следующим образом

malloc(strlen(ptr)+1)

Также вы должны инициализировать значения a и b до 0 или лучше, объедините a, b и c в одну переменную и увеличивайте ее только тогда, когда вы прочитали 3-й фрагмент информации.

0 голосов
/ 04 октября 2019

Для начала вам нужно передать функции количество элементов в массиве. Таким образом, объявление функции должно выглядеть следующим образом:

void fileToArray( struct Processes dataArray[], size_t n, FILE *fp );

. И лучше, когда функция возвращает количество заполненных элементов массива.

size_t fileToArray( struct Processes dataArray[], size_t n, FILE *fp );

и функцию можно вызывать внаименее похоже на

size_t n = fileToArray( dataArray, 10, fp );

В этом объявлении

int a, b, c = 0;

только переменная c инициализируется. Все остальные переменные, a и b, не инициализируются. Так, например, это утверждение

dataArray[a].pName = malloc(strlen(ptr + 1));

приводит к неопределенному поведению.

Это выражение

malloc(strlen(ptr + 1))

недопустимо. Это эквивалентно

malloc(strlen( &ptr[1] ))

И нет никакого смысла сразу освобождать память после ее выделения.

free(dataArray[a].pName);

Функцию можно определить следующим образом

size_t fileToArray( struct Processes dataArray[], size_t n, FILE *fp )
{
    // temp[14] because 14 is the max size a line can be
    char temp[14];
    char delim[] = " \n";

    size_t i = 0;

    for( ; i < n && fgets( temp, sizeof( temp ), fp) != NULL; i++ )
    {
        dataArray[i].pName   = NULL;
        dataArray[i].arvTime = NULL;
        dataArray[i].srvTime = NULL;

        char *ptr = strtok( temp, delim );

        for( size_t j = 0; j < 3 && ptr != NULL; j++ )
        {
            switch ( j )
            {
            case 0:
                dataArray[i].pName = malloc( strlen( ptr ) + 1 );
                strcpy( dataArray[i].pName, ptr );
                break;

            case 1:
                dataArray[i].arvTime = malloc( strlen( ptr ) + 1 );
                strcpy( dataArray[i].arvTime, ptr );
                break;

            case 2:
                dataArray[i].srvTime = malloc( strlen( ptr ) + 1 );
                strcpy( dataArray[i].srvTime, ptr );
                break;
            }

            ptr = strtok( NULL, delim );
        }
    }

    return i;
}
...