首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从文本文件中读取,然后用C语言将行解析为单词

从文本文件中读取,然后用C语言将行解析为单词
EN

Stack Overflow用户
提问于 2013-08-07 17:05:05
回答 3查看 67.2K关注 0票数 13

我是C和系统编程的初学者。对于作业作业,我需要编写一个程序,将输入从stdin解析行读入单词,并使用System消息队列将单词发送到排序子进程(例如,计数单词)。我在输入部分被卡住了。我正在尝试处理输入,删除非字母字符,将所有alpha单词放入小写,最后,将一行单词拆分成多个单词。到目前为止,我可以用小写打印所有字母单词,但是单词之间有一行,我认为这是不正确的。谁能看一下,给我一些建议吗?

文本文件中的示例:荷马伊利亚特的Gutenberg EBook项目,由荷马

我认为正确的产出应该是:

代码语言:javascript
复制
the
project
gutenberg
ebook
of
the
iliad
of
homer
by
homer

但我的产出如下:

代码语言:javascript
复制
project
gutenberg
ebook
of
the
iliad
of
homer
                         <------There is a line there
by
homer

我认为空行是由",“和" by”之间的空格造成的。我试过“如果是空间(C),那就什么都不做”,但它不起作用。我的密码在下面。如有任何帮助或建议,我们将不胜感激。

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>


//Main Function
int main (int argc, char **argv)
{
    int c;
    char *input = argv[1];
    FILE *input_file;

    input_file = fopen(input, "r");

    if (input_file == 0)
    {
        //fopen returns 0, the NULL pointer, on failure
        perror("Canot open input file\n");
        exit(-1);
    }
    else
    {        
        while ((c =fgetc(input_file)) != EOF )
        {
            //if it's an alpha, convert it to lower case
            if (isalpha(c))
            {
                c = tolower(c);
                putchar(c);
            }
            else if (isspace(c))
            {
                ;   //do nothing
            }
            else
            {
                c = '\n';
                putchar(c);
            }
        }
    }

    fclose(input_file);

    printf("\n");

    return 0;
}

编辑**

我编辑了我的代码,最后得到了正确的输出:

代码语言:javascript
复制
int main (int argc, char **argv)
{
    int c;
    char *input = argv[1];
    FILE *input_file;

    input_file = fopen(input, "r");

    if (input_file == 0)
    {
        //fopen returns 0, the NULL pointer, on failure
        perror("Canot open input file\n");
        exit(-1);
    }
    else
    {
        int found_word = 0;

        while ((c =fgetc(input_file)) != EOF )
        {
            //if it's an alpha, convert it to lower case
            if (isalpha(c))
            {
                found_word = 1;
                c = tolower(c);
                putchar(c);
            }
            else {
                if (found_word) {
                    putchar('\n');
                    found_word=0;
                }
            }

        }
    }

    fclose(input_file);

    printf("\n");

    return 0;
}
EN

Stack Overflow用户

发布于 2013-08-07 17:24:49

我怀疑你真的想把所有非字母字符作为分隔符来处理,而不仅仅是把空格作为分隔符来处理,而忽略非字母字符。否则,foo--bar将显示为一个单词foobar,对吗?好消息是,这会让事情变得更简单。可以删除isspace子句,只需使用else子句即可。

同时,不管你是否特别对待标点符号,你都有一个问题:你为任何空格打印换行符。因此,以\r\n\n结尾的行,甚至以.结尾的句子,都会打印空行。最明显的方法是跟踪最后一个字符或标志,所以只有在以前打印过字母的情况下才打印换行符。

例如:

代码语言:javascript
复制
int last_c = 0

while ((c = fgetc(input_file)) != EOF )
{
    //if it's an alpha, convert it to lower case
    if (isalpha(c))
    {
        c = tolower(c);
        putchar(c);
    }
    else if (isalpha(last_c))
    {
        putchar(c);
    }
    last_c = c;
}

但是你真的想把所有的标点符号都一样对待吗?问题陈述暗示着你会这样做,但在现实生活中,这有点奇怪。例如,foo--bar可能应该显示为单独的单词foobar,但是it's真的应该作为单独的单词its出现吗?因此,使用isalpha作为“单词字符”的规则也意味着,比方说,2nd将显示为nd

因此,如果isascii不是区分单词字符和分隔符的用例的适当规则,那么您必须编写自己的函数来做出正确的区分。您可以很容易地用逻辑(例如,isalnum(c) || c == '\'')或表(仅由128个in组成的数组,因此函数是c >= 0 && c < 128 && word_char_table[c])来表示这样的规则。这样做有一个额外的好处,就是以后可以扩展代码以处理拉丁语1或Unicode,或者处理程序文本(与英语文本有不同的单词字符)或…。

票数 1
EN
查看全部 3 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18109458

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档