OJ 输入与输出

<strong>一、五种基本的输入
1、简单输入</strong>

计算 a+b    
    
Input    
两个整数 a,b    
    
Output    
a+b的值    
    
    
Sample Input    
1 2    
    
Sample Output    
3

 
<span style="font-family: Arial, Helvetica, sans-serif; white-space: normal; background-color: rgb(255, 255, 255); ">C</span>

#include <stdio.h>    
int main()    
{    
    int a,b;    
    scanf("%d %d",&a, &b);    
    printf("%d\n",a+b);  //对其他题目,换成要求的复杂处理与输出    
    return 0;    
}    

scanf函数返回值就是读取的变量个数,如:scanf( “%d  %d”, &a,&b );
如果只有一个整数输入,返回值是1,如果有两个整数输入,返回值是2,如如果一个都没有,则返回值是-1。EOF是一个预定义的常量,等于-1

C++

#include <iostream>    
using namespace std;    
int  main()    
{    
    int a,b;    
    cin >> a >> b;    
    cout << a+b << endl;   //对其他题目,换成要求的复杂处理与输出    
    return 0;    
}   

2. 一次运行,要输入多组数据,直到读至输入文件末尾(EOF)为止


Description    
计算 a + b    
    
Input    
多组由两个整数(a和b)构成的输入,a和b之间用空格隔开,每组输入单独占一行     
    
Output    
每组的两个整数(a和b)求和并输出,每组的求和结果独占一行    
    
Sample Input    
1 5    
10 20    
400 516    
    
Sample Output    
6    
30    
916   

C:

#include <stdio.h>    
int main()     
{    
    int a,b;    
    while(scanf("%d %d",&a, &b) != EOF) // 输入结束时,scanf函数返回值为EOF(-1),即没有数据输入时会退出while循环    
    {    
        printf("%d\n",a+b);    
    }    
    return 0;     
}    
  说明:scanf函数返回值就是读出的变量个数,如果一个都没有,则返回值是-1。EOF是一个预定义的常量,等于-1。 

C++:

#include <iostream>     
using namespace std;    
int main()    
{    
    int a,b;    
    while(cin >> a >> b)    
    {    
        cout << a+b << endl;    
    }    
    return 0;    
}     

  说明:当读到输入结束时,cin >> a >> b返回 0,循环也结束


3. 一次运行,要输入多组数据,组数由第一个输入数据决定(在开始的时候输入一个N,接下来是N组数据)


Description    
计算 a + b    
    
Input    
第一行是数据的组数N,从第二行是N组由两个整数(a和b)构成的输入,a和b之间用空格隔开,每组输入单独占一行     
    
Output    
每组的两个整数(a和b)求和并输出,每组的求和结果独占一行    
    
Sample Input    
2    
1 5    
10 20    
    
Sample Output    
6    
30   

C:

#include<stdio.h>    
int main()    
{    
    int n,i;    
    int a,b;    
    scanf("%d",&n);    
    for(i=0;i<n;i++)    
    {    
        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;    
    for(i=0;i<n;i++)    
    {    
        cin >> a >> b;    
        cout << a + b << endl;    
    }    
    return 0;    
}   
4.  输入不说明有多少组数据,但以某个特殊输入为结束标志。平时做题中常见诸如“输入学生成绩,以-1结束”,没有学生得-1分的,这个结束数据可以要得。
Description    
计算 a + b    
    
Input    
多组由两个整数(a和b)构成的输入,a和b之间用空格隔开,每组输入单独占一行。当输入为 0 0 时,输入结束。    
    
Output    
每组的两个整数(a和b)求和并输出,每组的求和结果独占一行。    
    
Sample Input    
1 5    
10 20    
0 0    
    
Sample Output    
6    
30    

C:

#include <stdio.h>    
int main()    
{    
    int a,b;    
    while(scanf("%d %d",&a, &b) &&(a||b))    
    {    
        printf("%d\n",a+b);    
    }    
    return 0;    
}    

C++:

#include<iostream>    
using namespace std;    
int main()    
{    
    int a ,b;    
    while(cin>>a>>b&&(a||b))    
    {    
        cout<<a+b<<endl;    
    }    
    return 0;    
}    
5. 利用文件重定向提高调试效率
  编程得到正确结果前,往往需要多次运行程序,每次运行都需要花费不少的时间从键盘输入数据。每次输入的数据都是相同的时,会给人的心理带来不爽的感觉,并造成时间上的浪费。无论平时练习还是ACM竞赛实战,这些都是可以避免的。方法是,运用重定向。
  用下面的形式调用函数freopen()会将标准输入stdin重定向到文件input.txt(这个名字可以自己定义)。

  重定向后,原先从键盘(标准输入的默认设备)接受的输入,将统统从文件读取input.txt读取,这就是重定向。

C:

#include<stdio.h>    
int main()    
{    
    freopen("input.txt","r",stdin);  //只加这一句输入将被重定向到文件input.txt    
    int a,b;    
    scanf("%d%d",&a,&b);    
    printf("%d\n",a+b);    
    return 0;    
}   

C++:

#include<iostream>    
#include<fstream>    
using namespace std;    
int main()    
{    
    ifstream fin("input.txt");  //只加这一句输入将被重定向到文件input.txt    
    int a,b;    
    fin>>a>>b;    
    cout<<a+b<<endl;    
    fin.close(); //记得关掉  
    return 0;    
}   
  
于是,在运行程序前,将本该由键盘输入的数据,写到文件input.txt中。而在运行程序时,数据将不再需要人去输入。那个快,很享受。
  需要注意的是,调试通过的程序,千万不要直接提交到OJ平台上去。如果竞赛中这样做了,罚你的20分钟不要算到我的头上。提交的程序要把输入重定向的一行删除,这样才算是符合要求的,可以获得AC的程序。
  除了删除那一行,还有一种简单的做法是,提交前将这一行前加上注释符"//",效果是一样的。
二、字符串输入三种情况
  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程序设计竞赛时,可能认为:样例中都是输入数据和输入数据在一起,输出结果和输出结果在一起,可能会开个数组,把每组的结果存起来,等输入完了再一起输出。当遇到不知有多少组测试数据的题,就难以处理了。
其实在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");
}
示例:A + B Problem (4)
#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;
}
(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行交换。
5、模拟屏幕输出
在一些模拟题中,题目要求输出一幅画,只不过这个画是由字符组成的。对于这种情况,可以采用和带格式的字符串输出相似的方法,先开一个字符数组(在这里,是二维数组),然后把数组当成屏幕输出,屏幕的(i, j)点就是数组的(i, j)号元素。最后,输出这个二维数组就行了。
 一般来说,可以输出一个二维字符数组的方法和输出一般数组的方法是一样的,用双重循环来做。不过,可以只用一个循环就可以了,原因是在数组每行的恰当位置(一般是末尾)加了一个'\0',那么,数组的每一行就成了一个字符串,于是,输出程序就变成了:
int i;
char str[100][100];
...
for (i = 0; i < nRow; i++)
       puts(str);


文章来源:
               ACM题目中输入数据的处理(C++版),见:http://blog.csdn.net/sxhelijian/article/details/8978850
               ACM题目中输入数据的处理(C语言版)见:http://blog.csdn.net/sxhelijian/article/details/8978794
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值