微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用strtok

如何解决使用strtok

我有一个结构,其中包含我想从数组中填充的指针,这两个都在下面定义。我正在使用strtok在elements数组中拆分字符串,然后获取各个值并将其放入相关的结构值中。

我可以将字符串ok拆分,但是填充到eleNum中的值是错误的。我似乎正在获得一个指针值或类似的东西。我也不确定3个字段(eleNum,eleSym,eleName)的内存分配是否正确。它们适用于eleSymeleName,但我不知道这是运气还是为它们分配空间的正确方法

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,Hydrogen"};
    
    char    *token;
    char    eleDup[40];               // no need for dynamic allocation here
    char    sep[] = ",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不报告错误,请参见Why shouldn't I use atoi()?并使用strtol

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。