你能帮忙吗?当我执行此代码时,我会收到:AAAAA BBBBB CCCC BBBBB COMP┐╔长度31字母后面有一些奇怪的字符,而我只分配了21个字节。
#include <stdio.h>
#include <stdlib.h>
char * lineDown(){
unsigned short state[4] = {0,1,2,1};
char decorationUp[3][5] = {
{"AAAAA"},{"BBBBB"},{"CCCCC"}
};
char * deco = malloc(21);
int k;
int p = 0;
for(int j = 0; j < 4; j++){
k = state[j];
for(int i = 0; i < 5; i++){
*(deco+p) = decorationUp[k][i];
p++;
}
}
return deco;
}
int main(void){
char * lineDOWN = lineDown();
int k = 0;
char c;
do{
c = *(lineDOWN+k);
printf("%c",*(lineDOWN+k));
k++;
}while(c != ' ');
printf("LENGTH %dnn",k);
}
函数不生成字符串,因为结果数组不包含终止零,尽管在分配数组时为其保留了空间。
char * deco = malloc(21);
因此,在退出函数之前,您需要在数组中添加终止零
//...
*(deco + p ) = ' ';
return deco;
}
否则,循环时执行此操作
do{
c = *(lineDOWN+k);
printf("%c",*(lineDOWN+k));
k++;
}while(c != ' ')
将具有未定义的行为。
但是,即使您将使用终止零来附加数组,循环也会错误地计算存储字符串的长度,因为即使当前字符是终止零,它也会增加变量k。
相反,您应该使用while循环。在这种情况下,变量c
的声明将是多余的。环路可能看起来像
while ( *( lineDOWN + k ) )
{
printf("%c",*(lineDOWN+k));
k++;
}
在这种情况下,此调用
printf("nLENGTH %dnn",k);
^^
将输出等于CCD_ 2的字符串的正确长度。
在退出程序之前,您应该释放分配的内存
free( lineDOWN );
正如其他一些人在回答中所写的那样,数组decorationUp
必须像一样声明
char decorationUp[3][6] = {
{"AAAAA"},{"BBBBB"},{"CCCCC"}
};
那么,如果您不打算将数组的元素用作字符串,并且在程序中没有将它们用作字符串,则没有必要这样做。
考虑到你的程序充满了神奇的数字。这样的程序通常容易出错。相反,您应该使用命名常量。
在中
char decorationUp[3][5] = {
{"AAAAA"},{"BBBBB"},{"CCCCC"}
};
您的字符串还需要6个字符来放置null字符,即使在这种情况下,您也不将它们用作"标准"字符串,而仅使用字符数组。要养成这个习惯,总是颠倒结尾空字符的位置
你可以做
char decorationUp[3][6] = {
{"AAAAA"},{"BBBBB"},{"CCCCC"}
};
注意,给出第一个大小是没有用的,编译器会为你计算
因为在main中,当您读取null字符时会停止,您还需要将其放在deco的末尾,因此您需要为其分配21。与之前一样,您错过了null字符的位置,但在这里,这会产生未定义的行为,因为您在分配的块之后读取。
要执行*(deco+p)
不可读,请执行deco[p]
例如:
char * lineDown(){
unsigned short state[] = {0,1,2,1};
char decorationUp[][6] = {
{"AAAAA"},{"BBBBB"},{"CCCCC"}
};
char * deco = malloc(4*5 + 1); /* a formula to explain why 21 is better than 21 directly */
int k;
int p = 0;
for(int j = 0; j < 4; j++){
k = state[j];
for(int i = 0; i < 5; i++){
deco[p] = decorationUp[k][i];
p++;
}
}
deco[p] = 0;
return deco;
}