OJ在线编程之ACM模式中输入输出的处理(C++版)
1. 最简单的输入
1 Description 2 计算 a+b 3 4 Input 5 两个整数 a,b 6 7 Output 8 a+b的值 9 10 Sample Input 11 1 2 12 13 Sample Output 14 3
解决办法是:
1 #include <iostream> 2 using namespace std; 3 int main() 4 { 5 int a,b; 6 cin >> a >> b; 7 cout << a+b << endl; //对其他题目,换成要求的复杂处理与输出 8 return 0; 9 }
2. 一次运行,要输入多组数据,直到读至输入文件末尾(EOF)为止
1 Description 2 计算 a + b 3 4 Input 5 多组由两个整数(a和b)构成的输入,a和b之间用空格隔开,每组输入单独占一行 6 7 Output 8 每组的两个整数(a和b)求和并输出,每组的求和结果独占一行 9 10 Sample Input 11 1 5 12 10 20 13 400 516 14 15 Sample Output 16 6 17 30 18 916
这种输入包含多对输入数据,需要构造一个循环读取。因为没有指出到底有多少对输入,要有办法判断输入何时结束。解决办法是:
1 #include <iostream> 2 using namespace std; 3 int main() 4 { 5 int a,b; 6 while(cin >> a >> b) //当读到输入结束时,cin >> a >> b返回 0,循环也结束 7 { 8 cout << a+b << endl; 9 } 10 return 0; 11 } //在调试程序时,键盘输入的数据,用CTRL-Z(即按住CTRL键不放,再按下Z)组合作为输入结束,此谓键盘输入设备的“文件末尾”
3. 一次运行,要输入多组数据,组数由第一个输入数据决定(在开始的时候输入一个N,接下来是N组数据)
1 Description 2 计算 a + b 3 4 Input 5 第一行是数据的组数N,从第二行是N组由两个整数(a和b)构成的输入,a和b之间用空格隔开,每组输入单独占一行 6 7 Output 8 每组的两个整数(a和b)求和并输出,每组的求和结果独占一行 9 10 Sample Input 11 2 12 1 5 13 10 20 14 15 Sample Output 16 6 17 30
需要先读入第一行确定组数N,而后写一次执行N次的循环进行处理即可。解决办法是:
1 #include <iostream> 2 using namespace std; 3 int main() { 4 int a, b, n; 5 cin >> n; 6 for(i=0;i<n;i++) 7 { 8 cin >> a >> b; 9 cout << a + b << endl; 10 } 11 return 0; 12 }
4. 输入不说明有多少组数据,但以某个特殊输入为结束标志。平时做题中常见诸如“输入学生成绩,以-1结束”,没有学生得-1分的,这个结束数据可以要得。
1 Description 2 计算 a + b 3 4 Input 5 多组由两个整数(a和b)构成的输入,a和b之间用空格隔开,每组输入单独占一行。当输入为 0 0 时,输入结束。 6 7 Output 8 每组的两个整数(a和b)求和并输出,每组的求和结果独占一行。 9 10 Sample Input 11 1 5 12 10 20 13 0 0 14 15 Sample Output 16 6 17 30
1 构造循环对数据进行处理,将是否遇到了要求结束的输入,作为循环是否结束的依据。解决办法是: 2 #include<iostream> 3 using namespace std; 4 int main() 5 { 6 int a ,b; 7 while(cin>>a>>b&&(a||b)) 8 { 9 cout<<a+b<<endl; 10 } 11 return 0; 12 }
如果是有多组输入 ,不知道组数 和 组中元素个数
如
1 输入 2 1 2 3 3 4 5 4 0 0 0 0 0 5 输出 6 6 7 9 8 0
方法:
1 #include <iostream> 2 3 using namespace std; 4 5 int main() { 6 int ele; 7 while(cin >> ele) { 8 int sum = ele; 9 // 下面改成getchar() != '\n' 也行 10 while(cin.get() != '\n') { 11 cin >> ele; 12 sum += ele; 13 } 14 15 cout << sum << endl; 16 } 17 return 0; 18 }
5. 利用文件重定向提高调试效率
编程得到正确结果前,往往需要多次运行程序,每次运行都需要花费不少的时间从键盘输入数据。每次输入的数据都是相同的时,会给人的心理带来不爽的感觉,并造成时间上的浪费。无论平时练习还是ACM竞赛实战,这些都是可以避免的。方法是,运用重定向。
用下面的形式调用函数freopen()会将标准输入stdin重定向到文件input.txt(这个名字可以自己定义)。
1 freopen("input.txt","r",stdin); //设置输入和输出文件
2 重定向后,原先从键盘(标准输入的默认设备)接受的输入,将统统从文件读取input.txt读取,这就是重定向。程序可以写作:
3 #include<iostream> 4 #include<cstdio> 5 using namespace std; 6 int main() 7 { 8 freopen("input.txt","r",stdin); //只加这一句输入将被重定向到文件input.txt 9 int a,b; 10 cin>>a>>b; 11 cout<<a+b<<endl; 12 return 0; 13 }
于是,在运行程序前,将本该由键盘输入的数据,写到文件input.txt中。而在运行程序时,数据将不再需要人去输入。那个快,很享受。
需要注意的是,调试通过的程序,千万不要直接提交到OJ平台上去。如果竞赛中这样做了,罚你的20分钟不要算到我的头上。提交的程序要把输入重定向的一行删除,这样才算是符合要求的,可以获得AC的程序。
6.给定字符(串),进行相关地处理
1 //给定字符 2 char ch; 3 cin>>ch;//方式一 4 while(cin.get(ch))//方式二
5 //给定字符串 6 string input; 7 getline(cin,input);//方式一 8 cin>>input;//方式二 9 while(方式一/方式二) //方式三
10 //还是推荐用方式三的输入方式,不容易出错,字符串的一些题目用方式一和方式二可能会出错(由于输入格式的问题
2)给定不止一组字符串,告知大小
1 //举个例子,先输入一个数表示有多少个字符串,再输入每个字符串,根据字符串长度排序 2 int N;//定义数量 3 string temp;//字符串变量 4 while(cin>>N){ //输入数量 5 vector<string> input; //存储所有的字符串 6 for(int i=0;i<N;i++){ 7 cin>>temp; //输入字符串 8 input.push_back(temp);//保存 9 } 10 } 11 //下面是另一种不安全的写法 12 int N;//定义数量 13 cin>>N;//输入数量 14 string temp;//字符串变量 15 vector<string> input; //存储所有的字符串 16 for(int i=0;i<N;i++){ 17 cin>>temp; //输入字符串 18 input.push_back(temp);//保存 19 } 20 //以该例题为例,可能在本地IDE能得到正确答案,但如果是牛客网系统,由于输入格式的问题,这样写编译会通过,就是得不到正确答案
3)输入一组字符串,不告知大小,仍然以上个例子举例,不告诉你有多少字符串,这样就不能根据数量来用for循环做了,但可以用while循环处理
1 string temp;//字符串变量 2 vector<string> input; //存储所有的字符串 3 while(cin>>temp){ //输入数量 4 input.push_back(temp);//保存 5 //... 6 }
4)没有一行的个数,字符串带空格,一个用例 一行
1 输入 2 a c bb 3 f dddd 4 nowcoder 5 输出 6 a bb c 7 dddd f 8 nowcoder 9 10 11 #include<stdio.h> 12 #include<string.h> 13 #include<iostream> 14 #include<vector> 15 #include<algorithm> 16 using namespace std; 17 int main() 18 { 19 vector<string> s; 20 string ns; 21 while(cin>>ns){ 22 s.push_back(ns); 23 if(cin.get()=='\n'){ //依靠cin.get()
判断'\n'
24 sort(s.begin(),s.end()); 25 for(int i=0;i<s.size();i++){ 26 if(i==s.size()-1) 27 cout<<s[i]<<endl; 28 else 29 cout<<s[i]<<" "; 30 } 31 s.clear(); 32 } 33 } 34 }
5)多个测试用例,每个测试用例一行。每行通过逗号‘,’隔开,有n个字符,n<100。依靠sstream和getline() getline 的在输入值等于第三个参数时 停止输入。
cin在遇到回车 空格时停止输入。
1 输入 2 a,c,bb 3 f,dddd 4 nowcoder 5 输出 6 a bb c 7 dddd f 8 nowcoder
1 #include<bits/stdc++.h> 2 using namespace std; 3 int main() { 4 string ns; 5 while(getline(cin, ns)) { 6 vector<string> s; 7 stringstream ss(ns); 8 //getline()可以实现对流的自定义读取,使用stringstream将一个字符串变成了流,这样能被getline使用。 9 10 while(getline(ss,ns,',')) //这个程序也适用于其他符号隔开的输入,如“;”、“-”等,只要是一个字符长度的就可以 11 s.push_back(ns); 12 13 sort(s.begin(),s.end()); 14 for(int i=0; i<s.size(); i++) { 15 if(i==s.size()-1) 16 cout<<s[i]<<endl; 17 else 18 cout<<s[i]<<' '; 19 } 20 s.clear(); 21 } 22 }
1 在<string>中的getline函数有四种重载形式: 2 3 4 istream& getline (istream& is, string& str, char delim); 5 istream& getline (istream&& is, string& str, char delim); 6 istream& getline (istream& is, string& str); 7 istream& getline (istream&& is, string& str); 8 用法和上第一种类似,但是读取的istream是作为参数is传进函数的。读取的字符串保存在string类型的str中。 9 10 is:表示一个输入流,例如cin。 11 12 str:string类型的引用,用来存储输入流中的流信息。 13 14 delim:char类型的变量,所设置的截断字符;在不自定义设置的情况下,遇到'\n',则终止输入。 15 16 17 #include<iostream> 18 #include<string> 19 using namespace std; 20 int main(){ 21 string str; 22 getline(cin, str, 'A'); 23 cout<<"The string we have gotten is :"<<str<<'.'<<endl; 24 getline(cin, str, 'B'); 25 cout<<"The string we have gotten is :"<<str<<'.'<<endl; 26 return 0; 27 } 28 29 输入 30 i_am_A_student_from_Beijing 31 32 输出 33 The string we have gotten is :i_am_. 34 The string we have gotten is :_student_from_.
万能头文件 #include<bits/stdc++.h>
包含了目前c++所包含的所有头文件