C: Чтение из файла строк в массив char * s - PullRequest
0 голосов
/ 08 апреля 2011

У меня есть что-то вроде этого (без проблем с пробелами), где я читаю файл со строками, разделенными знаком #, и пытаюсь прочитать каждую из них в массив char * s. Тем не менее, каждый char*, который содержит строку, будет иметь точную длину строки. Это немного глючит.

char * fragments[1000];
 char temp[20];
      while (i < numFrags) {
          if (fscanf(fp, "#%15[^#]#", temp) == 1) {
            char entry[strlen(temp)];
        entry = strcpy(entry, temp);
        fragments[i++] = entry;
        printf("%d\n", strlen(temp));

          }
      }

Мысли

1 Ответ

2 голосов
/ 08 апреля 2011

Ваша проблема в том, что вы повторно используете массив entry.

Посмотрите, как для всех i у нас есть fragments[i++] = entry;. В конце каждый фрагмент будет указывать на одно и то же место и, следовательно, будет содержать одну и ту же строку (в этом случае это будет последняя прочитанная строка).

Кажется, что вы пытались обойти это, используя оба массива temp и entry, но в итоге вы могли бы точно также сделать запись fscanf непосредственно в массив entry .


Другая проблема, которую вы можете получить, - это если ваши указатели указывают на массив, который был автоматически размещен в стеке (т. Е .: массив, объявленный внутри функции). Эти места в памяти повторно используются вашей программой после возврата из вашей функции, ваши указатели могут начать указывать на недопустимые данные (и поскольку это C, использование этих поврежденных строк может привести к всевозможным сбоям и плохому поведению программы).


Ваша проблема в основном связана с распределением памяти, поэтому существует множество решений.

  1. Сделать fragments массивом символьных массивов (вместо только указателей). Таким образом, у вас есть отдельный кусок памяти для каждой строки.

    char fragments[2000][20]; //can hold 2000 19-character strings
    for(i=0; i<N; i++){
        scanf("%d", fragments[i]);
    }
    

    Преимущество этого решения в том, что оно простое и вся память выделяется заранее.

  2. Использовать динамическое выделение памяти с malloc. Это позволяет вам выбирать различный размер массива для каждой строки, а также позволяет выбирать размер ваших массивов во время выполнения вместо времени компиляции.

    char* fragments[2000];
    char entry[MAX_FRAGMENT_LENGTH]; //temporary buffer for strings
    for(i=0; i<N; i++){
        scanf("%d", entry[i]);
        //dynamically allocate an array, just big enough to fit our string in.
        fragments[i] = malloc(sizeof(char) * (1 + strlen(entry));
        strcpy(fragments[i], entry);
    }
    

    Основным преимуществом этого метода является то, что он очень гибкий, но при этом достаточно простой. Основным недостатком является то, что вам нужно будет free все указатели, которые были malloc -оданы после того, как вы их сделали (в противном случае вы можете получить утечку памяти).

  3. Выполните «динамическое выделение» вручную, используя один большой буфер для хранения всех строк.

    char buffer[2000*20];
    char* fragments[2000];
    char* next_empty_location = buffer;
    for(i=0; i<N; i++){
        scanf("%d", next_empty_location);
        fragments[i] = next_empty_location;
        next_empty_location += strlen(next_empty_location) + 1;
    }
    

    Если вы не можете / не хотите / не можете использовать решение malloc, это то, что ближе всего. Это может быть труднее понять (в случае, если у вас возникли проблемы с C), но лучше всего оно подходит для смутного ограничения «каждый символ *, который содержит строку, будет точной длиной строки».

...