RAID! UVA - 509

链接:https://vjudge.net/problem/UVA-509

记录这个题主要是来记录一下自己遇到的神奇的bug,避免再走弯路。

#include <iostream>
#include <stdio.h>
#include <cstring>
//#define LOCAL
using namespace std;
char disk[7][105][66];
int d, s, b, check, exibs[105][66], flcnt;
char d2h[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; 
            //一种更简单的写法:="0123456789ABCDEF"
struct Flaw
{
    int df, bf, sf;
} flaw[6800];

int get(int cd, int cb)
{
    char c; bool f = true;
    for (int i = 1; i <= s; ++i)
    {
        c = getchar();
        if (c == 'x')
        {
            if (exibs[cb][i] == 0)
                flcnt++, flaw[flcnt].df = cd, flaw[flcnt].bf = cb, flaw[flcnt].sf = i, exibs[cb][i] = 1;
            else f = false;
        }
        disk[cd][cb][i] = c;
    }
    disk[cd][cb][s + 1] = '\0'; //就是这句,要重新设置结束符,不然会跟以前记录的数据连在一起输出。。
    return f;
}

void fix(int df, int bf, int sf)
{
    int ans = 0;
    for (int i = 1; i <= d; ++i)
    {
        if (i != df) ans ^= disk[i][bf][sf] - '0';
    }
    disk[df][bf][sf] = char((ans ^ check) + '0'); //注意位运算的优先级是很低的,要加括号保险(之前被这个坑了)
}

bool examine()
{
    int t;
    for (int k = 1; k <= s; ++k)
    {
        for (int j = 1; j <= b; ++j)
        {
            t = 0;
            for (int i = 1; i <= d; ++i)
            {
                t ^= disk[i][j][k] - '0';
            }
            if (t != check) return false;
        }
    }
    return true;
}

void print()
{
    char output[50000] = "\0";
    for (int i = 1; i <= b; ++i)
    {
        for (int j = 1; j <= d; ++j)
        {
            if ((i - 1) % d + 1 != j)
            {
                strcat(output, disk[j][i] + 1); //就在这里用了整租字符串,没有注意结束符号QAQ
            }
        }
    }
    int n = strlen(output);
    int t = n % 4;
    if (t)
    {
        n += 4 - t;
        for (int i = 1; i <= 4 - t; ++i)
            strcat(output, "0"); //注意一下strcat的用法
    }
    for (int i = 0; i <= n - 4; i += 4)
    {
        t = 0;
        for (int j = i; j < i + 4; ++j)
        {
            t = t * 2 + (output[j] - '0');
        }
        putchar(d2h[t]);
    }
}

int main()
{
    #ifdef LOCAL
    freopen("in.in", "r", stdin);
    freopen("out.txt", "w", stdout);
    #endif
    int cnt = 0;
    char buf[3];
    bool skf;
    while (scanf("%d%d%d", &d, &s, &b) && d)
    {
        fgets(buf, 2, stdin); //防止溢出,同样在强调,用getchar注意换行符,注意换行符,注意换行符
        skf = false;
        memset(exibs, 0, sizeof(exibs));
        flcnt = 0;
        printf("Disk set %d is ", ++cnt);
        check = (getchar() == 'E' ? 0 : 1);
        fgets(buf, 2, stdin);
        for (int i = 1; i <= d; ++i)
        {
            for (int j = 1; j <= b; ++j)
            {
                if (!get(i, j) && !skf) 
                {
                    printf("invalid.");
                    skf = true;
                }
            }
            fgets(buf, 2, stdin);
        }
        if (!skf)
        {
            for (int i = 1; i <= flcnt; ++i)
            {
                fix(flaw[i].df, flaw[i].bf, flaw[i].sf);
            }
            if (examine())
            {
                printf("valid, contents are: ");
                print();
            }
            else printf("invalid.");
        }
        /*#ifdef LOCAL
        for (int i = 1; i <= d; ++i)
        {
            for (int j = 1; j <= b; ++j)
                printf("%s", disk[i][j] + 1);
            putchar('\n');
        }
        #endif*/
        putchar('\n');
    }
}

一开始弄错了d和b的次序,这种变量多的题目容易搞混。。

字符数组的bug折腾了我好久,最后还是靠构造数据找出来了,只能说幸好这种题的结果正确与否比较明显。

构造数据的话首先要考虑极端情况,一般就是从数值上或是可能的情况上入手。(要是能想到所有情况还构造什么数据啊啊啊)也要尽可能让程序的每个部分都得以测试。

其次要考虑多组数据,有可能前面的数据会对后面造成影响,例如这题。。如果难以观察可以把数据分开测试,在合并测试。

上一篇:动画 | 什么是计数排序?


下一篇:L1-009 N个数求和 (20分)