首页 > 代码库 > 编程挑战系统的输入和输出详细说明
编程挑战系统的输入和输出详细说明
在高校俱乐部线上编程挑战中,一道题目的所有测试数据是放在一个文本文件中,选手将一道题目的程序提交给评判系统运行,程序从该文件中读取测试数据,再把运行结果输出到另一个文本文件中。系统把输出文件与标准答案比对,来评判程序编写得正确与否。
本系统采用标准的输入输出,输入结束有文件末尾标识(EOF),这可以用于确定输入结束。
一、四种基本输入形式
1. 一组输入数据
示例:整数求和
描述
给定两个整数,求它们之和。
输入
两个整数A,B.
输出
两个整数的和。
样例输入
1 2
样例输出
3
在此列出用C/C++语言的答题示例如下:
C语法:
#include <stdio.h> int main() { int a,b; scanf("%d %d",&a, &b); printf("%d\n",a+b); }
注意:输入前不要打印提示信息。输出完毕后立即终止程序,不要等待用户按键。
C++语法:
#include<iostream> using namespace std; int main() { int a ,b; cin>>a>>b; cout<<a+b<<endl; return 0; }
Java语法:
import java.util.*; public class Main { public static void main(String [] args) { Scanner cin = new Scanner(System.in); int a = cin.nextInt(); int b = cin.nextInt(); System.out.println(a+b); cin.close(); } }
C#语法:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { string[] ss = Console.ReadLine().Split(); Console.WriteLine(int.Parse(ss[0]) + int.Parse(ss[1])); } } }
2. 多组输入数据,不说明多少组,直到读至输入文件末尾为止
示例:整数求和
描述
给定两个整数,求它们之和。
输入
输入由一系列包含两个整数的数组构成,由两个数字由空格分开,一行一组数据
输出
针对每组输入数据,输出之和
样例输入
2 7
样例输出
9
在此列出用C/C++语言的答题示例如下:
C语法:
#include <stdio.h> int main() { int a,b; while (scanf("%d %d",&a, &b) != EOF) printf("%d\n",a+b); }
说明:scanf函数返回值就是读出的变量个数,如:scanf( “%d %d”, &a, &b );如果只有一个整数输入,返回值是1,如果有两个整数输入,返回值是2,如果一个都没有,则返回值是EOF。EOF是一个预定义的常量,等于-1
C++语法:
#include<iostream> using namespace std; int main() { int a ,b; while (cin>>a>>b) cout<<a+b<<endl; return 0; }
cin是一个对象,表达式cin >> m >> n在读入发生错误返回0,否则返回cin的地址。
Java语法:
import java.util.*; public class Main { public static void main(String [] args) { Scanner cin = new Scanner(System.in); int a ,b; while(cin.hasNext()) { a= cin.nextInt(); b=cin.nextInt(); System.out.println(a+b); } cin.close(); } }
C#语法:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { string line; while ((line = Console.ReadLine()) != null) { string[] ss = line.Split(); Console.WriteLine(int.Parse(ss[0]) + int.Parse(ss[1])); } } } }
3. 多组输入数据,不说明多少组,以某特殊输入为结束标志
示例:整数求和
描述
给定两个整数,求它们之和。
输入
输入由一系列包含两个整数的数组构成,由空格分开,一行一组数据。最后一行为0 0,且不做运算处理;
输出
针对每组输入数据,输出之和
样例输入
2 7
1 6
0 0
样例输出
9
在此列出用C/C++语言的答题示例如下:
C语法:
#include <stdio.h> int main() { int a,b; while(scanf("%d %d",&a, &b) &&(a||b)) printf("%d\n",a+b); }
C++语法:
#include<iostream> using namespace std; int main() { int a ,b; while(cin>>a>>b&&(a||b)) {cout<<a+b<<endl;} return 0; }
Java语法:
import java.util.*; public class Main { public static void main(String [] args) { Scanner cin = new Scanner(System.in); int a ,b; while(cin.hasNext()) { a= cin.nextInt(); b=cin.nextInt(); if(a==0&&b==0)break; System.out.println(a+b); } cin.close(); } }
C#语法:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { string line; int a, b; while ((line = Console.ReadLine()) != null) { string[] ss = line.Split(); a=int.Parse(ss[0]); b=int.Parse(ss[1]); if (a == 0 && b == 0) break; Console.WriteLine(a+b); } } } }
4. 多组输入数据,开始输入一个N,接下来是N组数据
示例:整数求和
描述
给定两个整数,求它们之和。
输入
输入数据每行由N开头,
输入由一系列包含两个整数的数组构成,由空格分开,一行一组数据。第一行为N,表明后续数组的个数;
输出
针对每组输入数据,输出之和
样例输入
2
1 6
5 3
样例输出
7
8
在此列出用C/C++语言的答题示例如下:
C语法:
#include<stdio.h> int main() { int a ,b,n; scanf("%d",&n); while(n--) { scanf("%d %d",&a, &b); printf("%d\n",a+b); } return 0; }
C++语法:
#include<iostream> using namespace std; int main() { int a ,b,n; cin>>n while(n--) { cin>>a>>b; cout<<a+b<<endl; } return 0; }
Java语法:
import java.util.*; public class Main { public static void main(String [] args) { Scanner cin = new Scanner(System.in); int a ,b,n=cin.nextInt();; while((n--)>0) { a= cin.nextInt(); b=cin.nextInt(); System.out.println(a+b); } cin.close(); } }
C#语法:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { int n = int.Parse(Console.ReadLine()); while ((n--)>0) { string[] ss = Console.ReadLine().Split(); Console.WriteLine(int.Parse(ss[0]) + int.Parse(ss[1])); } } } }
二、字符串输入
对字符串的输入分三种情况:
1. 每个字符串中不含空格、制表符及回车
这种情况,用scanf("%s",str)是再好不过的了,比如,测试数据中只有两个字符串:abc def
要读入abc与def,可以这样写:
char str1[1000], str2[1000];
scanf("%s%s", str1, str2);
2. 字符串中含有空格、制表符,但不含回车
对于这种情况,scanf("%s",str)无能为力,因为scanf用空格、制表符及回车作为字符串的分界符。对于一个含有空格、制表符及回车的字符串,如果用scanf("%s",str)来读,将读到若干个字符串,这个字符串被scanf分开了。
可以用另外一个函数gets。gets函数用回车作为字符串的分界符,比如,有以下的一个字符串:
Hello world!
要读入这个字符串,这样写:
char str[1000];
gets(str);
这样,str的内容就是"Hello world!"了。另外,gets返回NULL表示出错或end of file。
3. 字符串中含回车
在这种情况下,如果没有题目的说明,程序无法知道哪里是字符串的分界。那么,用scanf("%c",&ch)来读,一边读,一边判断分界条件是否满足,如果满足,则把当前读到的东西存到一个字符串中。
三、输出处理
在初次接触ACM程序设计竞赛时,可能认为:样例中都是输入数据和输入数据在一起,输出结果和输出结果在一起,可能会开个数组,把每组的结果存起来,等输入完了再一起输出。当遇到不知有多少组测试数据的题,就难以处理了。
在高校俱乐部线上编程挑战中,输入数据和输出数据是分别在两个不同的文件中进行的,程序的输入和输出是相互独立的,所以读入一组数据就输出一组结果,跟先读入所有数据再输出所有的结果,效果是完全一样的。因此,每当处理完一组测试数据,就应当按题目要求进行相应的输出操作。而不必将所有结果储存起来一起输出。在处理输出时,一般要注意:每行输出均以回车符结束,包括最后一行。
1. 关于空行(Blank line)
很多题目都要求在输出数据的恰当位置加空行。一个空行就是一个单独的"\n"。这里,有的题目说:“After each test case, you should output one blank line”,而有的题目说:“Between each test case, you should ouput one blank line”。要注意After和Between的区别,因为如果多了一或少了空行,将导致Presentation Error甚至Wrong Answer。
(1) After
这种情况最简单,只需要输出结果后,再加一个printf("\n")或puts("")就行了,就像这样:
int i; for (i = 0; i < 10; i++) { printf("%d\n", a); printf("\n"); }
在此列出用C/C++语言的答题示例如下:
示例:整数求和
描述
给定几个整数,求它们之和。
输入
输入包含多个测试用例。每个测试用例包含N+1个整数,第一位为整数N,后面跟随N个整数;
最后一行第一位数字为0,此行不做运算处理。
输出
对每一行输入数据求和;最后一行输出空行
样例输入
4 1 2 3 4
5 1 2 3 4 5
0
样例输出
10
15
程序示例:
C语法:
#include<stdio.h> int main() { int n,sum,a; while(scanf("%d",&n) && n) { sum=0; while(n--) { scanf("%d",&a); sum+=a; } printf("%d\n",sum); printf("\n"); } return 0; }
C++语法:
#include<iostream> using namespace std; int main() { int n,sum,a; while(cin>>n&&n) { sum=0; while(n--) { cin>>a; sum+=a; } cout<<sum<<endl; cout<<endl; } return 0; }
Java语法:
import java.util.*; public class Main { public static void main(String [] args) { Scanner cin = new Scanner(System.in); int x,n,sum; while(cin.hasNext()) { n= cin.nextInt(); if(n<=0)break; sum=0; while((n--)>0) { x=cin.nextInt(); sum+=x; } System.out.println(sum); } cin.close(); } }
C#语法:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { string line; int n,sum; while ((line = Console.ReadLine()) != null) { n = int.Parse(line); if (n <= 0) break; sum = 0; string[] ss = Console.ReadLine().Split(); for (int i = 0; i < n; ++i) { sum += int.Parse(ss[i]); } Console.WriteLine(sum); } } } }
(2) Between
Between和After不同的是,最后一组结果后面不应该再加单独的"\n",应该像这样:
int i; for (i = 0; i < 10; i++) { printf("%d\n", a); if (i != 9) printf("\n"); }
由于有时候我们并不知道测试数据有几组(比如测试数据是以end of file 结束的),用上面的方法就不行了,于是,可以换一种写法:
int a; bool bFirst = true; while (scanf("%d", &a) == 1) { if (!bFirst) puts(""); else bFirst = false; printf("%d\n", a); }
这样,从第二组测试数据起,在输出每组测试数据的结果之前就会输出一个空行,和想要的效果是一样的。
2. 关于空格、逗号以及其他分隔符
这种情况与空行的情况相当相似,处理方法也是一样的,只不过把"\n"改成相应的分隔符就行了。
3. 带格式的字符串输出
有些题目要求输出这样的字符串
abc*****de****f
其中“*”代表空格。
要求是这样的:str1在前5个字符中左对齐,str2在第6到第10个字符中右对齐,str3在第11到第15个字符中右对齐。
可行的做法是,先初始化一个数组,用‘ ‘(空格)填充,再在相应的位置填相应的内容。用程序来表述:
01:char str[1000];
02:char str1[] = "abc", str2[] = "de", str3[] = "f";
03:memset(str, ‘ ‘, 1000 * sizeof(char));
04:sprintf(str, "%s", str1);
05:str[strlen(str1)] = ‘ ‘;
06:sprintf(str + 5, "%5s", str2);
07:str[10] = ‘ ‘;
08:sprintf(str + 10, "%5s", str3);
09:str[15] = ‘\0‘;
10:puts(str);
关键的部分:
(1)在调用sprintf后,要清除不恰当字符串结束符(第5,7行);
(2)在恰当的位置添加字符串结束符(第9行)。
4. 二维数组的输出
首先要考虑的是数组是按行排列还是按列排列,如果是按行排列,就应该这样写:
int i, j;
01: for (i = 0; i < nRow; i++)
02: {
03: for (j = 0; j < nCol; j++)
{
if (j > 0)
printf(" ");
printf("%d", a[j]);
}
puts("");
}
如果是按列,就要把1行和3行交换。
来源:http://student.csdn.net/mcd/topic/235300/758992