从文本文件中读取并用C语言将行解析为单词

从文本文件中读取并用C语言将行解析为单词,c,file,file-io,io,C,File,File Io,Io,我是C和系统编程的初学者。对于家庭作业,我需要编写一个程序,将stdin解析行中的输入读取为单词,并使用systemv消息队列将单词发送到排序子进程(例如,计算单词)。我在输入部分卡住了。我正在尝试处理输入,删除非字母字符,将所有字母单词放在小写,最后,将一行单词拆分为多个单词。到目前为止,我可以用小写字母打印所有字母单词,但单词之间有行,我认为这是不正确的。有人能看一下并给我一些建议吗 来自文本文件的示例:荷马的《荷马的伊利亚特》的古腾堡计划电子书 我认为正确的输出应该是: the proje

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

来自文本文件的示例:荷马的《荷马的伊利亚特》的古腾堡计划电子书

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

the
project
gutenberg
ebook
of
the
iliad
of
homer
by
homer
但我的输出如下:

project
gutenberg
ebook
of
the
iliad
of
homer
                         <------There is a line there
by
homer

看起来你在用空格分隔单词,所以我认为

while ((c =fgetc(input_file)) != EOF )
{
    if (isalpha(c))
    {
        c = tolower(c);
        putchar(c);
    }
    else if (isspace(c))
    {
       putchar('\n');
    }
}

这也行。假设您的输入文本在单词之间的空格不超过一个。

我怀疑您确实希望将所有非字母字符作为分隔符处理,而不仅仅是将空格作为分隔符处理并忽略非字母字符。否则,
foo--bar
将显示为单个单词
foobar
,对吗?好消息是,这让事情变得更容易。您可以删除
isspace
子句,只需使用
else
子句即可

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

例如:

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
应该显示为单独的单词
foo
bar
,但是
它的
应该真正显示为单独的单词
it
s
?因此,使用
isalpha
作为“单词字符”的规则也意味着,
2nd
将显示为
nd


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

我认为您只需要忽略任何非字母字符
!isalpha(c)
否则转换为小写。在这种情况下,当你找到一个单词时,你需要保持跟踪

int found_word = 0;

while ((c =fgetc(input_file)) != EOF )
{
    if (!isalpha(c))
    {
        if (found_word) {
            putchar('\n');
            found_word = 0;
        }
    }
    else {
        found_word = 1;
        c = tolower(c);
        putchar(c);
    }
}
如果您需要在诸如“Is Not”之类的单词中处理撇号,那么这应该可以做到-

int found_word = 0;
int found_apostrophe = 0;
    while ((c =fgetc(input_file)) != EOF )
    {
    if (!isalpha(c))
    {
        if (found_word) {
            if (!found_apostrophe && c=='\'') {
                found_apostrophe = 1;
            }
            else {
                found_apostrophe = 0;
                putchar('\n');
                found_word = 0;
            }
                }
    }
    else {
        if (found_apostrophe) {
            putchar('\'');
            found_apostrophe = 0;
        }
        found_word = 1;
        c = tolower(c);
        putchar(c);
    }
}

+1用于发布合理代码。一个建议:
perror(输入)
。没有什么比没有文件名的错误消息更糟糕的了。strtok函数可能会有所帮助。请注意,这将停止一些可能需要保留的标点符号,包括连字符和撇号。您可能需要对它们进行特殊处理,在某些情况下(即连字符后跟换行符)无论如何都会将它们丢弃。否则,像“不是”这样的词将不会保留它们原来的表达方式。@WhozCraig:是;因为OP明确跳过了所有标点符号,所以我选择了同样的方法。但如果这不是他想要的,他需要额外的代码。我将在答案中添加一个注释。允许
的问题不是
,而是它还应该允许
作为“单个单词”。那么,这取决于输入是否会成为下一个问题。@Jongware:是的,这里没有一个明显正确的答案;OP必须理解这个问题,并找出符合其目的的答案。考虑到他描述家庭作业问题的方式,我认为最简单的答案可能是正确的。但他应该仔细考虑并做出决定。所以谁说得对。@abarnert:非常感谢你回答我的问题。是的,你说得对。我想处理所有非字母字符作为分隔符。我用你的建议来修正我的代码。所有的字母都紧挨着。有没有办法把一行字分成多个字?我将编辑我的代码以向您展示。再次感谢。输入中只有一个逗号没有复制到输出。该概要还描述了“词语”。尽管如此,简明扼要;易于调整。
int found_word = 0;

while ((c =fgetc(input_file)) != EOF )
{
    if (!isalpha(c))
    {
        if (found_word) {
            putchar('\n');
            found_word = 0;
        }
    }
    else {
        found_word = 1;
        c = tolower(c);
        putchar(c);
    }
}
int found_word = 0;
int found_apostrophe = 0;
    while ((c =fgetc(input_file)) != EOF )
    {
    if (!isalpha(c))
    {
        if (found_word) {
            if (!found_apostrophe && c=='\'') {
                found_apostrophe = 1;
            }
            else {
                found_apostrophe = 0;
                putchar('\n');
                found_word = 0;
            }
                }
    }
    else {
        if (found_apostrophe) {
            putchar('\'');
            found_apostrophe = 0;
        }
        found_word = 1;
        c = tolower(c);
        putchar(c);
    }
}