Чтение из файла и сохранение в массиве - PullRequest
6 голосов
/ 21 ноября 2010

Я написал следующую программу для построчного чтения файла и сохранения его в массиве слов. На выходе должны быть два случайных слова из массива. Но удивительно, что массив слов содержит только последнее слово, прочитанное повторно. Любая помощь в том, что пошло не так?

int main(){
 int i = 0;
 char line_buffer[BUFSIZ];
 char* words[20];
 FILE *fp = fopen("input.txt", "r");
  while (fgets(line_buffer, sizeof(line_buffer), fp)) {
  //printf("%s", line_buffer); 
  words[i] = line_buffer;
  i = i + 1;
 } 
 printf("%d", i);
 int j = rand()%8;
    int k = (j+1)%8;
 printf("%s %s", words[j], words[k]); 
 fclose(fp);
 return 0;
}

input.txt

nematode knowledge
empty bottle
nevertheless
claustrophobia
metamorphosis
acknowledgement
impossibility
never gave up

Ответы [ 4 ]

6 голосов
/ 21 ноября 2010

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

Вы получаете кредит за использование fgets(), а не gets(); это 100% правильное решение.


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

enum { MAXLINES = 30 };

int main(void)
{
    int i = 0;
    char lines[MAXLINES][BUFSIZ];
    FILE *fp = fopen("input.txt", "r");

    if (fp == 0)
    {
        fprintf(stderr, "failed to open input.txt\n");
        exit(1);
    }
    while (i < MAXLINES && fgets(lines[i], sizeof(lines[0]), fp))
    {
        lines[i][strlen(lines[i])-1] = '\0';
        i = i + 1;
    }
    fclose(fp);
    printf("%d\n", i);
    srand(time(0));
    int j = rand() % i;
    int k = (j+1) % i;
    printf("%s %s\n", lines[j], lines[k]); 
    return 0;
}

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

3 голосов
/ 21 ноября 2010
int main(){
 int i = 0;

 int BUFSIZE = 1000;
 char* words[20];
 FILE *fp = fopen("input.txt", "r");
 if (fp == 0){
        fprintf(stderr, "Error while opening");
        exit(1);
 }

 words[i] = malloc(BUFSIZE);
  while (fgets(words[i], BUFSIZE, fp)) {
        i++;
        words[i] = malloc(BUFSIZE);
 } 
 printf("Output: \n");
 srand(time(NULL));
 int j = rand()%i;
 int k = (j+1)%i;
 fflush(stdout);
 printf("%d - %s %d -%s", j, words[j], k, words[k]); 

 int x;
 for(x = 0; x<i; x++)
       free(words[x]);
 scanf("%d", x);
 fclose(fp);
 return 0;
}

пс. Проверить результат malloc

2 голосов
/ 21 ноября 2010

Вы многократно перезаписываете память в line_buffer. Массив words содержит только указатели на эту переменную.

Вы должны либо использовать многомерный массив, либо выделять память во время выполнения.

Кстати: плохие вещи произойдут, когда вы передадите в код более 20 строк ...

1 голос
/ 21 ноября 2010

Вы инициализировали генератор случайных чисел с srand?Объяснение, с примером того, как его использовать , доступно здесь .

...