【问题标题】:Scan Numbers among letters in a Sentence扫描句子中字母之间的数字
【发布时间】:2011-02-18 06:59:25
【问题描述】:

我有一个很简单的问题。 (使用 C)

在诸如

这样的句子中

In this document, there are 345 words and 6 figures

我如何扫描 345 和 6 而忽略介于两者之间的所有内容?

我试过fscanf(FILE *pointer,"%d %d",&words,&figs); 但它只获得第一个值...

我做错了什么?

编辑

对不起,我忘了提,声明总是固定的...... In this document, there are # words and # figures

【问题讨论】:

  • 句子固定了吗?例如,是否总是在这个文档中,有 X 个单词和 Y 个数字,其中 XY 是数字?
  • @Jacob,是的,它已修复.. 我认为 Georg Fritzsche 有最好的方法,使用 %*[^0-9] 方法.. 我现在检查一下
  • @Zazu:然后你就可以直接索引到字符串/fseek文件,不用担心扫描。顺便说一句,我看到了两个很好的答案,很高兴为那些应该有效的答案投票……
  • @Potatoswatter,我正试图在我的代码中解决它们,一旦我完成了,我就支持 cmets :)
  • @Zazu:对于我们的回答者来说,如果他们已经被排名,就更容易看到一个好的答案是否已经存在。为什么阅读它们的工作没有点赞的回报?

标签: c file scanf


【解决方案1】:

这是因为scanf() 系列的函数旨在读取使用printf() 编写的字符串,类似于函数具有相同格式。既然是这种情况,就无需求助于字符串解析和整数转换:

const char *format = "In this document, there are %d words and %d figures";

int n = fscanf(fp, format, &words, &figs);
if (n != 2) //--- not recognized ...

当然,格式必须完全相同,至少在读取的值之前是这样,因此将其保存在 一个 位置会更安全,紧随 Once and Only Once 原理,需要测试fscanf()返回码。

【讨论】:

    【解决方案2】:

    我认为这样做的方法是将strpbrkstrtol结合起来。

    看起来有点像:

    long int n;
    const char *p = str;
    while( (p = strpbrk(p, "-0123456789")) ) {
        n = strtol(p, &p, 0);
        handle(n);
    }
    

    更新:
    根据您的需要,使用strtol(p, &p, 10) 可能会更好,因为在我刚刚运行的测试中,我发现它确实将Testing0x100what happens if I use base16 hex 转换为256, 16

    【讨论】:

      【解决方案3】:

      您的格式字符串的问题是格式字符串中的空格只会导致空白被忽略。

      如果在下一个换行符之前可能没有第二个数值并且您也容易受到任意输入长度的影响,我认为仅使用 scanf() 是不可能的。但是fgets()/sscanf() 组合应该没问题:

      int a=0, b=0;
      char buf[255];
      fgets(buf, sizeof(buf), stdin);
      sscanf(buf, "%*[^0-9]%d%*[^0-9]%d", &a, &b);
      

      但是,如果您知道始终存在两个单独的数值并且输入长度固定为合理的长度,则应该执行以下操作:

      int a=0, b=0;
      scanf("%*[^0-9]%d%*[^0-9]%d", &a, &b);
      

      【讨论】:

      • 这是这里最简单的方法,scanf("%d%*[^0-9]%d", &a, &b); 但它对我不起作用.. 为什么?
      • @Zazu:它是否提供更多信息,如标识符(即变量或函数名称)?
      • @Georg:这是我的确切代码fscanf(file,"%*[^0-9]%d%*[^0-9]%d",&word,&doc); ...它不起作用:(
      • 变量 worddoc 是否在某处定义?
      • 他们是,但是 int doc,word;现在我让它们int doc=0,word=0; .. 它工作了.. 但是当我打印它们的值时,它们是 =0 :S 它没有扫描文档
      【解决方案4】:

      您需要对字符串进行标记并按顺序检查每个单词。下面的代码是从a C++ reference修改而来的,调用的其实是C。

      /* strtok example */
      #include <stdio.h>
      #include <string.h>
      
      int main ()
      {
        char str[] ="- This, a sample 9876 string.";
        char * pch;
        printf ("Splitting string \"%s\" into tokens:\n",str);
        pch = strtok (str," ,.-");
        while (pch != NULL)
        {
          if (pch[0] >= '0' && pch[0] <= '9')
          {
              // It's a number
          }
          pch = strtok (NULL, " ,.-");
        }
        return 0;
      }
      

      【讨论】:

        【解决方案5】:

        如果您不知道输入字符串的确切格式,我认为 scanf/fscanf 在这种情况下不会满足您的需求。

        更好的方法可能是解析输入行,直到您遇到空格、句点或逗号(或其他分隔符),然后查看您目前所拥有的内容是否仅由数字组成。如果是这样,那么你有一个数字,否则,你有一个单词(假设这里的句子格式正确)。然后,您可以将该数字存储在数组或任何您想要的数据结构中。

        但是,如果句子结构始终采用完全相同的格式,您可以使用这样的方法:

            int main() {
              char* buff = "In this document, there are 345 words and 6 figures";
              char extra1[5000];
              char extra2[5000];
              int a,b;
              sscanf(buff,"%[In this document, there are ]%d%[ words and ]%d", extra1, &a, extra2, &b);
              cout<<a<<" "<<b<<endl;
              return 0;
            }
        

        【讨论】:

        • 感谢您的回复 :) 如果声明已修复,该怎么办?
        • 如果声明是固定的,那么你可以使用类似我上面的东西。如果没有,你需要一种不同的方法,比如我上面提到的“更好”的方法。
        • %[abc] 用于字符集(您可以使用%*[abc] 丢弃结果)。在这里,sscanf(buf,"Here are %d words.",&amp;words) 之类的内容就足够了。
        猜你喜欢
        • 2018-05-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-16
        • 1970-01-01
        • 2020-12-14
        • 1970-01-01
        相关资源
        最近更新 更多