Written by razrlele
15:19 December 12, 2014
Update0
刚刚才发现在另外一台电脑上面, 同样的程序, 同样的数据, 代码却是在pilecount == 33, i == 4的时候出现Segment Fault, 并且i最终变成的是18474…
Update1
1 2 3 4 |
char* top(int k)//返回每一堆牌顶端的牌 { return p[k].cards[p[k].num]; } |
首先是这个地方发现了问题, 字符数组是不可以这么返回的, 不过这个只是造成了程序运行结果的错误, 跟之前的Segment Fault没有关系.
另外问题就好像出现在strcpy上面, 把strcpy换成了自己构造的函数过后i值就没有出现异样.
后期自己构造的函数:
1 2 3 4 5 6 |
void cpycards(char* a, char* b) { a[0] = b[0]; a[1] = b[1]; return ; } |
Update2
突然发现是自己犯了一个非常低级的错误…
明明是需要储存两个字符的字符数组我却只分配了两个单位, 完全没有考虑’\0’君的感受, 然后应该就是strcpy君找不到’\0’君引发的一系列字节混乱, 然后就波及到了i君…
刚才在刷Uvaoj的时候的又写出了一段奇怪的代码, 这一次我不想像以前那样直接把代码全部推掉然后重新写过, 所以先在这里记录一下.
题目说明以及最终解题报告见 UVAOJ127
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
/* * File Name: uvaoj127.cpp * Author: razrLeLe * Mail: razrlele@outlook.com * Homepage: https://yueyu.io * Created Time: 2014年12月11日 星期四 17时24分35秒 */ #include "vector" #include "set" #include "deque" #include "queue" #include "algorithm" #include "functional" #include "iostream" #include "cstdio" #include "cmath" #include "cstdlib" #include "string" #include "cstring" #include "string.h" #include "map" #include "cctype" #define LOCAL const int maxn = 52; int pilecount; using namespace std; #define INF 0x3f3f3f3f struct pile//每一堆牌 { char cards[maxn+10][2];//字符串数组最后一个即为牌的顶端 int num; }p[maxn+10]; char* top(int k)//返回每一堆牌顶端的牌 { return p[k].cards[p[k].num]; } void pop(int k)//模拟stack pop { p[k].num--; return ; } void push(int k, char* a) { strcpy(p[k].cards[++p[k].num], a); return ; } int main() { #ifdef LOCAL freopen("/home/razrlele/build/data.txt", "r", stdin); freopen("/home/razrlele/build/out.txt", "w", stdout); #endif char tmp[2]; while(scanf("%s", tmp)) { if(tmp[0] == '#') break; strcpy(p[1].cards[1], tmp); p[1].num = 1; for(int i = 2; i <= maxn; i++) { scanf("%s", p[i].cards[1]); p[i].num = 1; } pilecount = maxn; bool moved = true; while(moved)//一直移动到不能移动为止 { int i; moved = false; for( i = 2; i <= pilecount; i++) { int pa = i-1, pb = i-3;//pa是左边第一张的下标, pb是左边第三张的下标 strcpy(tmp, top(i)); char tmpa[2]; strcpy(tmpa, top(pa)); if(pb > 0)//如果存在左边第三张则优先判断 { char tmpb[2]; strcpy(tmpb, top(pb)); if(tmp[1] == tmpb[1] || tmp[0] == tmpb[0]) { moved = true; pop(i); push(pb, tmp); break; } else if(tmp[1] == tmpa[1] || tmp[0] == tmpa[0]) { moved = true; pop(i); push(pa, tmp); break; } } else if(tmp[1] == tmpa[1] || tmp[0] == tmpa[0])//不存在左边第三张 { moved = true; pop(i); push(pa, tmp); break; } } if(p[i].num == 0 && moved)//如果当前堆为空则右边的堆必须全部左移 { for(int j = i+1; j <= pilecount; j++) { swap(p[j-1], p[j]); } //debug pilecount--; /* for(int j = 0; j < pilecount; j++) cout << " " << pile[j].top(); printf("\n"); */ } } printf("%d piles remaining:", pilecount); for(int i = 1; i <= pilecount; i++) { printf(" %d", (int)p[i].num); } printf("\n"); } return 0; } |
这段代码在直接运行的时候会报Segment Fault, 然后我使用gdb调试发现出错点在循环到pilecount == 39, 其中的for到了i == 6, 代码运行到86行
1 |
strcpy(tmpb, top(pb)); |
的时候i会十分诡异地由6变成21313, 进而导致运行到后面的时候程序会出现栈溢出的情况, 这里的关键点就在于出错代码段明明对i没有任何操作但是i的值却突然发生变化…
实在是难以想通…