#include //题意分析: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; }