文件读入输出、数据生成、对拍

2021/10/20 6:11:30

本文主要是介绍文件读入输出、数据生成、对拍,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录
  • 文件读入输出
    • 知识介绍
    • 使用方法
  • 数据生成
    • 知识介绍
    • 使用方法
  • 对拍
    • 知识介绍
    • 使用方法
    • 注意事项
    • 对拍演示

文件读入输出

知识介绍

顾名思义,程序将会从文件中读入数据,也会将数据输出到文件中(两文件可不同)

在有时,如果程序想要测试数据较大的样例

可能会因为要输入的东西过多而无法完成

这时,如果我们已经有了输入数据的文件

便可以通过文件读入输出来使程序自动完成数据的输入与输出

使用方法

freopen("a.in", "r", stdin)

头文件 \(cstdio(stdio.h)\) 中包含函数 \(freopen\),用于重定向输入输出流

freopen("a.in", "r", stdin);//使程序从文件 a.in 中读入
fclose(stdin);//恢复 输入流 的重定向

\(r\) 为 \(read\) 的简写,表示“只读访问”

\(stdin\) 表示被重定向的文件流为 输入流

freopen("a.out", "w", stdout)

freopen("a.out", "w", stdout);//使程序输出到文件 a.out
fclose(stdout);//恢复 输出流 的重定向

\(w\) 为 \(write\) 的简写,表示“只写访问”

\(stdout\) 表示被重定向的文件流为 输出流

代码示例

在一般情况下,将 \(freopen\) 两个语句放到主函数开头

将 \(fclose\) 两个语句放到主函数末尾(\(return\ 0;\)之前)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e6 + 5;
typedef long long LL;
int read() {
	int x = 0, f = 1; char ch;
	while(! isdigit(ch = getchar())) (ch == '-') && (f = -f);
	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 3) + (x << 1) + (ch ^ 48));
	return x * f;
}
template <class T> T Max(T a, T b) { return a > b ? a : b; }
template <class T> T Min(T a, T b) { return a < b ? a : b; }
int main() {
	freopen("a.in", "r", stdin);
	freopen("a.out", "w", stdout);
	
	fclose(stdin);
	fclose(stdout); 
	return 0;
}

注:

  • 文件 \(a.in\) 和 \(a.out\) 应和程序在同一目录下

    当不存在文件 \(a.out\) 时,会由程序自动建立

  • 当由本地评测机对程序进行数据测试时

    一般也是采用文件读入输出+文件文本对比的方式判断程序运行情况

  • 文件读入输出适用于数据较大的情况

  • 输入输出文件名可以自定义,不一定以 \(.in\) 和 \(.out\) 为后缀名

数据生成

知识介绍

我们在本地进行编译测试程序时,一般使用的都是小数据

但在某些情况下,我们需要用大数据来对程序进行测试

显然,有时大数据会因为数据量过大而无法手动生成

此时,便需要我们利用程序编写数据生成的代码

来辅助我们对于代码的调试

使用方法

在头文件 \(cstdlib(stdlib.h)\) 中

包含两个函数 \(rand()\) 和 \(srand()\) 及一个整数常量 \(RAND\_MAX\)

RAND_MAX

一般情况下,\(RAND\_MAX\) 在 \(Windwos\) 系统中为 \(32767\)

而在类 \(Unix\) 系统中为 \(2147483647\)

rand()

\(rand()\) 函数返回区间 \([0,RAND\_MAX]\) 内的随机整数 \(int\)

srand()

\(srand()\) 函数接受一个无符号 \(32\) 位整数的参数作为 \(seed\) (随机种子)

此后,\(rand()\) 函数按一定规则生成随机数

种子确定后,每次 \(rand()\) 得出的值便被固定(实际上,这种随机叫做伪随机)

注:默认情况下,\(seed\) 为 \(1\)

time(0)

那么此时出现了问题,如果想生成随机数

需要事先将一个随机数当作种子,那么这个随机数从哪里来呢?

对于该问题,一个简单的解决方法是

使用头文件 \(ctime(time.h)\) 中的 \(time()\) 函数

\(time(0)\) 返回从 \(1970\) 年 \(1\) 月 \(1\) 日 \(0\) 时 \(0\) 分 \(0\) 秒 (\(Unix\) 纪元 )到现在的秒数

代码示例

以下程序 \(random(x)\) 函数生成 \([0,n-1]\) 的整数

#include <cstdlib>
#include <ctime>
int random(int n) {
	return (long long)rand() * rand() % n;
}
int main() {
	srand((unsigned)time(0));//(unsigned)可以省略,强制类型转换
	
	return 0;
}

对拍

知识介绍

对拍是一种用于调试程序的方法

当我们写出一个程序,但不知道所用的方法是否正确时

如果我们已经拥有一份运行正确的代码

那么我们可以通过对拍的方法来找到使得我们程序错误的样例

\(Windows\) 系统下有 \(bat\) 批处理脚本

类 \(Unix\) 系统下有 \(bash\) 脚本

都可以用来编写对拍程序

此处介绍使用 \(C/C++\) 语言编写对拍程序的方法

使用方法

system()

头文件 \(cstdlib(stdlib.h)\) 中函数 \(system\) 接受字符串参数

并将该字符串作为系统命令执行

例如:system("C:\\random.exe") 执行 \(C\) 盘根目录下的 \(random.exe\) 文件

fc/diff

\(Windows\) 系统命令 \(fc\) 和 类\(Unix\) 系统命令 \(diff\) 可以进行文件比对

后接两个文件路径,比较两文件是否一致,并返回 \(0\)(一致)或 非零值(不一致)

注:该命令在文本比对时默认忽略行末空格和行尾回车

与一般评测网站和评测机所使用的文本对比方式相同

若需要特别的文本比对方式,需要另加参数

注意事项
  • 当命令行中所所传入的文件路径与当前命令行所处路径相同时,可省略文件路径

    QQ截图20211020002636.png

  • 文件路径查看方式

    右键单击文件 --> 属性 --> 位置

  • 显示文件扩展名(后缀名)

    我的电脑 --> 查看 --> 文件扩展名

    QQ截图20211020003741.png

  • 打开命令行

    ①\(Win+r\) --> 输入 "cmd" --> 回车

    ②按如图方式输入 “cmd” 并回车

    注:方法②打开的命令行会自动跳转至输入“cmd”的界面所在目录

    QQ截图20211020004120.png

对拍演示

四个程序:

\(a.cpp:\) 未知对错程序

#include <iostream>
#include <cstdio>
using namespace std;
int main() {
	freopen("a.in", "r", stdin);
	freopen("a.out", "w", stdout);
	int a, b;
	cin >> a >> b;
	cout << (a + b) << endl;
	fclose(stdin);
	fclose(stdout);
	return 0;
} 

\(b.cpp:\) 正确程序

#include <stdio.h>
int main() {
	freopen("a.in", "r", stdin);
	freopen("b.out", "w", stdout);
	int a, b;
	scanf("%d%d", &a, &b);
	printf("%d\n", a + b);
	fclose(stdin);
	fclose(stdout);
	return 0;
}

\(rand.cpp:\) 数据生成器

#include <cstdio>
#include <ctime> 
#include <cstdlib>
using namespace std;
int main() {
	freopen("a.in", "w", stdout);
	srand(time(0));
	printf("%d %d\n", rand(), rand());
	return 0;
}

\(dp.cpp:\) 对拍程序

#include <cstdio>
#include <ctime> 
#include <cstdlib>
using namespace std;
int main() {
	int cnt = 0;
	while(1) {
		system("rand.exe");
		double t1 = clock();
		system("a.exe");
		double t2 = clock();
		system("b.exe");
		if(system("fc a.out b.out")) { printf("WA\n");return 0; }
		else printf("AC: %d T: %.2f\n", ++ cnt, (t2 - t1) / 1000.0);
	}
	return 0;
}

注:\(clock()\) 函数在头文件 \(ctime(time.h)\) 中

返回程序从运行到现在的时间(单位:\(ms\)(\(Windows\)系统)、\(s\)(类\(Unix\)系统))

将这四个程序都放在桌面

编译运行前三个程序,生成对应的可执行文件(\(.exe\) 文件)后

编译运行对拍程序即可进行对拍

QQ截图20211020005932.png

当两程序输出结果不同时,会在屏幕上输出 "WA" 并结束程序



这篇关于文件读入输出、数据生成、对拍的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程