C 我想从包含段落的文件中读取文本,拆分单词,然后分配给数组

C 我想从包含段落的文件中读取文本,拆分单词,然后分配给数组,c,arrays,string,readfile,C,Arrays,String,Readfile,文本文件包含: “从查尔斯·达尔文的《双城记》开始 这是最好的时代,也是最糟糕的时代。这是一个时代 关于智慧,那是愚蠢的时代,那是智慧的时代 信仰,这是怀疑的时代。” 我不知道我哪里做错了 #包括 #包括 #包括 #定义最多20个单词 #定义最多1000个单词 #定义最大单词长度80 int main() { char story[max_story_words][max_word_length],ch; int num_words=1; FILE*FILE_story=fopen(“TwoCi

文本文件包含: “从查尔斯·达尔文的《双城记》开始

这是最好的时代,也是最糟糕的时代。这是一个时代 关于智慧,那是愚蠢的时代,那是智慧的时代 信仰,这是怀疑的时代。”

我不知道我哪里做错了

#包括
#包括
#包括
#定义最多20个单词
#定义最多1000个单词
#定义最大单词长度80
int main()
{
char story[max_story_words][max_word_length],ch;
int num_words=1;
FILE*FILE_story=fopen(“TwoCitiesStory.txt”、“r”);
if(file_story==NULL)
printf(“无法打开%s\n”,“TwoCitiesStory.txt”);
否则{
ch=fgetc(文件/故事);
while(ch!=EOF){
如果(ch=''| | ch='\n')
num_words++;
ch=fgetc(文件/故事);
}
int i=0;
//将每个单词分配给故事[i]

虽然(i你的代码最大的问题是:(1)在你读取流到
EOF
计数单词后,你没有将
fgets
读取的每一行标记为单词,然后分配给
故事[i]
。发生的是
fgets
一次读取整行(这就是你想要的)。但是,你需要把每一行分成几个字,去掉标点符号

要做到这一点,您需要
strtok
strep
strtok
非常适合这项工作。仔细选择分隔列表将允许您将行拆分为单词,同时将单词分配给
story[i]

此外,看在上帝的份上,让你的代码呼吸吧……是的,你可以把所有的东西塞进一块,去掉所有的空格,这在我的书中几乎是混淆。行距和语法稍微扩展一下,使你的代码更具可读性。(你甚至可能会发现这有助于你更容易编写代码)但每个人都有自己的。如果你喜欢浓缩,那很好

查看以下内容,如果您有问题,请告诉我。我更改了代码以将文件名作为参数,因此它不是硬编码的。您可以运行程序并将文件名放在命令行上。祝您好运:

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

#define max_words 20
#define max_story_words 1000
#define max_word_length 80

int main (int argc, char **argv)
{
    if (argc < 2 ) {
        fprintf (stderr, "Error: insufficient input, usage: %s filename\n", argv[0]);
        return 1;
    }

    char story[max_story_words][max_word_length] = {{0}};
    char line[max_story_words] = {0};
    char *p;
    char ch = 0;
    char *punct="\n ,!.:;?-";
    int num_words = 1;
    int i = 0;
    FILE *file_story = fopen (argv[1], "r");

    if (file_story==NULL) {
        printf("Unable to open '%s'\n",argv[1]);
        return (EXIT_FAILURE);
    }

    /* count words */
    while ((ch = fgetc (file_story)) != EOF) {
        if (ch == ' ' || ch == '\n')
            num_words++;
    }

    /* you already read file_story to EOF, so you must rewind to
       reset the EOF condition and place the file pointer at the start */
    rewind (file_story);

    i = 0;
    /* read each line in file */
    while (fgets (line, max_word_length, file_story) != NULL) 
    {
        /* tokenize line into words removing punctuation chars in punct */
        for (p = strtok (line, punct); p != NULL; p = strtok (NULL, punct))
        {
            /* convert each char in p to lower-case with tolower */
            char *c = p;
            for (; *c; c++)
                *c = tolower (*c);

            /* manually convert each char in p to lower-case */
            // char *c = p;       /* save start address of p */
            // for (; *c; c++)
            //     if ('A' <= *c && *c <= 'Z')
            //         *c += 32;

            /* copy token (word) to story[i] */
            strncpy ((char *)story[i], p, strlen (p));
            i++;
        }
    }

    /* output array */
    for(i = 0; i < num_words; i++)
        printf ("story[%d]: %s\n", i, story[i]);

    printf("\ntotal words: %d\n\n",num_words);

    return (EXIT_SUCCESS);
}
#包括
#包括
#包括
#包括
#定义最多20个单词
#定义最多1000个单词
#定义最大单词长度80
int main(int argc,字符**argv)
{
如果(argc<2){
fprintf(stderr,“错误:输入不足,用法:%s filename\n”,argv[0]);
返回1;
}
char story[max_story_words][max_word_length]={{{0};
字符行[max_story_words]={0};
char*p;
char ch=0;
char*punct=“\n,!:;?-”;
int num_words=1;
int i=0;
FILE*FILE_story=fopen(argv[1],“r”);
if(file_story==NULL){
printf(“无法打开“%s”\n”,argv[1]);
返回(退出失败);
}
/*数词*/
而((ch=fgetc(文件故事))!=EOF){
如果(ch=''| | ch='\n')
num_words++;
}
/*您已经将文件_story读取到EOF,因此必须倒带到
重置EOF条件并将文件指针置于起始位置*/
倒带(文件/故事);
i=0;
/*读取文件中的每一行*/
while(fgets(行、最大字长、文件和故事)!=NULL)
{
/*将行标记为单词,删除点号中的标点字符*/
for(p=strtok(行,点);p!=NULL;p=strtok(NULL,点))
{
/*用tolower将p中的每个字符转换为小写*/
char*c=p;
对于(;*c;c++)
*c=耐受力(*c);
/*手动将p中的每个字符转换为小写*/
//char*c=p;/*保存p的起始地址*/
//对于(;*c;c++)

//if('A')谢谢你的帮助。我只是一个初学者。如果我想在存储到数组之前将一个单词的所有字母都转换成小写怎么办?我在输出数组之前添加了这个循环,但不起作用:for(int I=0;iAdd
#include
作为头文件,然后更改
strncpy((char*)story[I],p,strlen(p));
将所有字符转换为小写。我将更新示例。您选择学习C是正确的。没有其他东西能提供C所能提供的力量和控制,但强大的力量带来了巨大的责任。学习C是一段旅程,而不是一场比赛。享受这段旅程。此外,手动完成时无需添加
#包含
。请查看ASCII字符。请注意,所有小写字符的值都比大写版本大。因此,您只需检查字符串中的每个字母,如果它是大写,则向其值中添加32,将其更改为小写。(还有一个
tolower(char p)
函数在
ctype.h
中。您可以使用任何一种方法。(
为字符串中的每个字符添加32
或调用
tolower(ch)
)。注意:您必须保存
p
的原始起始地址,以便在调用
strncpy
p
仍然指向单词的开头,因此只需创建另一个字符指针
char*c=p;
并在转换为lowerca时使用指针
c
逐步遍历单词的每个字符即可se.非常感谢,再次抱歉打扰您。如果您使用我提到的文本文件运行此代码,首先在第2行有一个完全空的行,在文本的最后一个句号后有一个不必要的空格(错误后)。您将得到48个字的输出,其中有2个空格,而它本来应该是46。@david