无法从 C 中的结构打印字符串
Can´t print a String from a structure in C
typedef struct listaDocente nodoDocente;
struct listaDocente{ //teacherList
char Rut[12]; //ID
char Nombre[50]; //Name
char Correo[70]; //Email
char Cod_Curso[6]; //Grade_Code
char Asignatura[15]; //Grade_Name
nodoDocente *siguiente; //Next (Node)
};
int main(){
nodoDocente *D = ((nodoDocente * )malloc(sizeof(nodoDocente)));
strcpy(D->Nombre, "Charlie");
strcpy(D->Rut, "18123456");
strcpy(D->Asignatura, "EDD");
strcpy(D->Cod_Curso, "INS123");
strcpy(D->Correo, "charlie@test.com");
printf("%s\n", D->Nombre);
printf("%s\n", D->Rut);
printf("%s\n", D->Asignatura);
printf("%s\n", D->Cod_Curso);
printf("%s\n", D->Correo);
return 0;
}
首先,抱歉,如果有些词是西班牙语。
我试图打印这些值,但我得到了一个空白 space。
Charlie
18123456
INS123
charlie@test.com
它应该在哪里打印出 EDD,就像这样。
Charlie
18123456
EDD
INS123
charlie@test.com
不要忘记 C 中的字符串总是有一个尾随 [=13=]
字符。所以你的:
INS123
写成
INS123[=11=]
它的长度是 7 个字符,而不是 6。所以你所做的是在 Asignatura
的第一个字符上写一个额外的 [=13=]
,因此它的长度变为 0。
要解决此问题,您应该声明 Cod_Curso
足够:
char Cod_Curso[7]; //Grade_Code
您已声明:
char Cod_Curso[6];
并用 :
填充
strcpy(D->Cod_Curso, "INS123");
但是 INS123
后跟字符串的终止字符 [=15=]
。因此,字符串 INS123
并不是您想象的 6
个字符,而是实际上占据了 7
个字符。因此,您不能期望语句 :
printf("%s\n", D->Asignatura);
以在您使用上一行调用 undefined-behavior 时正常工作。
解决方案:声明Cod_Curso
大小为7
(或更多),像这样:
char Cod_Curso[7];
还有,看看这个link on why not to cast the result of malloc。
一个字符串需要一个额外的字节来存储 [=11=]
这使得一个字符数组被视为字符串。你在这里违反了这条规则,
char Cod_Curso[6];
strcpy(D->Cod_Curso, "INS123");
这会将 [=11=]
覆盖到分配给其他变量的内存,这会导致代码中出现 UB。
如果您确定每个字符串的长度,您可以为您的 char 数组使用一个精确定义的长度,或者您可以将它们全部声明为 char*
并 malloc 每个来存储您提供的字符串或为所有人提供足够的数组长度 (buffer
)。
此外,您的代码中存在内存泄漏。您应该 free
使用 malloc
、calloc
和 realloc
分配的内存。
malloc
returns void*
隐式提升为 C 中的任何其他指针类型,因此您无需转换 malloc
.
您已使用 strcpy
将 INS123
复制到 Cod_Curso[6]
。现在 strcpy
从 src 读取直到它看到 '\0' 并将读取的内容(包括 '\0')复制到 dest
。因此这里 7 个字符将被复制到 Cod_Curso
.
指向的缓冲区
问题来了。目标缓冲区中分配的 space 只有 6 个字符。因此,将 7 个字符复制到其中将导致缓冲区溢出,即额外的字符将被复制到不属于 Cod_Curso
的内存中,而是复制到堆栈中它上面的变量中,这里是 Asignatura[15]
。所以现在额外的字符 '\0' 被复制到 Asignatura[0]
.
现在 printf
和 '%s'
打印,直到它在传递的缓冲区中看到 '[=21=]'
。由于 Asignatura[0]
是 '[=21=]'
,因此打印了一个空字符串。
解决方案
最好使用 strcpy
的安全版本,例如 strncpy。或者您可以增加缓冲区大小。
typedef struct listaDocente nodoDocente;
struct listaDocente{ //teacherList
char Rut[12]; //ID
char Nombre[50]; //Name
char Correo[70]; //Email
char Cod_Curso[6]; //Grade_Code
char Asignatura[15]; //Grade_Name
nodoDocente *siguiente; //Next (Node)
};
int main(){
nodoDocente *D = ((nodoDocente * )malloc(sizeof(nodoDocente)));
strcpy(D->Nombre, "Charlie");
strcpy(D->Rut, "18123456");
strcpy(D->Asignatura, "EDD");
strcpy(D->Cod_Curso, "INS123");
strcpy(D->Correo, "charlie@test.com");
printf("%s\n", D->Nombre);
printf("%s\n", D->Rut);
printf("%s\n", D->Asignatura);
printf("%s\n", D->Cod_Curso);
printf("%s\n", D->Correo);
return 0;
}
首先,抱歉,如果有些词是西班牙语。 我试图打印这些值,但我得到了一个空白 space。
Charlie
18123456
INS123
charlie@test.com
它应该在哪里打印出 EDD,就像这样。
Charlie
18123456
EDD
INS123
charlie@test.com
不要忘记 C 中的字符串总是有一个尾随 [=13=]
字符。所以你的:
INS123
写成
INS123[=11=]
它的长度是 7 个字符,而不是 6。所以你所做的是在 Asignatura
的第一个字符上写一个额外的 [=13=]
,因此它的长度变为 0。
要解决此问题,您应该声明 Cod_Curso
足够:
char Cod_Curso[7]; //Grade_Code
您已声明:
char Cod_Curso[6];
并用 :
填充strcpy(D->Cod_Curso, "INS123");
但是 INS123
后跟字符串的终止字符 [=15=]
。因此,字符串 INS123
并不是您想象的 6
个字符,而是实际上占据了 7
个字符。因此,您不能期望语句 :
printf("%s\n", D->Asignatura);
以在您使用上一行调用 undefined-behavior 时正常工作。
解决方案:声明Cod_Curso
大小为7
(或更多),像这样:
char Cod_Curso[7];
还有,看看这个link on why not to cast the result of malloc。
一个字符串需要一个额外的字节来存储 [=11=]
这使得一个字符数组被视为字符串。你在这里违反了这条规则,
char Cod_Curso[6];
strcpy(D->Cod_Curso, "INS123");
这会将 [=11=]
覆盖到分配给其他变量的内存,这会导致代码中出现 UB。
如果您确定每个字符串的长度,您可以为您的 char 数组使用一个精确定义的长度,或者您可以将它们全部声明为 char*
并 malloc 每个来存储您提供的字符串或为所有人提供足够的数组长度 (buffer
)。
此外,您的代码中存在内存泄漏。您应该 free
使用 malloc
、calloc
和 realloc
分配的内存。
malloc
returns void*
隐式提升为 C 中的任何其他指针类型,因此您无需转换 malloc
.
您已使用 strcpy
将 INS123
复制到 Cod_Curso[6]
。现在 strcpy
从 src 读取直到它看到 '\0' 并将读取的内容(包括 '\0')复制到 dest
。因此这里 7 个字符将被复制到 Cod_Curso
.
问题来了。目标缓冲区中分配的 space 只有 6 个字符。因此,将 7 个字符复制到其中将导致缓冲区溢出,即额外的字符将被复制到不属于 Cod_Curso
的内存中,而是复制到堆栈中它上面的变量中,这里是 Asignatura[15]
。所以现在额外的字符 '\0' 被复制到 Asignatura[0]
.
现在 printf
和 '%s'
打印,直到它在传递的缓冲区中看到 '[=21=]'
。由于 Asignatura[0]
是 '[=21=]'
,因此打印了一个空字符串。
解决方案
最好使用 strcpy
的安全版本,例如 strncpy。或者您可以增加缓冲区大小。