当我编写简单的代码来将简单的字母序列编码为字节并再次解码时,我遇到了解码问题。一切都在完成我想要有4个字符的序列,但它也包括最后的字节。这是我的代码:
char* B2T(int num) {
unsigned char temp;
char res[4];
int sw[] = { 6,4,2,0 };
char tab[4] = { 'A', 'C', 'G', 'T' };
int i = 0;
for (int i = 0; i < 4; i++) {
res[i] = tab[(num >> sw[i]) & 3];
}
printf_s("%s\n", res); //!!!!!!problem here!!!!!!!!
return res;
}
int main() {
FILE *I, *O;
char tab[5], opt;
int res, i, temp;
bool work = true;
while (work) {
printf_s("\nChoose option: decode or encode (d/e): ");
scanf_s("%c", &opt);
switch (opt) {
case 'e':
fopen_s(&I, "DNA.txt", "r");
fscanf_s(I, "%s", &tab, 5);
fopen_s(&O, "result.bin", "a");
while (feof(I) == 0) {
res = T2B(tab);
printf_s("%X ", res);
fprintf_s(O, "%X ", res);
fscanf_s(I, "%s", &tab, 5);
};
fclose(I);
fclose(O);
break;
case 'd':
fopen_s(&I, "result.bin", "r");
fscanf_s(I, "%X", &temp);
while (feof(I)==0) {
char* ress = B2T(temp);
fscanf_s(I, "%X", &temp);
}
fclose(I);
break;
}
}
return 0;
}
答案 0 :(得分:3)
您填充char res[4];
,而不会使其终止,从而导致未定义行为,因为printf()
期望空终止符号停止打印。
改为:
char res[5];
res[4] = '\0';
此外,你应该专注于这一行:
while (feof(I) == 0)
在循环中使用feof()
来停止解析文件。这是一个已知问题,它解释了您的额外角色。请阅读Why is “while ( !feof (file) )” always wrong?
PS:一般来说,C库的所有函数都希望字符串以空值终止,因此强烈建议将所有字符串以空值终止。
答案 1 :(得分:2)
Oups!其他人已经说错误的输出是由一个char数组引起的,不是以null结尾。
但是你的代码包含另一个(更严重的恕我直言)缺陷:你从一个函数返回一个自动数组:
char* B2T(int num) {
unsigned char temp;
char res[4]; // <- res will reach end of life when function returns
...
return res;
}
int main() {
FILE *I, *O;
char tab[5], opt;
int res, i, temp;
...
res = T2B(tab); // <- res is a dangling pointer converted to int
...
在数组到达生命周期结束后使用指向数组的指针是明确的未定义行为。在通常的实现中,自动数组存储在堆栈中,并且在函数返回之后可以重用其存储器,从而导致意外的更改。谷歌的 C悬空指针以获取更多参考资料......
快速解决方法是将其声明为静态,这可以接受,因为您既不使用递归也不使用多线程:
char* B2T(int num) {
unsigned char temp;
static char res[5]; // <- res will persist after function returns
答案 2 :(得分:1)
您的res
未终止。
将其更改为:
char res[5];
res[4] = '\0';
然后printf
将正确打印。