【问题标题】:Parse file in C to read char在 C 中解析文件以读取字符
【发布时间】:2012-10-26 10:16:13
【问题描述】:

假设我有一个文件,其中包含带有空格的随机字符,并且 \n 也包含随机字符。

我想查找这组字符,例如:UU、II、NJ、KU。所以目的是读取文件,寻找这类组并说出文件中有多少。

我的问题是空格和\n,因为如果我找到其中之一,我应该跳过它并再次搜索组。我找到了一个可以帮助我的解决方案,函数 strtok_r

http://www.codecogs.com/reference/computing/c/string.h/strtok.php?alias=strtok_r

我认为这将隔离完整的字符串,以便我可以一次读取一个。

这是一个好的解决方案还是应该采取其他方法?

【问题讨论】:

  • 逐行读取文本文件和缓冲区上的strstr()。使用strtok_r(),您会产生不必要的令牌。
  • 您应该始终考虑极端情况,这样我们就不必问了。如果你看到 UUU 或 KUU 会发生什么?
  • 我不知道,我会逐个字符地读取字符,但是按 2 处理 2,这意味着我会看到 U,然后看到另一个 U 和 count++,然后我会读取下一个字符,依此类推,如果我发现空格或与字母不同的任何内容,我将丢弃它和我之前读过的字符
  • 使用 strtok_r() 是一个很好的解决方案,因为它可以在循环中使用。如果您将 NULL 作为第一个参数传递,它将返回下一个令牌。在使用 strstr() 时,您必须维护一个指针来跟踪您已经阅读的内容。去 strtok_r()

标签: c file parsing strtok


【解决方案1】:

一个天真的解决方案可能会一次读取一个字符,当它是'U''I''N''K' 时,然后读取另一个字符以查看它是否是组中的下一个字符。如果是,则为该组增加一个计数器。所有其他字符都被简单地丢弃。

编辑:示例函数:

int count_uu = 0;
int count_ii = 0;
int count_nj = 0;
int count_ku = 0;

void check_next_char(int expected, FILE *input, int *counter);

void count(FILE *input)
{
    int ch;  /* Character we read into */

    while ((ch = fgetc(input)) != EOF)
    {
        switch (ch)
        {
        case 'U':
            check_next_char('U', input, &count_uu);
            break;
        case 'I':
            check_next_char('I', input, &count_ii);
            break;
        case 'N':
            check_next_char('J', input, &count_nj);
            break;
        case 'K':
            check_next_char('U', input, &count_ku);
            break;

        default:
            /* Not a character we're interested in */
            break;
    }
}

/* This function gets the next character from a file and checks against
   an `expected` character. If it is same as the expected character then
   increase a counter, else put the character back into the stream buffer */
void check_next_char(int expected, FILE *input, int *counter)
{
    int ch = fgetc(input);
    if (ch == expected)
        (*counter)++;
    else
        ungetc(ch, input);
}

【讨论】:

  • “如果是则为该组增加一个计数器”我将其改写为“实现状态机”。
  • 状态机似乎可以实现是啊!我想做的不是读取空格和\ n。想象一下,我有一个非常大的文件,使用 strtok 我不会读取那些“字符”,对吧?
  • @nunobhorta 您必须阅读所有字符,甚至包括空格。如果您按照我的回答逐个字符地阅读,或者按块阅读都没关系。但是,您就像您不感兴趣的任何其他角色一样跳过它。
  • @nunobhorta 添加了我的答案中概述的解决方案的一种可能实现。
  • 如果文件包含 WUUT 或 NJQ,UU 和 NJ 被计算在内但不应该被计算在内
【解决方案2】:

你也可以使用

https://github.com/leblancmeneses/NPEG/tree/master/Languages/npeg_c

如果您的搜索模式变得更加困难。

这是一个可以导出C版本的可视化工具: http://www.robusthaven.com/blog/parsing-expression-grammar/npeg-language-workbench

规则语法文档: http://www.robusthaven.com/blog/parsing-expression-grammar/npeg-dsl-documentation

规则

    (?<UU>): 'UU'\i; 
(?<II>): 'II'\i; 
(?<NJ>): 'NJ'\i; 
(?<KU>): 'KU'; // does not use \i so is case sensitive 

Find: UU / II / NJ / KU;
(?<RootExpression>): (Find / .)+;

输入 1:

 UU, II, NJ, KU  uu, ii, nJ, kU

输入 2:

jsdlfj023#uu, ii, nJ, kU $^%900oi)()*()  UU, II, NJ, KU  

【讨论】:

    猜你喜欢
    • 2020-08-01
    • 1970-01-01
    • 2012-10-29
    • 1970-01-01
    • 2017-07-08
    • 1970-01-01
    • 1970-01-01
    • 2011-06-16
    • 2021-03-21
    相关资源
    最近更新 更多