You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

104 lines
4.2 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <bits/stdc++.h>
//题意分析https://blog.csdn.net/xienaoban/article/details/52164099
using namespace std;
//d:d块磁盘,s:1<=s<=64数据被划分成大小为s比特的数据块
//b:b个数据块 b in range(1,101)
int d, s, b, kase = 0;
//type:校验的种类E->偶校验 O->奇校验
char type;
//每块磁盘上8的含义数据的内容之所以是8000是因为每个字符是8个字节
char tab[8][8000];
//检查是不是合法
bool Fix() {
for (int i = 0; i < s * b; ++i) {
//s比特的数据块 * 数据块个数=所有的比特数据个数
// ++i 表示先加1再循环与i++的区别在于:
// https://blog.csdn.net/qq_41620518/article/details/88066963
int sum = 0, cnt = 0, x_no;
for (int j = 0; j < d; ++j) {
if (tab[j][i] == '1') ++sum;//求1的个数
if (tab[j][i] == 'x') ++cnt, x_no = j;
//如果存在x即明确的错误标识那么cnt记录错误的个数,同时记录是哪个位置出错了~
}
sum %= 2; //求最终校验位是0还是1看看是不是有问题
if (cnt >= 2) return false;//有两个以上错误就没办法了
else if (cnt == 1) //如果还可以挽救的话
{
if (sum)//如果是1
if (type == 'E') //如果是偶校验,表示缺少一个1那么肯定是出错标识的那个位置是1
tab[x_no][i] = '1';
else tab[x_no][i] = '0';//如果是奇校验位表示1的数量正常出错标识那个的位置是0
else //如果是0
if (type == 'E') tab[x_no][i] = '0'; //如果是偶校验位出错标识的那个位置是0
else tab[x_no][i] = '1';//如果是奇校验位出错标识的那个位置是1
} else if (cnt == 0) {//没有明确出错标识,检查吧
if (type == 'E' && sum == 1) return false; //偶校验,但校验码是奇数,表示有错误
if (type == 'O' && sum == 0) return false; //奇校验,但校验码是偶数,表示有错误
}
}
return true;
}
//输出数据
void out_data() {
int sum = 0, bit_cnt = 0;
//b个数据块
for (int i = 0; i < b; ++i) {
int except = i % d; //排除哪一块磁盘上是存在parity
//d块磁盘
for (int j = 0; j < d; ++j) {
if (j == except) continue; //遍历每一块磁盘时,遇到校验块就跳过
//数据是s比特的数据块
//然后还有一点是输出数据的时候4个bit转化为一个十六进制。
//刚开始做题认为每个数据块输出一个整数这需要2^5*64这么大的数来存储
//难道要用大整数类?后来一想,可以每一个十六进制位输出一次便可。
for (int k = i * s; k < i * s + s; ++k) { //遍历每一个数据位
bit_cnt = (bit_cnt + 1) % 4;
if (tab[j][k] == '0') sum *= 2;
else sum = sum * 2 + 1;
if (!bit_cnt) {
printf("%X", sum);
sum = 0;
}
}
}
}
//有尾巴需要输出的话
if (bit_cnt) {
int over = 4 - bit_cnt;
sum = sum * (1 << over);
printf("%X", sum);
}
printf("\n");
}
int main() {
//https://www.cnblogs.com/cytus/p/7763569.html
//对于标准输入和输出的缓冲同步进行禁止,防止程序超时
ios::sync_with_stdio(false);
//真是能省就省啊一路初始化数组一般输入数据如果数据是0或者小于0那么停止。
while (memset(tab, 0, sizeof(tab)), cin >> d && d) {
//d:d个磁盘
//s:数据被划分成大小为s比特的数据块
//b: 1<=b<=100个数据块
//type:校验的种类E表示偶校验O表示奇校验
cin >> s >> b >> type;
for (int i = 0; i < d; ++i)
cin >> tab[i]; //在录入磁盘中的数据
//校验失败
if (!Fix())
printf("Disk set %d is invalid.\n", ++kase);
else {
//校验成功
printf("Disk set %d is valid, contents are: ", ++kase);
//输出数据
out_data();
}
}
return 0;
}