数据处理程序
前段时间帮一个外学院的老师处理数据,发现自己会的太少的,按理用脚本应该可以更方便搞定的(没研究那么深),结果硬是写了400行的C++代码。
IDE 用的是CodeBlocks
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <windows.h>
#include <stdio.h>
#include <string.h>
#define LEN 1024
using namespace std;
typedef long long LL;
const int MAXN = 1e6 + 10;
const int INF = 1e9 + 7;
struct Data {
int number; // 区站号
int year; // 年
int month; // 月
int day; // 日
double water; // 20-20时降水量
double Max; // 日最高气温
double Min; // 日最低气温
double aver; // 平均气温
};
Data num[MAXN];
bool cmp(Data a, Data b) {
if(a.year != b.year) {
return a.year < b.year;
}
else {
return a.month != b.month ? a.month < b.month : a.day < b.day;
}
}
//输出结果:
//年份 一般性高温(35 ℃ - 38 ℃)天 危害性高温(38 ℃ - 40 ℃)天
//强危害性高温(≥ 40 ℃)天 极端最高气温(各台站每一年日高温最大值)℃
//热浪日数 最长热浪持续日数
struct Answer {
int year; // 年份
int num1; // 一般性高温(35 ℃ - 38 ℃)天
int num2; // 危害性高温(38 ℃ - 40 ℃)天
int num3; // 强危害性高温(≥ 40 ℃)天
double Max; // 极端最高气温(各台站每一年日高温最大值)℃
int day1; // 热浪日数
int day2; // 最长热浪持续日数
};
Answer ans[MAXN];
double rec[MAXN]; // 存储1961 - 1990的所有日最高温度
int D[13] = {0, 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
bool judge(int y) {
return y % 400 == 0 || (y % 4 == 0 && y % 100);
}
void Work1(LPCSTR FullPathName, LPCSTR outputPath1) {
freopen(FullPathName, "r", stdin);
freopen(outputPath1, "w", stdout);
char str[1000];
for(int i = 1; i <= 8; i++) {
scanf("%s", str);
}
int N = 0; int M = 0;
int res = 0;
while(scanf("%d%d%d%d%lf%lf%lf%lf", &num[N].number, &num[N].year, &num[N].month, &num[N].day,
&num[N].water, &num[N].Max, &num[N].Min, &num[N].aver) != EOF) {
if(num[N].year >= 1961 && num[N].year <= 1990) {
rec[M++] = num[N].Max;
}
N++;
}
//如果输入的数据 没有按年月日严格排列
sort(num, num + N, cmp);
//判断1961-2016的数据全不全
int s = -1;
for(int i = 0; i < N; i++) {
if(num[i].year == 1961) {
s = i; break;
}
}
if(s == -1) {
printf("1961-2015年数据不全\n");
return ;
}
bool flag = true;
for(int i = 1961; i <= 2015; i++) {
if(judge(i)) {
D[2] = 29;
}
else {
D[2] = 28;
}
for(int j = 1; j <= 12; j++) {
for(int k = 1; k <= D[j]; k++) {
if(s < N && num[s].year == i && num[s].month == j && num[s].day == k) {
s++;
}
else {
printf("%d %d %d\n", i, j, k);
flag = false; break;
}
}
if(!flag) break;
}
if(!flag) break;
}
if(num[N - 1].year == 2015 && num[N - 1].month == 12 && num[N - 1].day == 31) {
}
else {
flag = false;
}
if(!flag) {
printf("1961-2015年数据不全\n");
return ;
}
// 处理缺测数据
for(int i = 0; i < N; i++) {
if(num[i].Max >= 30000) {
num[i].Max = 0;
}
}
int j = 0; // 从1961年开始
for(int i = 0; i < N; i++) {
if(num[i].year == 1961) {
j = i; break;
}
}
for(int i = 1961; i <= 2015; i++) {
ans[i].year = i;
ans[i].num1 = 0; ans[i].num2 = 0; ans[i].num3 = 0;
ans[i].Max = -100000000;
for(; j < N; j++) {
if(num[j].year != i) break;
ans[i].Max = max(ans[i].Max, num[j].Max); // 求解每年极端最高气温
if(num[j].Max >= 350 && num[j].Max < 380) {
ans[i].num1++;
} // 求解一般性高温(35 ℃ - 38 ℃)天
if(num[j].Max >= 380 && num[j].Max < 400) {
ans[i].num2++;
} // 求解危害性高温(38 ℃ - 40 ℃)天
if(num[j].Max >= 400) {
ans[i].num3++;
} // 求解强危害性高温(≥ 40 ℃)天
}
}
double mark = 320; // 热浪的临界温度值
//求解热浪的临界温度值
sort(rec, rec + M); // 升序排列
//找第95百分位 温度值
if((M * 95) % 100 == 0) {
mark = max(mark, 1.0 * rec[(M * 95) / 100 - 1]);
}
else {
int pos = (M * 95) / 100 - 1;
mark = max(mark, 1.0 * (rec[pos] + rec[pos + 1]) / 2);
} // 取平均值
j = 0;
for(int i = 0; i < N; i++) {
if(num[i].year == 1961) {//从1961年
j = i; break;
}
}
for(int i = 1961; i <= 2015; i++) {
ans[i].day1 = 0; ans[i].day2 = 0;
int s = -1; // 记录热浪的起始点
for(; j < N; j++) {
if(num[j].year != i) break;
if(num[j].Max >= mark) {
if(s == -1) { // 未设置起点
s = j;
}
}
else { // 断了
if(s != -1) { // 是否存在起点
int cnt = j - s; // 持续天数
if(cnt >= 3) { // 超过三天
ans[i].day1 += cnt;
ans[i].day2 = max(ans[i].day2, cnt);
}
}
s = -1;
}
}
if(s != -1) {
int cnt = j - s;
if(cnt >= 3) {
ans[i].day1 += cnt;
ans[i].day2 = max(ans[i].day2, cnt);
}
}
}
printf("年份 ");
printf(" 一般性高温(35℃-38℃)天 ");
printf(" 危害性高温(38℃-40℃)天 ");
printf("强危害性高温(≥40℃)天 ");
printf(" 极端最高气温(各台站每一年日高温最大值)℃");
printf(" 热浪日数 ");
printf(" 最长热浪持续日数\n");
for(int i = 1961; i <= 2015; i++) {
printf("%-1d ", ans[i].year);
printf("%-1d ", ans[i].num1);
printf("%-1d ", ans[i].num2);
printf(" %-1d ", ans[i].num3);
printf(" %-1.0lf ", ans[i].Max);
printf(" %-1d ", ans[i].day1);
printf("%-1d \n", ans[i].day2);
}
//1961 - 1990 均值
printf("1961-1990均值 ");
double sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0, sum6 = 0;
for(int i = 1961; i <= 1990; i++) {
sum1 += ans[i].num1;
sum2 += ans[i].num2;
sum3 += ans[i].num3;
sum4 += ans[i].Max;
sum5 += ans[i].day1;
sum6 += ans[i].day2;
}
printf("%-1.2lf ", sum1 / 30);
printf("%-1.2lf ", sum2 / 30);
printf(" %-1.2lf ", sum3 / 30);
printf(" %-1.2lf ", sum4 / 30);
printf(" %-1.2lf ", sum5 / 30);
printf("%-1.2lf \n", sum6 / 30);
//1991 - 2015 均值
printf("1991-2015均值 ");
sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0, sum6 = 0;
for(int i = 1991; i <= 2015; i++) {
sum1 += ans[i].num1;
sum2 += ans[i].num2;
sum3 += ans[i].num3;
sum4 += ans[i].Max;
sum5 += ans[i].day1;
sum6 += ans[i].day2;
}
printf("%-1.2lf ", sum1 / 25);
printf("%-1.2lf ", sum2 / 25);
printf(" %-1.2lf ", sum3 / 25);
printf(" %-1.2lf ", sum4 / 25);
printf(" %-1.2lf ", sum5 / 25);
printf("%-1.2lf \n", sum6 / 25);
}
char outputPath2[LEN]; // 每个省输出文件的路径
void Work2_Init() { // 用于Work2
// 求出 均值数据输出路径
//strcpy(outputPath2, "C:\\Users\\chenzhenyu\\Desktop\\Newdata\\重庆市\\均值.txt");
freopen("out.txt", "a", stdout);
printf("区站号 ");
printf("第一阶段 ");
printf(" 一般性高温(35℃-38℃)天 ");
printf(" 危害性高温(38℃-40℃)天 ");
printf("强危害性高温(≥40℃)天 ");
printf(" 极端最高气温(各台站每一年日高温最大值)℃");
printf(" 热浪日数 ");
printf(" 最长热浪持续日数 ");
printf("第二阶段 ");
printf(" 一般性高温(35℃-38℃)天 ");
printf(" 危害性高温(38℃-40℃)天 ");
printf("强危害性高温(≥40℃)天 ");
printf(" 极端最高气温(各台站每一年日高温最大值)℃");
printf(" 热浪日数 ");
printf(" 最长热浪持续日数\n");
}
void Work2(LPCSTR FullPathName, char *s) {
freopen(FullPathName, "r", stdin);
freopen("out.txt", "a", stdout);
char ss[1000]; scanf("%s", ss);
bool First = false;
if(ss[0] >= '0' && ss[0] <= '9') {
First = true;
}
for(int i = 2; i <= 7; i++) {
scanf("%s", ss);
}
if(First) {
for(int i = 1962; i <= 2015; i++) {
for(int j = 1; j <= 7; j++) {
scanf("%s", ss);
}
}
}
else {
for(int i = 1961; i <= 2015; i++) {
for(int j = 1; j <= 7; j++) {
scanf("%s", ss);
}
}
}
printf("%s ", s);
for(int i = 1; i <= 2; i++) {
for(int j = 1; j <= 7; j++) {
scanf("%s", ss);
printf("%s ", ss);
}
}
printf("\n");
}
void Work3(LPCSTR Path, char *s) { // 筛选区站号为s的最新年份的站点数据,路径为Path
freopen("安徽.txt", "r", stdin); // 打开该省最新年份所有站点的数据文件
freopen(Path, "a", stdout);
char str[100];
for(int i = 1; i <= 20; i++) {
scanf("%s", str);
}
int val = 0;
for(int i = 0; i < 5; i++) {
val = val * 10 + s[i] - '0';
}
int a[30];
while(scanf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
&a[1], &a[2], &a[3], &a[4], &a[5], &a[6], &a[7], &a[8], &a[9], &a[10],
&a[11], &a[12], &a[13], &a[14], &a[15], &a[16], &a[17], &a[18], &a[19], &a[20]) != EOF) {
if(a[1] == val) {
printf("%d %d %d %d %d %d %d\n", a[1], a[2], a[3], a[4], a[20], a[15], a[16], a[14]);
}
}
}
BOOL DirectoryList(LPCSTR Path) {
WIN32_FIND_DATA FindData;
HANDLE hError;
char FilePathName[LEN];
// 构造路径
char FullPathName[LEN];
strcpy(FilePathName, Path);
strcat(FilePathName, "\\*.*");
hError = FindFirstFile(FilePathName, &FindData);
if (hError == INVALID_HANDLE_VALUE) {
printf("搜索失败!");
return 0;
}
while(::FindNextFile(hError, &FindData)) {
// 过虑.和..
if (strcmp(FindData.cFileName, ".") == 0
|| strcmp(FindData.cFileName, "..") == 0 ) {
continue;
}
// 构造完整路径
sprintf(FullPathName, "%s\\%s", Path, FindData.cFileName);
/*
// 用于Work1,求出每个站每一年的数据
char outputPath1[LEN]; // Work1中输出文件的路径
strcpy(outputPath1, "C:\\Users\\chenzhenyu\\Desktop\\Newdata\\安徽省\\out");
strcat(outputPath1, "\\");
strcat(outputPath1, FindData.cFileName);
Work1(FullPathName, outputPath1); // 统计所有基础信息
*/
bool Stop = false;
int len = strlen(FullPathName);
if(FullPathName[len - 1] != 't') {
Stop = true;
}
if(!(FullPathName[len - 5] >= 0 && FullPathName[len - 5] <= '9')) {
Stop = true;
}
if(FullPathName[len - 11] != 't') {
Stop = true;
}
// 求出区站号
char number[1000];
for(int i = 0; i <= 4; i++) {
number[i] = FindData.cFileName[i];
}
number[5] = 0;
if(!Stop) {
//cout << FullPathName << endl;
Work2(FullPathName, number); // 统计均值
}
//Work3(FullPathName, number); // 筛选区站号为number路径为FullPathName的数据
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
DirectoryList(FullPathName);
}
}
return 0;
}
int main()
{
//Work2_Init(); // 用于统计每个省 两个阶段的数据
DirectoryList("C:\\Users\\chenzhenyu\\Desktop\\Newdata");
/*
李震需要的的部分
*/
/*for(int i = 1961; i <= 2016; i++) {
//freopen("每年所有站点数据平均值.txt", "a", stdout);
DirectoryList("C:\\Users\\chenzhenyu\\Desktop\\Newdata\\安徽省");
}*/
return 0;
}