关于c++中cin的一个小问题。请大家帮我解答一下

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于c++中cin的一个小问题。请大家帮我解答一下相关的知识,希望对你有一定的参考价值。

下面这个小程序中为什么我输入数字的时候程序没有问题,可以用switch捕捉的到。可以输入字母的时候却会死循环。请各位高手都来帮帮忙吧。不胜感激。

#include<iostream.h>
#include<conio.h>
#include<iomanip.h>
#include<stdlib.h>
#define DELAY 9999999

int menu(void);
void delay(void);

void main(void)


while(1)
switch(menu())
case 0:
cout<<"\nExecuting choice 1..."<<endl;
delay();
break;

case 13:
cout<<"\nExecuting choice enter..."<<endl;
delay();
break;

case 65:
cout<<"\nExecuting choice enter..."<<endl;
delay();
break;

default:
cout<<"\nInvalid choice. Try again..."<<endl;
delay();
break;





int menu(void)

int select;
// char buffer_ch;
cout<<setw(40)<<"Enter A for task 1"<<endl;
cout<<setw(40)<<"Enter B for task 2"<<endl;
cout<<setw(40)<<"Enter C for task 3"<<endl;
cin>>select;
//select=getche();
return select;


void delay(void)

long i;
for(i=0;i<=DELAY;i++);

我在调试的时候也是发现select被赋值为0,很奇怪。cin>>应该是字符和数值都能接受的吧?既然是缓冲式输入,并且字符是以Ascii的形式放在缓冲区的,为什么select的值不能是字符的ascii值呢?我也试了将select定义成char就可以了。可是我想数字和字符都可以输入怎么办?为什么上面的程序将cin>>select; 换成select=getche(); 就可以输入字符数字都没有问题?哪位高手可以以这个例子跟我讲明一下这个缓冲式输入和非缓冲式输入的区别,我现在还是初学,迷糊的很。不胜感激。

参考技术A 我看了很久,还是没看出来有问题呀,郁闷. 参考技术B select 定义成 char select 参考技术C 我也不是很清楚,不过,我简单调试发现,当输入字母是,select被赋值为0,在此后的死循环中,它被赋以858993460。
这原因我就不知道了。
你可以对输入之进行一次判断,如果是字母就让重新输入,从而避免这种情况。

在 C++ 程序中使用 scanf() 比使用 cin 更快?

【中文标题】在 C++ 程序中使用 scanf() 比使用 cin 更快?【英文标题】:Using scanf() in C++ programs is faster than using cin? 【发布时间】:2010-11-05 17:46:09 【问题描述】:

我不知道这是否属实,但是当我阅读有关提供问题的网站之一的常见问题解答时,我发现了一些引起我注意的东西:

检查您的输入/输出方法。在 C++ 中,使用 cin 和 cout 太慢了。使用这些,您将保证无法通过大量输入或输出来解决任何问题。请改用 printf 和 scanf。

有人可以澄清一下吗?真的在 C++ 程序中使用 scanf() 比使用 cin >> something 更快吗?如果是,那么在 C++ 程序中使用它是一个好习惯吗?我认为它是特定于 C 的,虽然我只是在学习 C++...

【问题讨论】:

我的猜测:糟糕的程序员将性能不佳归咎于标准库。有点像总是幽默的“我想我在 GCC 中发现了一个错误”的哭声。 @eclipse:我为比赛处理的 ACM 问题有大量的输入/输出,你的程序必须在 60 秒内解决问题......问题在这里。 --- 也就是说,如果您需要依赖 scanf() 来获得额外的性能提升,那么您解决问题的方式是错误的 :) 作为一个观察 - 我玩过它,在第二个问题 (PRIME1) - 使用相同的算法,两次,一次使用 cin/cout,一次使用 scanf/printf 和第一个版本比第二个更快(但足够接近以至于在统计上不相关)。这是被标记为输入/输出密集型的问题之一,输入/输出的方法没有任何统计差异。 @Eclipse - 感谢您提供有关测试这两种方法的信息。不过我很难过 - 我试图责怪 cin 和 cout,但现在我知道我的算法很烂:) 【参考方案1】:

下面是一个简单案例的快速测试:一个从标准输入读取数字列表并对所有数字进行异或运算的程序。

iostream 版本:

#include <iostream>

int main(int argc, char **argv) 

  int parity = 0;
  int x;

  while (std::cin >> x)
    parity ^= x;
  std::cout << parity << std::endl;

  return 0;

scanf 版本:

#include <stdio.h>

int main(int argc, char **argv) 

  int parity = 0;
  int x;

  while (1 == scanf("%d", &x))
    parity ^= x;
  printf("%d\n", parity);

  return 0;

结果

使用第三个程序,我生成了一个包含 33,280,276 个随机数的文本文件。执行时间为:

iostream version:  24.3 seconds
scanf version:      6.4 seconds

更改编译器的优化设置似乎根本没有改变结果。

因此:确实存在速度差异。


编辑: 用户 clyfish points out below 速度差异主要是由于 iostream I/O 函数与 C I/O 函数保持同步。我们可以通过致电std::ios::sync_with_stdio(false); 来关闭它:

#include <iostream>

int main(int argc, char **argv) 

  int parity = 0;
  int x;

  std::ios::sync_with_stdio(false);

  while (std::cin >> x)
    parity ^= x;
  std::cout << parity << std::endl;

  return 0;

新结果:

iostream version:                       21.9 seconds
scanf version:                           6.8 seconds
iostream with sync_with_stdio(false):    5.5 seconds

C++ iostream 获胜! 事实证明,这种内部同步/刷新通常会减慢 iostream i/o。如果我们不混合 stdio 和 iostream,我们可以将其关闭,然后 iostream 是最快的。

代码:https://gist.github.com/3845568

【讨论】:

我认为使用 'endl' 可能会减慢执行速度。 std::endl的使用不在循环中。 开启或关闭同步没有区别。这要怪 libc++。它只会提升 libstdc++ 你认为 之间会有什么区别吗?? iostream 在一个 scanf 调用中解析多个整数时会丢失。【参考方案2】:

http://www.quora.com/Is-cin-cout-slower-than-scanf-printf/answer/Aditya-Vishwakarma

cin/cout 的性能可能很慢,因为它们需要与底层 C 库保持同步。如果要同时使用 C IO 和 C++ IO,这是必不可少的。

但是,如果您只打算使用 C++ IO,那么只需在任何 IO 操作之前使用以下行。

std::ios::sync_with_stdio(false);

有关这方面的更多信息,请查看相应的libstdc++ docs。

【讨论】:

刚刚检查了上面的行 (std::ios::sync_with_stdio(false);) 它确实使 iostream 几乎和 cstdio 一样快 也使用 cin.tie(static_cast(0));为了更好的性能【参考方案3】:

可能 scanf 比使用流要快一些。尽管流提供了很多类型安全性,并且不必在运行时解析格式字符串,但它通常具有不需要过多内存分配的优点(这取决于您的编译器和运行时)。也就是说,除非性能是您唯一的最终目标并且您处于关键路径中,否则您应该真正偏爱更安全(更慢)的方法。

Herb Sutter "The String Formatters of Manor Farm" 在这里写了一篇非常美味的文章,他详细介绍了字符串格式化程序(如 sscanflexical_cast)的性能,以及是什么导致它们运行缓慢或很快。这有点类似,可能类似于会影响 C 风格 IO 和 C++ 风格之间性能的那种事情。与格式化程序的主要区别往往是类型安全和内存分配的数量。

【讨论】:

【参考方案4】:

我刚刚花了一个晚上在 UVa Online 上解决一个问题(Factovisors,一个非常有趣的问题,看看):

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=35&page=show_problem&problem=1080

我的提交获得了 TLE(超出时间限制)。在这些解决问题的在线评委网站上,您有大约 2-3 秒的时间限制来处理可能用于评估您的解决方案的数千个测试用例。对于像这样的计算密集型问题,每一微秒都很重要。

我正在使用建议的算法(在该站点的讨论论坛中阅读),但仍然获得 TLE。

我只将“cin >> n >> m”更改为“scanf("%d %d", &n, &m )",将几个小的“couts”更改为“printfs”,我的 TLE 变成了“Accepted” “!

所以,是的,它可以产生很大的不同,尤其是在时间限制很短的情况下。

【讨论】:

同意。在 UVA Online Judge 问题中我也遇到了同样的情况:Army Buddies uva.onlinejudge.org/…【参考方案5】:

如果您同时关心性能和字符串格式,请查看Matthew Wilson's FastFormat 库。

edit -- 指向该库上 accu 出版物的链接:http://accu.org/index.php/journals/1539

【讨论】:

完全同意。但您需要注意 FastFormat 仅用于输出。它没有输入/读取功能。 (反正还没有) 不幸的是,该链接似乎已失效。这是一个 Wayback 机器副本:web.archive.org/web/20081222164527/http://fastformat.org【参考方案6】:

一般使用的语句cincout 似乎比C++ 中的scanfprintf 慢,但实际上它们更快!

问题是:在 C++ 中,每当您使用 cincout 时,默认情况下都会发生同步过程,以确保如果您在程序中同时使用 scanfcin,那么它们都会彼此同步工作。此同步过程需要时间。因此cincout 看起来要慢一些。

但是,如果将同步过程设置为不发生,则cinscanf 快。

要跳过同步过程,请在您的程序中在main() 的开头添加以下代码sn-p:

std::ios::sync_with_stdio(false);

访问this site了解更多信息。

【讨论】:

+1 用于您对同步的解释。 I had just turned sync off and used both scanf and cin in some code。现在我知道它出了什么问题。谢谢!【参考方案7】:

有 stdio 实现 (libio) 将 FILE* 实现为 C++ 流缓冲区,并将 fprintf 实现为运行时格式解析器。 IOstreams 不需要运行时格式解析,这一切都在编译时完成。因此,通过共享后端,可以合理地预期 iostreams 在运行时更快。

【讨论】:

我不这么认为。我认为 GNU 的 libc 是纯 C 和汇编。 这并没有让它变得更好。【参考方案8】:

是的,iostream 比 cstdio 慢。 是的,如果您使用 C++ 进行开发,您可能不应该使用 cstdio。 话虽如此,如果您不关心格式,类型安全,等等,等等,还有比 scanf 更快的方法来获取 I/O...

例如,这是一个从 STDIN 获取数字的自定义例程:

inline int get_number()

    int c;        
    int n = 0;

    while ((c = getchar_unlocked()) >= '0' && c <= '9')
    
        // n = 10 * n + (c - '0');
        n = (n << 3) + ( n << 1 ) + c - '0';
    
    return n;

【讨论】:

getchar_unlocked() 是非标准的,适用于 gcc 而不是 Visual Studio【参考方案9】:
#include <stdio.h>
#include <unistd.h>

#define likely(x)       __builtin_expect(!!(x), 1)
#define unlikely(x)     __builtin_expect(!!(x), 0)

static int scanuint(unsigned int* x)

  char c;
  *x = 0;

  do
  
      c = getchar_unlocked();
      if (unlikely(c==EOF)) return 1;
   while(c<'0' || c>'9');

  do
  
      //*x = (*x<<3)+(*x<<1) + c - '0';
      *x = 10 * (*x) + c - '0';
      c = getchar_unlocked();
      if (unlikely(c==EOF)) return 1;
   while ((c>='0' && c<='9'));

  return 0;


int main(int argc, char **argv) 

  int parity = 0;
  unsigned int x;

  while (1 != (scanuint(&x))) 
    parity ^= x;
  
  parity ^=x;
  printf("%d\n", parity);

  return 0;

文件末尾有一个错误,但此 C 代码比更快的 C++ 版本快得多。

paradox@scorpion 3845568-78602a3f95902f3f3ac63b6beecaa9719e28a6d6 ▶ make test        
time ./xor-c < rand.txt
360589110

real    0m11,336s
user    0m11,157s
sys 0m0,179s
time ./xor2-c < rand.txt
360589110

real    0m2,104s
user    0m1,959s
sys 0m0,144s
time ./xor-cpp < rand.txt
360589110

real    0m29,948s
user    0m29,809s
sys 0m0,140s
time ./xor-cpp-noflush < rand.txt
360589110

real    0m7,604s
user    0m7,480s
sys 0m0,123s

原始 C++ 耗时 30 秒,C 代码耗时 2 秒。

【讨论】:

【参考方案10】:

问题在于cin 涉及大量开销,因为它在scanf() 调用之上为您提供了一个抽象层。如果您正在编写 C++ 软件,则不应使用 scanf() 而不是 cin,因为这是需要 cin 的。如果你想要性能,你可能无论如何都不会用 C++ 编写 I/O。

【讨论】:

cin 真的比scanf 更“抽象”(在运行时)吗?我不这么认为...scanf 必须在运行时解释格式字符串,而 iostream 在编译时知道格式。 @nibot:type 在编译时是已知的,而不是 format。例如,输入是否应为十六进制完全取决于std::istream运行时 的配置方式(通过I/O 操纵器或通过在istream 对象本身上设置标志) .另一方面,FILE* 对象没有这种状态,因此在这方面对 scanf 的调用更加稳定。【参考方案11】:

当然,在 iostream 上使用 cstdio 是很荒谬的。至少在你开发软件的时候(如果你已经在使用 c++ 而不是 c,那么就一直使用它的好处,而不是只受它的缺点困扰)。

但是在网上判断你不是在开发软件,你是在创建一个程序应该可以做微软软件需要60秒才能在3秒内完成的事情!!!

所以,在这种情况下,黄金法则是这样的(当然,如果你不使用 java 遇到更多麻烦)

使用 c++ 并使用它的所有力量(以及沉重/缓慢)来解决问题 如果时间有限,请更改 printfs 和 scanfs 的 cins 和 couts (如果你使用类字符串搞砸了,打印如下: printf(%s,mystr.c_str()); 如果您仍然受到时间限制,那么请尝试进行一些明显的优化(例如避免嵌入过多的 for/while/dowhile 或递归函数)。还要确保通过太大的引用对象... 如果时间仍然有限,请尝试更改 c 数组的 std::vectors 和集合。 如果你仍然有时间限制,那么继续下一个问题......

【讨论】:

【参考方案12】:

即使scanfcin 快,也没关系。大多数情况下,您将从硬盘驱动器或键盘读取。将原始数据导入您的应用程序所花费的时间比 scanfcin 处理它所花费的时间要多几个数量级。

【讨论】:

IPC通过管道呢?您认为那里的性能可能会受到明显影响吗? 即使使用 IPC 通过管道,进出内核的时间也比仅使用 scanf/cin 解析要多得多。 我在这方面做了测试,当然 cout 和 cin 的性能很差。虽然对于用户输入来说可以忽略不计,但对于性能很重要的事情肯定不是这样。不过,还有其他更快的 c++ 框架。 问题是iostream 比硬盘慢。是的,这太糟糕了。

以上是关于关于c++中cin的一个小问题。请大家帮我解答一下的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 程序中使用 scanf() 比使用 cin 更快?

关于 getline(cin, string) 的 C++ 快速问题

C++ 中的 cin.fail() 和 !cin 有啥区别?

关于输入的一点小技巧

在 C++ 中同时使用 cin 将整数添加到数组 [关闭]

C++ 关于cin输入