arrays - 使用strtok在C中为这个结构分配空间的正确方法是什么
问题描述
我有一个包含我想从数组中填充的指针的结构,两者都在下面定义。我正在使用 strtok 拆分elements
数组中的字符串,然后获取各个值并将它们放入相关的结构值中。
我可以拆分字符串,但填充的值eleNum
是错误的。我似乎得到了一个指针值或类似的东西。我也不确定我对 3 个字段 ( eleNum, eleSym, eleName
) 的内存分配是否正确。他们为他们工作eleSym
,eleName
但我不知道这只是运气还是为他们分配空间的正确方式。
typedef struct PTdef {
int *eleNum;
char *eleSym;
char *eleName;
} ptDB;
int main(void)
{
ptDB pt[118] = {};
char elements[][40] = {"1,H,Hydrogen"};
char *token;
char *eleDup = (char *)malloc(40);
char sep[] = ",";
strcpy(eleDup, elements[0]);
token = strtok(eleDup, sep);
pt[0].eleNum = malloc(sizeof(int));
pt[0].eleSym = (char *)malloc(sizeof(token));
pt[0].eleName = (char *)malloc(strlen(token));
pt[0].eleNum = (int *)token;
token = strtok(NULL, sep);
strcpy(pt[0].eleSym, token);
token = strtok(NULL, sep);
strcpy(pt[0].eleName, token);
输出应该是。
pt[0].eleNum = 1.
pt[0].eleSym = H.
pt[0].eleName = Hydrogen.
解决方案
发布的代码有几个问题,请参阅下面内联的评论。
typedef struct PTdef { int *eleNum; char *eleSym; char *eleName; } ptDB; int main(void) { ptDB pt[118] = {}; char elements[][40] = {"1,H,Hydrogen"}; char *token; char *eleDup = (char *)malloc(40); // no need to cast the return of malloc // https://stackoverflow.com/questions/605845/ char sep[] = ","; strcpy(eleDup, elements[0]); token = strtok(eleDup, sep); // now 'token' points to nul-terminated "1" pt[0].eleNum = malloc(sizeof(int)); // 'eleNum' points to a newly allocated int pt[0].eleSym = (char *)malloc(sizeof(token)); // allocates sizeof(char*) bytes // typically 4 bytes in 32-bit // or 8 bytes in 64-bit compiles // regardless of contents of 'token' pt[0].eleName = (char *)malloc(strlen(token)); // allocates strlen("1") = 1 byte pt[0].eleNum = (int *)token; // discards the previous value of the pointer // so it leaks the malloc(sizeof(int)) memory // and forces 'eleNum' to point to string "1" // which is not an 'int' token = strtok(NULL, sep); // now 'token' points to "H" strcpy(pt[0].eleSym, token); // copies nul-terminated "H" // to oversized 4- or 8-byte buffer token = strtok(NULL, sep); // now 'token' points to "Hydrogen" strcpy(pt[0].eleName, token); // copies nul-terminated "Hydrogen" // to 1-byte buffer, which overruns it
使其尽可能接近原始代码,以下代码将正常工作。
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct PTdef {
int eleNum; // store value, not pointer
char *eleSym;
char *eleName;
} ptDB;
int main()
{
ptDB pt[118] = {};
char elements[][40] = {"1,H,Hydrogen"};
char *token;
char eleDup[40]; // no need for dynamic allocation here
char sep[] = ",";
strcpy(eleDup, elements[0]);
token = strtok(eleDup, sep);
pt[0].eleNum = atoi(token); // convert string "1" to integer 1
token = strtok(NULL, sep);
pt[0].eleSym = strdup(token); // or: pt[0].eleSym = malloc(strlen(token) + 1);
// strcpy(pt[0].eleSym, token);
token = strtok(NULL, sep);
pt[0].eleName = strdup(token);
printf("num %d, sym '%s', name '%s'\n", pt[0].eleNum, pt[0].eleSym, pt[0].eleName);
free(pt[0].eleName); // cleanup
free(pt[0].eleSym);
return 0;
}
留给OP填写:
strdup
应检查返回值以捕获内存不足的情况;strtok
应检查返回值以捕获格式错误的字符串;atoi
不报告错误,请参阅为什么我不应该使用 atoi()?并使用 strtol代替。
推荐阅读
- c# - 无法修改 WebRequest 的代理凭据
- vue.js - 我想隐藏我的 API 密钥,但我想同时在 GitHub 页面部署中使用这些密钥
- python-3.x - 解决预算规划师的问题(学校项目)
- java - 字段注入与构造函数注入 - 它对我编写单元测试的方式有何影响?
- nginx - 启用“httpd_can_network_connect”后,将其用作 Grafana 的反向代理时发生 Nginx Bad Gatway 错误
- reactjs - 使用带有动态数据的网格
- amazon-web-services - 无法删除的 EC2 经典资源 - 现在怎么办?
- javascript - 属性分配的Javascript不起作用
- typescript - node_module 中的类型文件夹
- c - 标识符未定义(在 C 中)