【问题标题】:Cleaning scanf buffer清洗 scanf 缓冲液
【发布时间】:2017-05-21 20:37:17
【问题描述】:

我正在尝试读取以下格式的输入

XgYsKsC XgYsKsC

其中 X、Y、K 是双精度值,C 是字符。

我正在使用以下代码

scanf("%lf%*c%lf%*c%lf%*c", &L1g, &L1m, &L1s);
scanf(" %c", &L1c);

scanf("%lf%*c%lf%*c%lf%*c", &L2g, &L2m, &L2s);
scanf(" %c", &L2c);

double lat = (L1g * 3600 + L1m * 60 + L1s) / 3600.0;
double len = (L2g * 3600 + L2m * 60 + L2s) / 3600.0;

cout << setprecision(2) << fixed << lat << " " << len << endl;

它在第一次迭代时运行良好,但在第二次迭代中,它以错误的值执行 cout 2 次。

所以,我在两个 scanf 之后添加了这 2 行代码

cout << L1g << " " << L1m << " " << L1s << " " << L1c << endl;
cout << L2g << " " << L2m << " " << L2s << " " << L2c << endl;

使用以下输入:

23g27m07sS 47g27m06sW
23g31m25sS 47g08m39sW

我有以下输出:

23 27 7 S
47 27 6 W
23.45 47.45 // all fine until here
23.00 27.00 7.00 g // It should be printed 23 31 25 S
31.00 25.00 6.00 S // It should be printed 47 8 39 W
23.45 31.45 // Wrong Answer
23.00 27.00 7.00 g // And it repeats without reading inputs
8.00 39.00 6.00 W
23.45 8.65

我尝试了几种方法来解决这个问题,但都没有奏效。我错过了什么?

【问题讨论】:

  • 总是检查scanf的返回值,对于初学者来说。
  • 如果您使用 C++ 编程,为什么要使用 scanf?如果您想处理输入中的错误,那么我建议您read the whole line,将其放入an input string stream,然后使用普通的“输入”运算符&gt;&gt; 尝试解析该行。如果您坚持使用scanf,那么请创建一个Minimal, Complete, and Verifiable Example 并展示给我们。
  • scanf 比 cin 快,真的靠编程竞赛了
  • 在第一个输入中,scanf 返回 3, 1, 3, 1 是正确的。在第二个输入上,它返回 0, 1, 2, 1,它应该是 3, 1, 3, 1
  • 在我看来,如果你在不知道非常了解如何使用scanf 之类的函数并进行错误检查的情况下尝试进行竞争性编程,那么你就不会去从中学习任何东西。首先了解如何进行良好的编程以及如何制作良好的、有据可查且工作的程序。 那么你可以去看看有竞争力的节目。不要这样做是为了学习如何编程,那么您将学到的只是(糟糕)竞争性编程(糟糕),仅此而已。

标签: c++ scanf


【解决方案1】:

我对这种形式的问题的标准模式是......

while( fgets( buffer, sizeof(buffer), stdin ) != NULL ) { /* for each line */
     if( sscanf( buffer, "%lf%*c%lf%*c%lf%*c", &L1g, &L1m, &L1s) == 3 ) {
        /* handle input which met first criteria.
     } /* else - try other formats */
}

在您的情况下,将两组输入绑定到一组可能更容易......

while( fgets( buffer, sizeof(buffer), stdin ) != NULL ) { /* for each line */
     if( sscanf( buffer, "%lf%*c%lf%*c%lf%*c %lf%*c%lf%*c%lf%*c", &L1g, &L1m, &L1s, &L2g, &L2m, &L2s)) == 6 ) {
        /* handle input which met first criteria.
     } /* else - try other formats */
}

通过分隔线,您可以限制数据和解析状态之间的断开连接。如果 [s]scanf 卡住了,它可能会在输入流中留下意想不到的字符,从而混淆后续的读取尝试。

通过读取整行,将断开连接限制为单行。通过读取一个scanf中的所有行,它要么匹配要么不匹配。

【讨论】:

    猜你喜欢
    • 2021-08-27
    • 1970-01-01
    • 2012-11-19
    • 1970-01-01
    • 2013-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多