【问题标题】:How do I save words from a file into an array?如何将文件中的单词保存到数组中?
【发布时间】:2020-02-14 23:53:27
【问题描述】:

***一些修改: 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

【问题讨论】:

  • 各种变量是如何声明的?
  • temp 的值在哪里?
  • 你不会增加j
  • 你为什么要尝试将字符串转换为数字(atoi)?
  • atoi() 将 ascii 字符串转换为整数,如果该字符串是一组可以表示整数的数字。如果字符串不代表整数,则返回 0。

标签: c arrays file fgets fgetc


【解决方案1】:

你可以这样做:

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]);
}

【讨论】:

    【解决方案2】:

    “我了解如何打开文件,...”

    不,不是真的,编码的一个基本规则是“不要硬编码文件名或使用幻数”。这意味着您不想:

    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 读取)并且您已验证文件流已打开以供读取。 p>

    要在不动态分配存储的情况下存储多个单词,您需要使用一个二维数组,其中每一行包含一个单词,并且列足以容纳任何单词加上 nul-terminating 字符,所以该行中的字符数组可以被视为字符串。未删节词典中最长的非医学词是 29 个字符(因此总列数为 30 列即可,但32 的下一个二次幂就可以了)

    由于您没有在代码中使用 magic-numbers,因此 #define 根据需要使用一个(或多个)常量。您可以使用全局 enum 来完成同样的事情。要为 31 个字符或更少的 128 个单词提供存储空间,您可以这样做:

    /* 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 一次读取一行)并收集字符直到'_'、@987654334找到 @ 或 EOF。为了保护您的words 数组边界,请确保您尝试填写的字数不超过ROWS。对于每个单词,通过确保读取的字符数不超过 COL-1-1nul-terminating 字符节省空间)来保护列边界

    将它们放在一起并使用几个计数器变量,您可以这样做:

        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 */
    

    (注意:跳出嵌套循环的唯一直接方法是使用旧的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
    

    查看一下,如果您还有其他问题,请告诉我。

    【讨论】:

    • 嗯。对于试图找出家庭作业问题的人来说,这似乎有点矫枉过正。
    • 嗯,这是霍布森对细节的选择。要么你提供一个答案的核心,提示许多后续行动,要么你提供一种可以应用于任何类似问题的方法,以及你这样做的原因。如果 OP 没有尝试,那么就不会有过度杀伤力。但是要使用提供的代码单独解决每个问题——你基本上会在同一个地方结束。矫枉过正——也许吧,但我一直讨厌那些让我感到困惑的老师,就像我一开始就带着问题去看他们一样。我们将为法学院保留苏格拉底式方法。
    • @HackSaw -- 但谢谢你带我回来,我搞砸了循环限制,切断了最后的 "cat" -- 已修复。幸运的是猫..
    猜你喜欢
    • 2014-01-31
    • 1970-01-01
    • 2020-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-29
    • 1970-01-01
    相关资源
    最近更新 更多