ACM输入输出介绍

上传人:M****1 文档编号:584023377 上传时间:2024-08-30 格式:PPT 页数:86 大小:441KB
返回 下载 相关 举报
ACM输入输出介绍_第1页
第1页 / 共86页
ACM输入输出介绍_第2页
第2页 / 共86页
ACM输入输出介绍_第3页
第3页 / 共86页
ACM输入输出介绍_第4页
第4页 / 共86页
ACM输入输出介绍_第5页
第5页 / 共86页
点击查看更多>>
资源描述

《ACM输入输出介绍》由会员分享,可在线阅读,更多相关《ACM输入输出介绍(86页珍藏版)》请在金锄头文库上搜索。

1、ACM输入输出格式输入输出格式2024/8/301ACM题目特点由于ACM竞赛题目的输入数据和输出数据一般有多组(不定),并且格式多种多样,所以,如何处理题目的输入输出是对大家的一项最基本的要求。这也是困扰初学者的一大问题。下面,分类介绍:2024/8/302一个超级简单的题目(ex-1):lProblem DescriptionYourtaskistocalculatea+b.lInputTheinputwillconsistofaseriesofpairsofintegersaandb,separatedbyaspace,onepairofintegersperline.lOutputFo

2、reachpairofinputintegersaandbyoushouldoutputthesumofaandbinoneline,andwithonelineofoutputforeachlineininput.lSample input151020lSample output6302024/8/303初学者很常见的一种写法:l#includelvoidmain()llinta,b;lscanf(“%d%d”,&a,&b);lPrintf(“%d”,a+b);l2024/8/304有什么问题呢?这就是下面需要解决的问题这就是下面需要解决的问题基本输入输出基本输入输出2024/8/305输入

3、第一类:l输入不说明有多少个InputBlock,以EOF为结束标志。参见:ex-1.2024/8/306ex-1源代码:#includeintmain()inta,b; while(scanf(%d%d,&a,&b)!=EOF)printf(%dn,a+b);2024/8/307本类输入解决方案:lC语法:while(scanf(%d%d,&a,&b)!=EOF).lC+语法:while(cinab).2024/8/308说明:1.Scanf函数返回值就是读出的变量个数,如:scanf(“%d%d”,&a,&b);如果a和b都被成功读入整数,那么scanf的返回值就是2;如果只有a被成功读入

4、整数,返回值为1;如果a和b都未被成功读入整数,返回值为0;如果遇到错误或遇到endoffile,返回值为EOF2.EOF是一个预定义的常量,等于-1。2024/8/309输入第二类:l输入一开始就会说有N个InputBlock,下面接着是N个InputBlock。ex-2lProblem DescriptionYourtaskistocalculatea+b.lInputInputcontainsanintegerNinthefirstline,andthenNlinesfollow.Eachlineconsistsofapairofintegersaandb,separatedbyaspa

5、ce,onepairofintegersperline.lOutputForeachpairofinputintegersaandbyoushouldoutputthesumofaandbinoneline,andwithonelineofoutputforeachlineininput.lSample input2151020lSample output6302024/8/3010ex-2源代码:#includeintmain()intn,i,a,b;scanf(%d,&n);for(i=0;in;i+)scanf(%d%d,&a,&b); printf(%dn,a+b);2024/8/30

6、11本类输入解决方案:lC语法:scanf(%d,&n);for(i=0;in;for(i=0;in;i+).2024/8/3012输入第三类:l输入不说明有多少个InputBlock,但以某个特殊输入为结束标志。ex-3lProblem DescriptionYourtaskistocalculatea+b.lInputInputcontainsmultipletestcases.Eachtestcasecontainsapairofintegersaandb,onepairofintegersperline.Atestcasecontaining00terminatestheinputan

7、dthistestcaseisnottobeprocessed.lOutputForeachpairofinputintegersaandbyoushouldoutputthesumofaandbinoneline,andwithonelineofoutputforeachlineininput.lSample input15102000lSample output6302024/8/3013ex-3源代码:#includeintmain()inta,b;while(scanf(%d%d,&a,&b)&(a!=0&b!=0) printf(%dn,a+b);上面的程序有什么问题?上面的程序有什

8、么问题?杜绝低级错误!2024/8/3014本类输入解决方案:如果最后一行是以一个0结尾则:lC语法:while(scanf(%d,&n)&n!=0).lC+语法:while(cinn&n!=0).2024/8/3015输入第四类:l输入是一整行的字符串的参见:POJ_1298lSample InputSTARTNSBFW,JAJSYXTKNRUTWYFSHJFWJYMJWJXZQYTKYWNANFQHFZXJXENDSTARTNBTZQIWFYMJWGJKNWXYNSFQNYYQJNGJWNFSANQQFLJYMFSXJHTSINSWTRJENDSTARTIFSLJWPSTBXKZQQBJQ

9、QYMFYHFJXFWNXRTWJIFSLJWTZXYMFSMJENDENDOFINPUT2024/8/3016本类输入解决方案:lC语法:charbuf20;gets(buf);lC+语法:如果用stringbuf;来保存:getline(cin,buf);如果用charbuf255;来保存:cin.getline(buf,255);2024/8/3017说明:lscanf(“%s%s”,str1,str2),在多个字符串之间用一个或多个空格分隔;l若使用gets函数,应为gets(str1);gets(str2);字符串之间用回车符作分隔。l通常情况下,接受短字符用scanf函数,接受长字

10、符用gets函数。l而getchar函数每次只接受一个字符,经常c=getchar()这样来使用。2024/8/3018说明:cin.getline的用法lgetline是一个函数,它可以接受用户的输入的字符,直到已达指定个数,或者用户输入了特定的字符。它的函数声明形式(函数原型)如下:istream&getline(charline,intsize,charendchar=n);l不用管它的返回类型,来关心它的三个参数:lcharline:就是一个字符数组,用户输入的内容将存入在该数组内。lintsize:最多接受几个字符?用户超过size的输入都将不被接受。lcharendchar:当用户

11、输入endchar指定的字符时,自动结束。默认是回车符。2024/8/3019说明续l结合后两个参数,getline可以方便地实现:用户最多输入指定个数的字符,如果超过,则仅指定个数的前面字符有效,如果没有超过,则用户可以通过回车来结束输入。lcharname4;lcin.getline(name,4,n);l由于endchar默认已经是n,所以后面那行也可以写成:lcin.getline(name,4);2024/8/3020练习:l以下题目属于哪一类输入?以下题目属于哪一类输入?lPOJ_1423lPOJ_1519l更多类型2024/8/3021输出的问题:l一个InputBlock对应一

12、个OutputBlock,OutputBlock之间空行。ex-4lProblem DescriptionYourtaskistocalculatethesumofsomeintegers.lInputInputcontainsanintegerNinthefirstline,andthenNlinesfollow.EachlinestartswithaintegerM,andthenMintegersfollowinthesameline.lOutputForeachgroupofinputintegersyoushouldoutputtheirsuminoneline,andyoumust

13、notethatthereisablanklinebetweenoutputs.lSample input3412345123453123lSample output101562024/8/3022以下方法什么问题?lC语法:.printf(%dnn,ans);lC+语法:.coutansendlendl;2024/8/3023Ex-4正确源代码l#includelintmain()llinticase,n,i,j,a,sum;lscanf(%d,&icase);lfor(i=0;iicase;i+)llsum=0;lscanf(%d,&n);lfor(j=0;jn;j+)llscanf(%d

14、,&a);lsum+=a;llif(iicase-1)lprintf(%dnn,sum);lelselprintf(%dn,sum);ll2024/8/3024解决办法:lC语法:for(k=0;kcount;k+)while()printf(%dn,result);if(k!=count-1)printf(n);lC+语法:类似,输出语句换一下即可。2024/8/3025思考:l思考以下题目的输入格式思考以下题目的输入格式2024/8/3026初学者常见问题初学者常见问题2024/8/3027编译错误lMain函数必须返回int类型(正式比赛)l不要在for语句中定义类型l_int64不支持

15、,可以用longlong代替l使用了汉语的标点符号litoa不是ANSI函数能将整数转换为字符串而且与ANSI标准兼容的方法是使用sprintf()函数intnum=100;charstr25;sprintf(str,%d,num);l另外,拷贝程序容易产生错误2024/8/3028不常规的编程方式lPrintfPrintf和和coutcout混用的问题混用的问题l以下的程序输出什么?l#includel#includelintmain()llintj=0;lfor(j=0;j5;j+)llcoutj=;lprintf(%dn,j);llreturn0;l2024/8/3029什么问题?l一个

16、带缓冲输出(一个带缓冲输出(coutcout)l一个不带缓冲输出一个不带缓冲输出(printf)(printf)lGooleGoole你的问题,充分利用网络资源你的问题,充分利用网络资源2024/8/3030相互学习进步相互学习进步l总结一些非算法方面的错误;l将心得相互交流;l避免初级错误是准备竞赛的第一步;l不要轻视初级错误。2024/8/3031菜鸟之伤菜鸟之伤ACMACM菜鸟的菜鸟的2121个经典错误个经典错误2024/8/3032以HDU1089 AB为例lSampleInputl15l1020lSampleOutputl6l302024/8/3033菜鸟之伤(1)l#include

17、lvoidmain()llinta,b;lscanf(“%d%d”,&a,&b);lprintf(“%dn”,a+b);l2024/8/3034菜鸟之伤(1)l总结:程序不能处理多组数据的问题是最常见的入门问题,只要掌握几种常见的类型,就可以轻松掌握了,具体处理方法曾在第一次课件有详细描述,这里省略了2024/8/3035菜鸟之伤(2)l#includelvoidmain()llinta,b;lwhile(scanf(“%d%d”,&a,&b)!=0)lprintf(“%dn”,a+b);l2024/8/3036菜鸟之伤(2)l总结:文件结束符EOF的值是-1而不是0,所以while(scan

18、f()!=0)常常会因为死循环而造成TLE,这个必须牢记。l说明:不仅仅菜鸟,很多老鸟也常常因为不注意这点而犯错误,而且还常常因为想不到会犯这种低级错误而想不到原因。2024/8/3037菜鸟之伤(3)l#includelvoidmain()llinta,b;lwhile(scanf(“%d%d”,&a,&b)!=EOF);lprintf(“%dn”,a+b);l2024/8/3038菜鸟之伤(3)l总结:while或者for循环的条件外面误加了分号,编译不影响,但是结果循环体没有真正得到多次执行;l说明:菜鸟常犯的错误,往往因为编译能通过而不能迅速察觉,尤其比赛中l提醒:提醒:当你将scan

19、f();语句加上while循环以处理多组数据问题的时候尤其注意因为之前有分号,很容易忘记去掉!2024/8/3039菜鸟之伤(4)l#includelvoidmain()llinta,b;lwhile(scanf(“%d%d”,&a,&b)=2)lprintf(“%dn”,a+b);l2024/8/3040菜鸟之伤(4)l总结:C语言中,赋值符号和判断是否相等的逻辑符号具有完全不同的含义,往往因为我们的习惯问题,在编程中误将判断是否相等的逻辑符号写成赋值符号。同样的,这种失误也会因为不影响编译而影响查错的时间。l说明:菜鸟常犯的错误,但是有过几次教训就会牢记了,呵呵2024/8/3041以HD

20、U1001 Sum Problem为例lSampleInputl1l100lSampleOutputl1l50502024/8/3042菜鸟之伤(5)#includevoidmain()inti,n,s;while(scanf(“%d”,&n)=1)for(i=1;i=n;i+)s+=i;printf(“%dnn”,s);2024/8/3043菜鸟之伤(5)l总结:忘记变量的初始化是典型的菜鸟问题,不必紧张,多经历几次就牢记了l说明:普通变量的初始化还比较容易查找,而用来保存计算结果的数组的初始化更是容易忘记!2024/8/3044菜鸟之伤(6)#includevoidmain()inti,n

21、,s=0;while(scanf(“%d”,&n)=1)for(i=1;i=n;i+)s+=i;printf(“%dnn”,s);2024/8/3045菜鸟之伤(6)l总结:变量初始化放在循环外,是一个典型的ACM初级错误,因为ACM赛题的多组测试特性,如果不能在循环内初始化,将只能确保第一组数据没问题,而很多入门者习惯只测试一组数据,很容易忽略这个问题。ll说明:菜鸟常犯的错误,关键是要理解为什么这样会有问题,真正理解后,修改也就不难了。2024/8/3046菜鸟之伤(7)l#includelvoidmain()linti,n,s;lwhile(scanf(“%d”,&n)=1)lls=n*

22、(n+1)/2;lprintf(“%dnn”,s);ll2024/8/3047菜鸟之伤(7)l总结:数组越界还能在提交后收到RuntimeError的信息反馈,而运算中的数据溢出则往往只能收到WrongAnswer的错误提示,所以这种错误往往容易被误导成算法问题;l说明:不仅菜鸟,就是大牛甚至大神,也常常犯这种错误,只是情况复杂些而已2024/8/3048菜鸟之伤(8)l#includelvoidmain()linti,n,s;lwhile(scanf(“%d”,&n)=1)lls=n/2*(n+1);lprintf(“%dnn”,s);ll2024/8/3049菜鸟之伤(8)l总结:当两个整

23、数进行运算的时候,运算结果一定还是整数,所以不要因为常规数学惯性思维的影响而认为结果可能为浮点数;而不同数据类型一同运算的时候,运算结果的数据类型和相对复杂的类型一致(比如整数+实数,结果类型是实数)2024/8/3050菜鸟之伤(9)l#includelvoidmain()linti,n,s;lwhile(scanf(“%d”,&n)=1)lif(n%2=0)ls=n/2*(n+1);lelsels=(n+1)/2*n;lprintf(“%dnn”,s);l2024/8/3051菜鸟之伤(9)l总结:写for或者while等任何循环语句的时候,不管循环体内有几个语句,务必养成都加上一对大括号

24、的好习惯。l常常碰到的情况是这样的本来循环体内只有一条语句,确实不用大括号,但是在修改程序的过程中,循环体内增加了其他语句,而这时却忘记了添加大括号!l所以说好习惯很重要!2024/8/3052菜鸟之伤(10)l#includelvoidmain()linti,n,s;lwhile(scanf(“%d”,&n)=1)lif(n%2=0)ls=n/2*(n+1);lelsels=(n+1)/2*n;lprintf(“%dnn”,s);l2024/8/3053菜鸟之伤(10)l总结:这也是一个经典错误,虽然为循环体加了大括号,但是并没有包含全部的信息,造成的后果是只有一次输出尽管对于每组数据都处理

25、了,但是只输出最后一组结果。l由于很多同学习惯每次只测试一组数据,就更容易忽略这个错误了.l再次证明再次证明好习惯很重要!好习惯很重要!2024/8/3054菜鸟之伤(11)l假设不会中间溢出,下面的程序是否有问题?l#includelvoidmain()linti,n,s;lwhile(scanf(“%d”,&n)=1)lls=n(n+1)/2;lprintf(“%dnn”,s);ll2024/8/3055菜鸟之伤(11)l总结:这也是受数学习惯影响而可能出现的一个错误,当然,这个错误很好检查,因为编译不能通过的l总结出这个只是因为确实会出现这个情况,而对于极度没有编程经验的同学来说,有时候

26、也会带来困扰2024/8/3056还是以AB为例l题目描述:计算AB的值,输入数据每行包含2个正整数,如果输入数据是两个负数,则结束输入。lSampleInputl15l-1-1lSampleOutputl62024/8/3057菜鸟之伤(12)l#includelvoidmain()llinta,b;lwhile(scanf(“%d%d”,&a,&b)=2)lif(a=-1&b=-1)return;lprintf(“%dn”,a+b);l2024/8/3058菜鸟之伤(12)l总结:正如判断相等要用“=”一样,C语言中进行逻辑与的运算也是需要两个字符“&”,类似的逻辑或运算也是两个字符“|”

27、,如果是单个的字符,含义就完全不同了2024/8/3059菜鸟之伤(13)l上一个程序的改进版:上一个程序的改进版:l#includelvoidmain()llinta,b;lwhile(scanf(“%d%d”,&a,&b)=2)lif(a=-1&b=-1)return;lprintf(“%dn”,a+b);l2024/8/3060菜鸟之伤(13)l总结:题目描述是负数结束输入,SampleInput最后给出的是-1,如果读题不仔细,很容易陷入思维定势,而会不加思索在程序中用-1判断,这样就真的会发生不幸的事件尽管我也认为这个陷阱有点阴,而且未必有很大意义,但是题目并没错,而你确实读题不仔细

28、l说明:算是经典的小陷阱,现在很少出现了2024/8/3061继续以AB为例l题目描述:给定2个整数A和B,如果A+B0,请输出”OK!”,否则请输出”No”lSampleInputl15l1-5lSampleOutputlOK!lNo2024/8/3062菜鸟之伤(14)l#includelvoidmain()llinta,b;lwhile(scanf(“%d%d”,&a,&b)=2)lif(a+b0)printf(“OK!n”);lelseprintf(“NOn”);l2024/8/3063菜鸟之伤(14)l总结:字符串输出的大小写问题对于菜鸟需要特别注意,其实,不管是全大写、全小写,还是

29、首字母大写,你尽管复制即可(没有电子版,另当别论),当然还要注意是否有标点符号等情况。l说明:菜鸟常犯错误,稍有经验即可避免2024/8/3064以1170BalloonComes!为例lSampleInputl4l+12l-12l*12l/12lSampleOutputl3l-1l2l0.502024/8/3065菜鸟之伤(15)lintn,a,b,i;lcharp;lscanf(%d,&n);lfor(i=0;in;i+)llscanf(%c%d%d,&p,&a,&b);lif()l2024/8/3066菜鸟之伤(15)l刚才程序的改进版:lintn,a,b,i;lcharp;lscanf

30、(%d,&n);lgetchar();lfor(i=0;in;i+)llscanf(%c%d%d,&p,&a,&b);lif(.)ll是否还有问题?如何修改?2024/8/3067菜鸟之伤(15)l总结:字符和数字的混合输入带来的问题,也是一个常常困扰使用C语言编程的同学的经典问题,关键就是程序未能及时接收回车符,而误将回车当作下一组数据的首字母,你可以通过添加一句getchar();轻松解决该问题。l说明:菜鸟的经典错误,如果之前没有遇到过,很难一下子反应过来,当然,遇到一次以后就不成为问题了2024/8/30682007 平方和与立方和l给定一段连续的整数,求出他们中所有偶数的平方和以及所

31、有奇数的立方和。lSampleInputl13l25lSampleOutputl428l201522024/8/3069菜鸟之伤(16)#includevoidmain()intm,n;while(scanf(“%d%d”,&m,&n)=2)inti,x=0,y=0;for(i=m;i=n;i+)if(i%2=0)y=y+i*i;elsex=x+i*i*i;printf(“%d%dn”,y,x);2024/8/3070菜鸟之伤(16)l总结:题目并没有保证数据是递增的,但人往往有思维定势,而很多题目的设计就是针对这一点!不要埋怨,这种训练能很好的培养我们审慎的思维习惯。l说明:这种错误经历过以

32、后还是比较容易牢记的,所以说有时候经验很重要。2024/8/3071菜鸟之伤(17)l以下的程序输出什么?l#includel#includelintmain()llintj=0;lfor(j=0;j5;j+)llcoutj=;lprintf(%dn,j);llreturn0;l2024/8/3072菜鸟之伤(17)l期望输出:lj=0lj=1lj=2lj=3lj=4l实际输出:l?2024/8/3073菜鸟之伤(17)l总结:在一个程序中同时使用C和C+的输出语句,很容易带来问题,原因就是输出机制不完全一样(一个不带缓冲,一个带缓冲),所以尽量避免C和C+输出语句混用。l说明:这是传说中的经

33、典错误,据说曾困扰某牛人于现场赛:-)2024/8/3074以2004 成绩转换 为例l题目描述:题目描述:输入一个百分制的成绩t,将其转换成对应的等级,具体转换规则如下:90100为A;8089为B;7079为C;6069为D;059为E;l输出描述:输出描述:对于每组输入数据,输出一行。如果输入数据不在0100范围内,请输出一行:“Scoreiserror!”。2024/8/3075菜鸟之伤(18)l#includelint main()l int t,a;l while(scanf(%d,&t)!=EOF)l if(t100|t0) printf(Score is error!n);l

34、elsel a=(t-50)/10;l switch(a)l case 5:l case 4:printf(An); case 3:printf(Bn);l case 2:printf(Cn); case 1:printf(Dn);l default:printf(En); l l return 0;l 2024/8/3076菜鸟之伤(18)l总结:C语言中的case语句要求在每个case的处理后面都要跟break;(特殊需求除外),而如果因为不了解或者不小心而缺少部分break;则执行的效果也许会不符合你最初的设计。l说明:C语言的基本功很重要2024/8/3077以2046 骨牌铺方格 为

35、例l题目描述:题目描述:在2n的一个长方形方格中,用一个12的骨牌铺满方格,输入n,输出铺放方案的总数.l输入描述:输入描述:输入数据由多行组成,每行包含一个整数n,表示该测试实例的长方形方格的规格是2n(0n=50)。2024/8/3078菜鸟之伤(19)l#includelintmain()llinti;l_int64a50=0,1,2;lfor(i=3;i=50;i+)lai=ai-1+ai-2;lwhile(scanf(%d,&i)!=EOF)lprintf(%I64dn,ai);ll2024/8/3079菜鸟之伤(19)l总结:数组下标越界是最常见的RuntimeError,也是菜鸟

36、常犯的错误,除了需要扎实的C语言基本功,编程中的注意力集中也是需要的(很多时候不是不知道理论,而是不注意)l说明:一般情况,你可以通过将数组开的大点而尽量避免这个问题2024/8/3080以1425 Sort为例l题目描述:题目描述:给你n个整数,请按从大到小的顺序输出其中前m大的数。l输入描述:输入描述:每组测试数据有两行,第一行有两个数n,m(0n,m1000000),第二行包含n个各不相同,且都处于区间-500000,500000的整数。2024/8/3081菜鸟之伤(20)l#includelvoidmain()llintn,m,i,num1000000;lwhile(scanf(“%

37、d%d”,&n,&m)=2)l.l2024/8/3082菜鸟之伤(20)l总结:ACM编程中,使用很大的数组是很常见的做法,但如果超大的数组被定义成局部变量,则很容易出现RuntimeError,解决办法也很简单:定义成全局变量即可。原因是局部变量分配在栈(较小),全局变量分配在堆(较大);l说明:这里所说的超大也不能无限制的大,可以根据题目的内存限制进行估算2024/8/3083以3199 Hamming Problem3199 Hamming Problem为例l题目描述:题目描述:Foreachthreeprimenumbersp1,p2andp3,letsdefineHammingse

38、quenceHi(p1,p2,p3),i=1,.ascontaininginincreasingorderallthenaturalnumberswhoseonlyprimedivisorsarep1,p2orp3.lForexample,H(2,3,5)=2,3,4,5,6,8,9,10,12,15,16,18,20,24,25,27,.lSoH5(2,3,5)=6.l输出描述:输出描述:Theoutputcontainthesingleinteger-Hi(p1,p2,p3).Allnumbersininputandoutputarelessthan1018.2024/8/3084菜鸟之伤(21)l典型错误l没有仔细分析.l也不敢尝试.l直接被吓走了.2024/8/3085菜鸟之伤(21)l总结:这个题目从本质上来说,和1058HumbleNumbers是一样的,唯一吓人的就是数据范围的描述,可能会有人想:i这么大,没法开数组呀?l但是,你仔细分析一下会发现:因为输出也是小于1018,而同时,即使一组内的三个素数是最小的2,3,5,增长的速度也是很快的,所以不必为数组太大而着急。l当然,也不必因为发现i很小而觉得数据太水,那是因为只能如此,不然输出就要超范围了2024/8/3086

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 建筑/环境 > 施工组织

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号