汇总一下在算法考试中常见的输入格式及处理方法,以防止出现明明算法是会的但由于输入问题处理不好导致题目没有答出,我就栽倒在这个问题上过。
一、几个常用的输入函数的异同
1. scanf()
需要包含头文件stdio.h。
scanf函数的返回值就是读入的变量的个数。
#include <stdio.h>
int main() {
int a, b;
int m = scanf("%d %d", &a, &b);
printf("a = %d, b = %d, m = %d", a, b, m);
return 0;
}
输入输出结果如下。
在这里,scanf函数规定了要输入两个变量,则一定要输完两个变量才可以进行下去,如果没输完两个变量,不管中间是按回车还是空格,都不会继续执行程序而是已知等待输入。这说明,scanf函数并不把回车和空格判定成一个输入。
scanf遇到空格、tab、回车都会判定结束。例如,如果只要求输入一个字符串但实际上输入了被空格分开的两个字符串,则只读入第一个。
#include <stdio.h>
int main() {
char a[10];
scanf("%s", a);
printf("%s", a);
return 0;
}
scanf也可以用来输入多个字符串,每个字符串之间用空格分开。
#include <stdio.h>
int main() {
char a[10], b[10];
scanf("%s %s", a, b);
printf("%s\n%s", a, b);
}
与输入其他类型的数据时同样,scanf必须读够两个输入才会继续运行,两个输入之间的空格和回车都不算。
2. cin >>
需要包括头文件iostream和命名空间std。
#include <iostream>
using namespace std;
其他各项特点基本与scanf相同,但还是有一些细微的区别。可以参考这篇文章。由于从时间效率上,scanf比cin要快很多,所以我郑重在写算法题时使用scanf,常常有意想不到的效果。
3. c++中其他常用输入函数
补充:无回车不回显的输入方式
_getch()函数是一个不回显函数,当用户按下某个字符时,函数自动读取,无需按回车,有的C语言命令行程序会用到此函数做小游戏,但是这个函数并非标准函数,要注意移植性!需要包括头文件conio.h。
二、常见输入输出情况汇总
1. 预先告知有N个输入块,接下来N行是这N个输入块的内容
计算A+B的值
输入描述:每一行整数N,接下来有N行输入,每行输入两个整型数字A和B,由空格分开,每组数字占一行。
输出描述:每个例子输出A+B单独作为一行。
输入样例:
2
1 1
4 4
输出样例:
2
8
这是最简单的情况,没啥好说的,直接上代码。
c语法:
scanf("%d",&n) ;
for( i=0 ; i<n ; i++ ) {
scanf("%d %d",&a, &b);
printf(“%d\n”,a+b);
}
c++语法:
cin >> n;
for( i=0 ; i<n ; i++ ) {
cin >> a >> b;
cout << a+b << endl;
}
2. 输入时不说明有多少个输入块,但以EOF结尾
计算A+B的值
输入描述:每一行输入两个整数A和B,由空格分开。
输出描述:每个例子输出A+B单独作为一行。
输入样例:
1 1
2 2
输出样例:
2
4
补充:什么是文件结束符EOF
EOF是End Of File的缩写,是一个预定义的常数,值为-1。通常在文本的最后存在此字符表示资料结束。
以EOF作为文件结束标志的文件,必须是文本文件。因为在文本文件中,数据都是以字符的ASCII代码值的形式存放。ASCII代码值的范围是0~255,不可能出现-1,因此可以用EOF作为文件结束标志。
c语法:
while (scanf("%d %d", &a, &b) != EOF) {
...
}
我写了这样一个程序。
#include <stdio.h>
int main() {
int a, b;
while (scanf("%d %d", &a, &b) != EOF) {
printf("%d", a + b);
}
}
结果如下。如果你是从控制台输入的话,每输入两个数字,按一下回车,就会输出一个结果。但问题是,程序会已知循环下去,不知道什么时候判定成输入结束。
如果我这样输入。一下子输入好几组数字,不使用回车,则每次循环会顺序往后读入两个输入,然后打印在屏幕上。但依旧不知什么时候判定成结束输入。
这是因为文件结束符是存在于文件输入的情况。如果你是控制台输入,没有手动输入文件控制符,自然不可能结束循环。
然而,ACM竞赛平台通常是从文本中进行数据输入的,因此会使用文件结束符EOF作为结束标志。因此在这类没有限定结束标志的问题中,直接判断是否读到文件结束符EOF就可以了。
c++语法:
while (cin >> a >> b) {
...
}
3. 输入时需要处理换行符
我曾经栽倒在这样的题目上过,明明算法很简单,但处理输入处理了半个多钟头。下面举个例子。
链表合并问题
输入描述:先输入一个非负数n,表示有n个链表。接下来输入n行,每行有若干个数字,中间用空格隔开,表示每一个链表。
输出描述:输出合并后的链表。
使用getchar()判断输入的字符是不是换行符’\n’。代码如下,只处理了输入问题,没有实现该题目的具体逻辑。
#include <stdio.h>
#include <vector>
using namespace std;
int main() {
int N;
scanf("%d", &N);
vector<vector<int>> linklists;
for (int i = 0; i < N; i++) {
vector<int> llist;
int num;
do {
scanf("%d", &num);
llist.push_back(num);
} while (getchar() != '\n');
linklists.push_back(llist);
}
//打印上面输入的内容
for (auto& a : linklists)
{
for (auto b : a)
printf("%d ", b);
printf("\n");
}
return 0;
}
这篇文章写起来不易,如果它对你有帮助的话,麻烦给个赞吧!!