在文本文件中仅隔离“字符串”的方法是什么?(C语言相关)

4
我可以为您翻译以下内容:

我有一个文本文件,其中包含1个单词,后面跟着约100个浮点数。这些浮点数用空格、制表符或换行符分隔。此格式在整个文本文件中多次重复。

例如,这就是文本文件的样子:

one 0.00591 0.07272 -0.78274 ... 
0.0673 ...
0.0897 ...
two 0.0654 ...
0.07843 ...
0.0873 ...
three ...
...
...

我的问题是,如何计算文件中的单词数,我尝试使用fscanf,但一旦它读取第一个单词,之后我就必须跳过所有浮点数直到下一个单词。
任何帮助都将不胜感激。
谢谢。

7
你为什么要限制自己只使用 C 语言?使用 awk、perl 等语言来解决这些问题可能会更加容易。你考虑一下这个选项吗? - Dirk Herrmann
3
请展示您当前的代码。 - mikedu95
正如@DirkHerrmann所建议的那样,除非你有一个必须使用C语言完成的作业,否则使用其他编程语言会更容易。如果你只是想计算单词数,你也可以尝试使用wc命令来完成这个任务。 - vmonteco
http://ideone.com/Ugvj6Y - BLUEPIXY
scanf系列函数几乎总是在任何严肃的解析中都是错误的选择。 - Arlie Stephens
显示剩余2条评论
4个回答

5
我会给您提供一个高层次的解决方案概述,让您自行思考如何将其转换为C语言。
  • 初始化一个非数字单词计数器为零。
  • 逐行读取文件。对于每一行,重复以下步骤:
    • 将该行分词成以空格分隔的单词。对于每个单词,重复以下步骤:
      • 如果该单词可以解析为数字,则不做任何操作并继续。
      • 否则,增加计数器。

您可能会发现以下一些库函数很有用:

  • getline用于读取一行输入,虽然它不是官方标准库的一部分,但许多实现(包括GNU的libc)都提供了扩展功能。如果您没有它,可以使用fgetsrealloc自己编写。
  • strtok用于将字符串分词,但使用起来有些棘手。如果要手动分词,您会发现isspace很有用。您需要用NUL字节替换空白字符,以便将它们之间的字符视为单独的NUL终止字符串。
  • strtod用于尝试将字符数组解析为double

除了使用库函数将数字解析为double之外,您还可以实现自己的有限状态机。这是自动机理论中的经典教学示例。例如,请参见此讲座(向下滚动查找“浮点数的语言”)。


2
这里提供一种逐个字符执行的方法(无需缓冲区)。我非常确定该逻辑是正确的。
#include <stdio.h>

int is_alpha(char c)
{
    //only works for some character encodings
    return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
int main(void)
{
    FILE *file_ptr;
    int character;
    int prev_char_was_letter = 0;
    int word_count = 0;
    file_ptr = fopen("my_file.txt", "r");
    if (!file_ptr) 
    { 
        fprintf(stderr, "can't open file\n");
        return 1;
    }
    character = fgetc(file_ptr);
    while (character != EOF)
    {
        if (is_alpha(character) && !prev_char_was_letter) 
        {
            word_count++;
            prev_char_was_letter = 1;
        }
        else if (!is_alpha(character))
        {
            prev_char_was_letter = 0;
        }
        character = fgetc(file_ptr);
    }
    printf("%d\n", word_count);
    fclose(file_ptr);
}

1

除了已经提出来的解决方案外,另一个选择是使用strtok()进行分隔和isalpha()函数。下面是一个执行此任务的程序示例。

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

char delim[4]={' ','\t',0x0a,0x0d};
#define MAX_LINE 1024

int isaword(char *);

int main(int argc,char **argv)
{
    FILE *fp;
    char line[MAX_LINE];
    char *s;
    int wcnt=0;

    if(argc==1)
    {
        fp = stdin;
    }
    else
    {
        fp = fopen(argv[1],"r");
    }
    if(fp==0)
    {
        return -1; ///file not found
    }
    while(!feof(fp))
    {
        s=fgets(line,MAX_LINE,fp);
        if(s)
        {
            s=strtok(line,delim);
            while(s!=NULL)
            {
                if(isaword(s))
                {
                    wcnt++;
                }
                s=strtok(NULL,delim);    
            }
        }
    }
    fclose(fp);
    printf("word count = %d",wcnt);
    return 0;
}

int isaword(char *w)
{
    int result = 1;
    int i;
    for(i=0;i<strlen(w);i++)
    {
        result = isalpha(w[i]);
        if(result==0)
        {
            break;
        }
    }
    return result;
}

解决方案中的免责声明 - "单词"的定义基于isalpha函数的功能。


0
你可以像这样做:
void foo() {
    FILE *file = fopen("file.txt", "r");
    char buffer[10000]; // your choice
    while(fscanf(file, "%s", buffer) > 0) {
        int i = 0;
        int word = 0;
        int number_of_dots = 0;
        while(i < strlen(buffer)) {
            if(!isdigit(buffer[i]) && buffer[i] != '.') {
                if(!(i == 0 && buffer[i] == '-')) {
                    word = 1;
                    break;
                }

            }
            if(buffer[i] == '.') number_of_dots++;
            i++;
        }
        if(word || number_of_dots > 1) {
            printf("%s ", buffer);
            puts("It's a word!");
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接