2019-03-03:损坏的RAID5【100】

这道题的难点应该是如何求出来盘数和行数吧

行数计算:

设需要求的块编号为b,行数其实比较好看出来:因为存放的时候是先分成条带,再在条带里的对应块放,所以要先计算出来条带行数

条带行数:在上图中,b=6时,该块所在条带行数为1(从0开始)

块行数:b=6时,该块在其所在条带内行数为0(从0开始),在整个中块行数为2(从0开始)

我们最后要求的是该块在整体中的块行数

思考过程如下:

每个条带行内的块数为(n-1)*s,条带行数=b/((n-1)*s),算出来的是当前块所在条带以上所有的条带行数,再*s,得到当前块所在条带以上的所有块行数。再加上该块在该条带中的行数,即为所求

b/((n-1)*s)*s+b%s

盘数计算:

我个人感觉盘数挺难想的,要不是看了别的朋友的代码,我压根不知道他有规律,下边都是自己的理解,每个人的理解应该也有差别的

因为在计算盘数的时候就只关注盘数就行,行数也可以给他改变,然后我把样例中Dsk0、Dsk1、Dsk2的块数编号分别写出来,发现其实是按顺序的

Dsk0:(0,1) (6,7).....

Dsk1:(2,3) (8,9)......

Dsk2:(4,5) (10,11).....‘

由此得出规律

盘数=b%(n*s)/s

输出为减号(-):

  • 阵列不完整,且被读取的块所在的硬盘缺失,且该数据无法由现存的硬盘数据推算出来;
根据输入块数求出来的盘数不在l个盘中,且n>l+1,无法根据异或运算得出
  • 指定的块超出阵列总长度。
行数+1(标号从0开始)*8>输入的字符串长度
样例1:
2 1 2
0 000102030405060710111213141516172021222324252627
1 000102030405060710111213141516172021222324252627
2
0
1

样例2:
3 2 2
0 000102030405060710111213141516172021222324252627
1 A0A1A2A3A4A5A6A7B0B1B2B3B4B5B6B7C0C1C2C3C4C5C6C7
2
2
5

自己的基础太差了,char *和char a[]根本就分不清楚

100分代码: 

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
using namespace std;

const int MAXN=1001;
const int MAXL=1024*80+5;
char disk[MAXN][MAXL];

int char2num(char c) {
	if(isdigit(c)) {
		return c-'0';
	} else {
		return c-'A'+10;
	}
}

char num2char(int x) {
//	return '0';
	if(x>=10) {
		return 'A'+x-10;
	} else {
		return '0'+x;
	}
}
//取出盘diskid的lineid*8到(lineid+1)*8的字符串
char* substr(char* s,int lineid) {
	char *res=(char *)malloc(sizeof(char)*(8));
	for(int i=0; i<8; i++) {
		res[i]=s[lineid*8+i];
	}
	return res;
}

void XOR(char* a,char*b) {
	for(int i=0; i<8; i++) {
		int temp=char2num(a[i])^char2num(b[i]);
		a[i]=num2char(temp);
	}
}

//每个块大小为4个字节
int main() {
	int n,s,l;  //阵列中硬盘数目为n,阵列的条带大小为s块,现存硬盘数目为l
	scanf("%d%d%d",&n,&s,&l);
	int index;
	for(int i=0; i<l; i++) {
		scanf("%d ",&index);  //硬盘的顺序号
		fgets(disk[index],MAXL,stdin);  // //对于长字符串,请勿直接使用scanf或cin,否则超时
	}
	int len=strlen(disk[index]);
	int m;
	scanf("%d",&m);   //m个请求
	for(int i=0; i<m; i++) {
		int b;
		scanf("%d",&b);
		int diskid=b%(n*s)/s;
		int lineid=b/((n-1)*s)*s+b%s;
		if(disk[diskid][0]=='\0' && n>l+1 || (lineid+1)*8>len) {  //无法进行读取操作
			printf("-\n");
			continue;
		}
		char* res;
		if(disk[diskid][0]!='\0') {  //该盘直接在输入中存在
			//取出盘diskid的lineid*8到(lineid+1)*8的字符串
			res=substr(disk[diskid],lineid);
			for(int i=0;i<8;i++){
				printf("%c",res[i]);
			}
			printf("\n");

		} else { //该盘不在输入中,但是可以通过异或运算求出来
			char ans[10]="00000000";
			for(int j=0; j<n; j++) {
				if(j==diskid) continue;
				else {
					XOR(ans,substr(disk[j],lineid));
				}
			}
			printf("%s",ans);
		}
		
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值