【问题标题】:use `sscanf` the same as `istringstream`?使用 `sscanf` 和 `istringstream` 一样吗?
【发布时间】:2014-11-15 03:03:55
【问题描述】:

使用istringstream,我们可以从一个字符串中一个一个地读取项目,例如:

istringstream iss("1 2 3 4");
int tmp;
while (iss >> tmp) {
    printf("%d \n", tmp);  // output: 1 2 3 4
}

我们可以使用sscanf 来做到这一点吗?

【问题讨论】:

    标签: c++ scanf istringstream


    【解决方案1】:

    你可以用这个非常接近地模拟它

    const char *s = "1 2 3 4";
    int tmp, cnt;
    
    for (const char *p = s; sscanf(p, "%d%n", &tmp, &cnt) == 1; p += cnt)
      printf("%d\n", tmp);
    

    【讨论】:

    • 我不确定%n 是否被sscanf 计算在内。我会改为测试>= 1
    • @Basile Starynkevitch:不应该计算它。规范说:“%n 指令的执行不会增加在完成fscanf 函数的执行时返回的赋值计数。”
    • scanf(3)“C 标准说:“执行 %n 指令不会增加执行完成时返回的分配计数”,但勘误表似乎与此相矛盾。可能最好不要对 %n 次转换对返回值的影响做出任何假设。"
    • @Basile Starynkevitch:我不知道他们从哪里得到这个以及他们指的是什么“更正”。 C99 和更高版本的规范对此非常具体:%n 不计算在内。此外,C99 明确指出 *(赋值抑制)不能与 %n(未定义的行为)一起使用,这也与链接中的文本相矛盾。我认为链接上的文字是一个维护/审查不佳的多个历史变化的综合体。
    • @Basile Starynkevitch:在这种简单的情况下,当每次调用只读取一个字段时,“不对返回值做任何假设”是可能的。但是在读取多个字段的更复杂的情况下,如果不确切知道%n 的行为方式,就不可能编写正确的代码。
    【解决方案2】:

    如果您可以使用strtok 将字符串分成单独的标记

      char str[] ="1 2 3 4";
      char * pch;
      pch = strtok (str," ");
      while (pch != NULL)
      {
        int tmp;
        sscanf( pch, "%d", &tmp );
        printf( "%d \n", tmp );
        pch = strtok (NULL, " ");
      }
    

    否则,scanf 支持 %n 转换,可以让您计算到目前为止消耗的字符数(我还没有测试过,可能存在我没有考虑过的陷阱);

      char str[] ="1 2 3 4";
      int ofs = 0;
      while ( ofs < strlen(str) )
      {
        int tmp, ofs2;
        sscanf( &str[ofs], "%d %n", &tmp, &ofs2 );
        printf( "%d \n", tmp );
        ofs += ofs2;
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-01-21
      • 2020-05-25
      • 1970-01-01
      • 2014-04-15
      • 2016-09-29
      • 2011-08-17
      • 1970-01-01
      • 2019-04-28
      相关资源
      最近更新 更多