关于scanf和cin的问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于scanf和cin的问题相关的知识,希望对你有一定的参考价值。
写了个简单的代码,如下
int main()
int i = -1;
while (scanf("%d", &i) != EOF && i == -1)
printf("%d\n", i);
return 0;
运行时,我输入字符'a',程序死循环了?这是为什么呢?它不会把'a'当成97赋值给i吗?
使用cin>>i,也有这个问题。求答人解答
解决方法:scanf()函数执行成功时的返回值是成功读取的变量数,也就是说,你这个scanf()函数有几个变量,如果scanf()函数全部正常读取,它就返回几。
所以你的函数为了避免输入错误,应该改为
#include <stdio.h>
int main()
int i = -1;
while (scanf("%d", &i) == 1 && i == -1)
printf("%d\n", i);
return 0;
参考技术A 首先我我指出改正的方法吧
while (scanf("%d", &i) != EOF && i == -1)
改成
while (scanf("%d", &i) && i == -1)
关于你的问题
首先scanf函数的原型是int scanf(const char * _Format,...)函数的第一个参数是格式控制符,后面的输入的参数列表,当输入的参数不满足前面的格式控制时候,返回值0;就比如说你程序里面的输入a,就是字符‘a’,但是他要求是一个整数,所以返回0,
然后在头文件<stdio.h>中我们发现这样一条预处理#define EOF (-1)也就是说,eof实际上就是-1,
这个时候当然满足了0!=-1,和i==-1的了哟,但是由于scanf函数错误,所以就无限循环了
至于cin流输入,基本是一个道理,不过他是流的状态出错(这里好像是,有点忘,基本没有用过)
以上是个人理解,欢迎一起交流,同时欢迎你光临我的空间
对于scanf和cin的输入输出速度的验证
本文为https://www.byvoid.com/zhs/blog/fast-readfile的验证性文章
---------------------------------------------------------------------------
首先生成一千万个随机数
1 #include<cstdio> 2 #include<ctime> 3 #include<cstdlib> 4 int main () 5 { 6 freopen("data.txt","w",stdout); 7 srand(time(0)); 8 for(int i=0;i<10000000;i++) 9 printf("%d ",rand()); 10 return 0; 11 }
我用重定向把数据导出到"data.txt"了。
然后,用scanf来读取数据,并计时
1 #include<cstdio> 2 #include<ctime> 3 int a[10000000]; 4 int main () 5 { 6 int start = clock(); 7 freopen("data.txt","r",stdin); 8 for(int i=0;i<10000000;i++) 9 scanf("%d",&a[i]); 10 printf("%.3lf\n",double(clock()-start)/CLOCKS_PER_SEC); 11 }
执行之后,使用时间为1.18s
,相比于原文的2.01
秒,缩短了一截,然后测试一下使用cin
输入的情况,代码如下:
1 #include<cstdio> 2 #include<ctime> 3 #include<iostream> 4 int a[10000000]; 5 int main () 6 { 7 int start = clock(); 8 freopen("data.txt","r",stdin); 9 for(int i=0;i<10000000;i++) 10 std::cin>>a[i]; 11 printf("%.3lf\n",double(clock()-start)/CLOCKS_PER_SEC); 12 }
cin
的使用时间为4.67s
,比scanf
更长,但是相比于原文的6.38s
还是短得多。
然后取消cin
与stdin
之间的同步之后,代码如下:
1 #include<cstdio> 2 #include<ctime> 3 #include<iostream> 4 int a[10000000]; 5 int main () 6 { 7 int start = clock(); 8 std::ios::sync_with_stdio(false); 9 freopen("data.txt","r",stdin); 10 for(int i=0;i<1000000;i++) 11 std::cin>>a[i]; 12 printf("%.3lf\n",double(clock()-start)/CLOCKS_PER_SEC); 13 }
时间大幅缩短,为1.24s
,与scanf很接近了。
然后按原文测试读入整个文件,代码如下:
1 #include<iostream> 2 #include<ctime> 3 #include<cstdio> 4 const int MAXN = 10000000; 5 const int MAXS = 60*1024*1024; 6 int numbers[MAXN]; 7 char buf[MAXS]; 8 9 void analyse(char *buf, int len =MAXS) 10 { 11 int i; 12 numbers[i=0]=0; 13 for(char *p=buf;*p && p-buf<len;p++) 14 if(*p == ‘ ‘) 15 numbers[++i]=0; 16 else 17 numbers[i]=numbers[i]*10+*p-‘0‘; 18 } 19 20 void fread_analyse() 21 { 22 freopen("data.txt","rb",stdin); 23 int len = fread(buf,1,MAXS,stdin); 24 buf[len]=‘\0‘; 25 analyse(buf,len); 26 } 27 28 int main () 29 { 30 int start = clock(); 31 fread_analyse(); 32 printf("%.3lf\n",double(clock()-start)/CLOCKS_PER_SEC); 33 return 0; 34 }
时间如原文一般,大幅缩短,我这里测试得到0.37s
,使用read
测试,代码如下:
#include<iostream> #include<ctime> #include<cstdio> #include<unistd.h> #include<fcntl.h> const int MAXN = 10000000; const int MAXS = 60*1024*1024; int numbers[MAXN]; char buf[MAXS]; void analyse(char *buf, int len =MAXS) { int i; numbers[i=0]=0; for(char *p=buf;*p && p-buf<len;p++) if(*p == ‘ ‘) numbers[++i]=0; else numbers[i]=numbers[i]*10+*p-‘0‘; } void read_analyse() { int fd = open("data.txt",O_RDONLY); int len = read(fd,buf,MAXS); buf[len]=‘\0‘; analyse(buf,len); } int main () { int start = clock(); read_analyse(); printf("%.3lf\n",double(clock()-start)/CLOCKS_PER_SEC); return 0; }
测试时间为0.31s
,有所进步,不过不是非常明显。
调用mmap
,代码如下:
1 #include<iostream> 2 #include<ctime> 3 #include<cstdio> 4 #include<unistd.h> 5 #include<fcntl.h> 6 #include<sys/mman.h> 7 const int MAXN = 10000000; 8 const int MAXS = 60*1024*1024; 9 int numbers[MAXN]; 10 char buf[MAXS]; 11 12 void analyse(char *buf, int len =MAXS) 13 { 14 int i; 15 numbers[i=0]=0; 16 for(char *p=buf;*p && p-buf<len;p++) 17 if(*p == ‘ ‘) 18 numbers[++i]=0; 19 else 20 numbers[i]=numbers[i]*10+*p-‘0‘; 21 } 22 23 void mmap_analyse() 24 { 25 int fd = open("data.txt",O_RDONLY); 26 int len = lseek(fd,0,SEEK_END); 27 char *mbuf = (char *) mmap(NULL,len,PROT_READ,MAP_PRIVATE,fd,0); 28 analyse(mbuf,len); 29 } 30 31 int main () 32 { 33 int start = clock(); 34 mmap_analyse(); 35 printf("%.3lf\n",double(clock()-start)/CLOCKS_PER_SEC); 36 return 0; 37 }
达到0.49s
,与原文不符(原文中使用mmnp
耗时更短,在我的测试中,耗时变长了),可能是代码与原作者的不一样,原作者只给出一部分代码,而测试需要写出完整的代码,可能我写的代码有问题。
以上测试结果在腾讯云上进行,因为原作者当时的硬件条件可能比不上我所使用的环境,我在树莓派 3B和我自己的电脑上测试了一下,所有平台硬件信息如下:
平台/硬件和软件信息 | Cent OS | Raspberry | Windows |
CPU | 1 Core | Broadcom BCM2837 1.2GHz | intel Core 5200u 2.2GHz |
RAM | 1GB | 1GB | 12GB |
Gcc | 4.8.5 | 4.9.2 | 5.3.0 |
PS: 这里忽略了硬盘的性能,理论上来说,硬盘的性能肯定能影响读写速度,只是没有较好的方法比较三个平台的硬盘性能,只能作罢。不过在下面的表中我对比了我自己电脑上在Windows环境下和Linux环境下的情况。相较于原文,舍去VS的比较信息,全部使用了GNU/GCC.
测试结果如下
方法/平台/耗时(s) | Cent OS | Raspberry | Windows(本机) | Ubuntu(本机) |
scanf | 1.180 | 14.786 | 4.488 | 1.158 |
cin | 13.026 | 61.255 | 13.026 | 4.309 |
cin(取消同步) | 1.240 | 7.694 | 8086 | 1.135 |
fread | 0.37 | 3.503 | 0.327 | 0.284 |
read | 0.31 | 2.975 | 0.370 | 0.285 |
mmap | 0.49 | 5.945 | NULL | 0.447 |
在同等硬件条件下,Windows比Linux慢得多,在同等环境下,硬件好的自然快,树莓派充分证明了这一点。
以上是关于关于scanf和cin的问题的主要内容,如果未能解决你的问题,请参考以下文章
关于scanf 与 cin gets(),getline()......输入输出字符串的区别