Как сохранить слова из файла в массив? - PullRequest
1 голос
/ 18 октября 2019

*** Некоторые правки: ключевые слова int [16];

FILE *secretMessage;
secretMessage = fopen("C://Users/anyah/Fall2019/ECE_114/GreatGatsby.txt", "r");

char c;
char temp[100];
char temp2;
int i = 0;
int j = 0;

Выше указано, как объявляются мои переменные. Я использовал atoi (), потому что не мог сохранить слово в массиве

. Мне нужно найти текстовый файл и найти символ «_». За подчеркиванием следует слово, которое нужно поместить в массив. Затем мне нужно распечатать массив слов в обратном порядке, в котором они были найдены в текстовом файле.

Я понимаю, как открыть файл, создать массив и выполнить поиск символов. У меня возникли проблемы с выяснением того, как сохранить найденные символы в строку, а затем в массив.

while(1)
{
        c = fgetc(secretMessage);
        if (c == '_')
        {
             while(1)
             {
                temp2 = fgetc(secretMessage);

                if (temp2 == ' ')
                    break;
                else
                    { 
                    temp[j] = temp2;
                    j++; 
                    };
            }
            int words = atoi(temp);
            keywords[i] = words;
            i++;
        }

        if (c==EOF)
        break;
    }

У меня нет ошибок или предупреждений при компиляции - это мой текущий вывод:

0 4200137 0 16 0 4200393 -1 -1 0 4200160 0 9900960 0 50 0 1

Ответы [ 2 ]

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

"Я понимаю, как открыть файл, ..."

Нет, не совсем, одно из фундаментальных правил кодирования - это вы "Не жестко кодируйте имена файлов и не используйтеMagic-номер ". Это означает, что вы не хотите:

secretMessage = fopen("C://Users/anyah/Fall2019/ECE_114/GreatGatsby.txt", "r");

Передача аргументов в вашу программу - вот почему у вас есть аргументы для main(), например

int main (int argc, char **argv)

Просто укажите имя файла для чтения какаргумент вашей программы (или прочитанный из stdin по умолчанию). Для этого вы можете сделать что-то похожее на:

#include <stdio.h>
...
int main (int argc, char **argv) {
    ...
    /* use filename provided as 1st argument (stdin by default) */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        perror ("file open failed");
        return 1;
    }

На данный момент вы закончили открывать файл (или читаете из stdin), и у вас есть проверено что файловый поток открыт для чтения.

Чтобы хранить несколько слов без динамического выделения памяти, вам нужно будет использовать двумерный массив, где каждая строка содержит слово, а столбцы достаточны для хранения любогослово плюс символ , заканчивающийся нулями , поэтому массив символов в этой строке можно рассматривать как строку. Самое длинное немедицинское слово в словаре Unabridged составляет 29 символов (поэтому подойдет общее количество столбцов, равное 30, но следующая степень двойки 32 в порядке)

Так как вы не используете магические числа в своем коде, #define одну (или более) константу по мере необходимости. Вы можете использовать глобальный enum, чтобы выполнить то же самое. Чтобы обеспечить хранение 128 слов из 31 символа или менее, вы можете сделать:

/* if you need a constant, #define one (or more) */
#define ROWS 128    /* max no. of words to read  */
#define COLS 32     /* max no. of chars per-word */
...
    char words[ROWS][COLS] = {""};  /* 2D array to hold words */

С открытым файлом и объявленным хранилищем для хранения ваших слов, теперь вы просто читаете каждый символ с fgetc (или читаетестрока с fgets) и собирать символы до тех пор, пока не будут найдены '_', '\n' или EOF. Чтобы защитить границы массива words, убедитесь, что вы пытаетесь заполнить не более ROWS слов. Для каждого слова вы защищаете границы столбцов, гарантируя, что вы читаете не более COL-1 символов (-1, чтобы сэкономить место для символа , заканчивающегося нулем )

Соединяя это вместеи используя пару переменных счетчика, вы можете сделать:

    while (row < ROWS) {                /* while rows left in array */
        int c, col = 0;                 /* character c, column counter */
        /* loop over each char in word */
        for (c = fgetc(fp); col < COLS - 1; col++, c = fgetc(fp)) {
            if (c == EOF)               /* if EOF jump out of nested loops */
                goto done;
            if (c == '_' || c == '\n')  /* if char is '_' or '\n', get next */
                break;
            words[row][col] = c;        /* assign char to current word */
        }
        words[row++][col] = 0;          /* nul-terminate, advance word count */
    }
    done:;      /* goto label to jump to */

( note: единственный прямой способ выпрыгнуть из вложенных циклов - использовать старый оператор goto. Единственным ограничением является то, что вы не пытаетесь выпрыгнуть из функции, разбивая вложенные циклы - это нормально)

Полный пример может быть:

#include <stdio.h>

/* if you need a constant, #define one (or more) */
#define ROWS 128    /* max no. of words to read  */
#define COLS 32     /* max no. of chars per-word */

int main (int argc, char **argv) {

    char words[ROWS][COLS] = {""};  /* 2D array to hold words */
    int row = 0, i;                 /* row (word) and loop counter */
    /* use filename provided as 1st argument (stdin by default) */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        perror ("file open failed");
        return 1;
    }

    while (row < ROWS) {                /* while rows left in array */
        int c, col = 0;                 /* character c, column counter */
        /* loop over each char in word */
        for (c = fgetc(fp); col < COLS - 1; col++, c = fgetc(fp)) {
            if (c == EOF)               /* if EOF jump out of nested loops */
                goto done;
            if (c == '_' || c == '\n')  /* if char is '_' or '\n', get next */
                break;
            words[row][col] = c;        /* assign char to current word */
        }
        words[row++][col] = 0;          /* nul-terminate, advance word count */
    }
    done:;      /* goto label to jump to */

    if (fp != stdin)   /* close file if not stdin */
        fclose (fp);

    for (i = row-1; i >= 0; i--)
        printf ((i != row - 1) > 0 ? " %s" : "%s", words[i]);
    putchar ('\n');
}

Последний цикл просто выводит словав обратном порядке и троичный в операторе printf просто гарантирует, что вы не печатаете пробел перед выводом первого слова.

Пример входного файла

$ cat dat/backwardsfleas.txt
cat_lucky_none_has_cat_my_fleas_has_dog_my

Пример использования / Вывод

$ ./bin/arrayrevwords dat/backwardsfleas.txt
my dog has fleas my cat has none lucky cat

Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.

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

Вы можете сделать что-то вроде этого:

char strings[100][100]; // array of 100 strings, each of them has no more than 99 meaningful characters
while () // outer loop by words
{
    while () // inner loop by characters. Don't forget to check EOF here too!
    {
        strings[i][j] = temp2;
        j++;
    }
    strings[i][j] = 0; // null-terminated string!
    i++;
}
while () // printing loop by words
{
    printf("%s", strings[i]);
}
...