一:题目

(一)基础知识补充(RAID和奇偶校验)

磁盘管理—磁盘阵列(RAID)实例详解(本题目常用RAID 5技术实现)

奇偶校验(同行数据中同位上的1的个数,偶校验时:1的个数为偶数则校验结果为0,否则为1,奇校验时相反:1的个数为偶数则校验结果为1,否则为0)

(二)题目详解

RAID技术用多个磁盘保存数据。每份数据在不止一个磁盘上保存,因此在某个磁盘损
坏时能通过其他磁盘恢复数据。本题讨论其中一种RAID技术。数据被划分成大小
为s(≤s≤)比特的数据块保存在d(≤d≤)个磁盘上,如图所示,每d-1个数据块都
有一个校验块,使得每d个数据块的异或结果为全0(偶校验)或者全1(奇校验)。

(三)案例解析

例如,d=,s=,偶校验,数据6C7A79EDFC(二进制01101100    )的保存方式如图所示

其中加粗块是校验块。输入d、s、b、校验的种类(E表示偶校验,O表示奇校验)以及b(≤b≤)个数据块(其中“x”表示损坏的数据),
你的任务是恢复并输出完整的数据。如果校验错或者由于损坏数据过多无法恢复,应报告磁盘非法。

(四)样例输入

注意:

其中样例输入中:第一组数据网站和书籍有所出入。自己检查后发现书上是可以的。所以将原来的

替换为:

样例输入:

  5  //第一个参数是磁盘块(将一个数据块拆分为多个分别存放在各个磁盘块中)--列数  第二个参数是每个磁盘块存放的数据位数  第三个参数是数据块数(将每一块数据拆分为多个分别存放在各个磁盘中)--行数
E     //E是偶校验 O是奇校验
E xx11011111 O 11xxx
x1111
0  //0代表输入结束

注意点:

、校验块是不加入十六进制运算的
、校验块的顺序是第一行的第一块,第二行的第二个,到了某行最后一个时,下一行就有从第一个开始算做校验块 ----- 当前行数%列数
、十六进制转换是 一个十六进制数字需要四个二进制数字,所以每四位二进制就是一位十六进制
校验进行是一行中每个块的相同位进行校验
、奇校验就是每个数互相异或下来是1,偶校验就是0
、磁盘不合理有三种可能性:一是已知的位校验不符合,二是未知位有多位,无法判断其内容,三是校验位中含有x

数据实际存放样式:

E

    ----->      
E                      

 ---->
xx11011111 xx
O

11xxx        ----->     11xxx x1111
x1111

(五)样例输出

Disk set  is valid, contents are: 6C7A79EDFC
Disk set is invalid.
Disk set is valid, contents are: FFC

二:代码实现

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string> #define ROW 100 //最多100条 100行
#define COL 6 //最多6个磁盘 6列
#define BITS 64 //每个磁盘块最多64位 int col, row, bits;
char DISK[ROW][COL][BITS], ct; //获取基本数据:磁盘数据和校验类型
char Ddata[COL][BITS], CkCode[BITS]; //获取每行数据和校验值 //-1无效 0结束 1正确

获取磁盘数据,并进行检测和纠错

int getDiskData()    //改进:在这里检错
{
int flag = ;
int x_bits[BITS], xNum = , OneNum[BITS]; //记录x位置x_bits中内容是对于列数值和x的个数
scanf("%d", &col);
if (col == ) return ;
scanf("%d %d", &bits, &row);
getchar();
scanf("%c", &ct);
getchar(); //获取磁盘数据
for (int i = ; i < row;i++)
{
memset(x_bits, -, sizeof(x_bits));
memset(OneNum, , sizeof(OneNum));
for (int j = ; j < col; j++)
{
for (int k = ; k < bits; k++)
{
scanf("%c", &DISK[i][j][k]);
if (DISK[i][j][k] == '\n')
{
k--;
continue;
}
if (i%col == j) //不允许校验位为x
{
if (DISK[i][j][k] == 'x')
flag = -;
} if (DISK[i][j][k] == 'x')
{
if (x_bits[k] != -) //不允许在同一位出现多个x
flag = -;
x_bits[k] = j; //最多记录不同位上的x位置
}
if (i%col !=j && DISK[i][j][k] == '')
OneNum[k]++;
}
}
//复制校验位
memcpy(CkCode, DISK[i][i%col], BITS);
for (int k = ; k < bits;k++) //将对应位置上的数据进行纠错
{
if (x_bits[k] != -) //该行有x数据,需要纠错(纠错就避免了检错)
{
if (ct == 'E') //偶校验
{
if ((CkCode[k] == ''&&OneNum[k] % == ) || (CkCode[k] == '' && OneNum[k] % == ))
DISK[i][x_bits[k]][k] = '';
else
DISK[i][x_bits[k]][k] = '';
}
else //奇校验
{
if ((CkCode[k] == ''&&OneNum[k] % == ) || (CkCode[k] == '' && OneNum[k] % == ))
DISK[i][x_bits[k]][k] = '';
else
DISK[i][x_bits[k]][k] = '';
}
}
else //该行没有x数据,直接检错
{
if (ct == 'E' && ((CkCode[k] == ''&&OneNum[k] % == ) || (CkCode[k] == '' && OneNum[k] % == )))
flag = -;
if (ct == 'O' && ((CkCode[k] == ''&&OneNum[k] % == ) || (CkCode[k] == '' && OneNum[k] % == )))
flag = -;
}
}
}
getchar();
return flag;
}

将字符串二进制转为16进制输出

//转换16进制输出
void printValidData()
{
int n = ;
int m;
//获取每一行数据,进行输出
for (int i = ; i < row; i++)
{
m = ;
for (int j = ; j < col; j++)
{
if (i%col==j) continue; //跳过校验位
for (int k = ; k < bits; k++)
{
if (DISK[i][j][k] == '')
n |= 0x01;
else
n |= 0x00;
m++;
if (m == )
{
printf("%X", n);
n = , m = ;
}
n <<= ;
}
}
//获取完一行
if (m > && m != )
{
m++;
while (m != )
{
n |= 0x00,n <<= ;
m++;
}
printf("%X", n);
}
}
printf("\n");
}

主函数

void main()
{
int c = , flag;
FILE* fp = freopen("data7.in", "r", stdin);
freopen("data7.out", "w", stdout); while (!feof(fp))
{
flag = getDiskData();
if (flag == ) break;
if (flag == -)
printf("Disk set %d is invalid.\n",c++);
else
{
printf("Disk set %d is valid, contends are: ",c++);
printValidData();
}
} freopen("CON", "r", stdin);
freopen("CON", "w", stdout);
}

最新文章

  1. DBImport v3.44 中文版发布:数据库数据互导及文档生成工具(IT人员必备)
  2. MyEclipse使用前优化与配置
  3. php实现注册
  4. Linux 安装配置Subversion edge
  5. lintcode:排颜色 II
  6. iOS 定位系统 知识
  7. 设置datagridview中button按钮的背景颜色
  8. js常用代码收藏
  9. SQL-Server索引漫谈
  10. 【算法系列学习】Dijkstra算法变形 [kuangbin带你飞]专题四 最短路练习
  11. Vue.js与Jquery的比较 谁与争锋 js风暴
  12. 查看 设置mysql时区
  13. 数据的描述性分析_R
  14. Ubuntu下导入PySpark到Shell和Pycharm中(未整理)
  15. react-router4 + webpack Code Splitting
  16. java基础语法学习DayOne
  17. [转]PHP利用Gearman来处理并行多进程问题
  18. VS2010/MFC编程入门之三十六(工具栏:工具栏资源及CToolBar类)
  19. 个人知识管理系统Version1.0开发记录(06)
  20. [001] leap_stage

热门文章

  1. 《CoderXiaoban》第九次团队作业:Beta冲刺与验收准备1
  2. 《代码敲不队》第九次团队作业:Beta冲刺第1天
  3. keras模块学习之-目标函数(objectives)笔记
  4. notepad++ 调整行间距
  5. 网络 IP
  6. java中split函数参数特殊字符的处理(转义),如:&quot;.&quot; 、&quot;\&quot;、&quot;|&quot;
  7. js遍历删除数组中不符合条件的元素
  8. cube.js 学习(三)cube.js data schema
  9. 【一起来烧脑】一步学会AngularJS系统
  10. if后的判断条件