【问题标题】:Converting a comma separated string to array将逗号分隔的字符串转换为数组
【发布时间】:2021-12-18 13:26:00
【问题描述】:

我一直在尝试将字符串转换为整数、浮点数和字符数组。虽然我可以让它适用于整数和浮点数,但字符有一些问题。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    char *s1;
    int k, no=5;
    char* variable = "R1,R2,R3,R4,R5";
    void* value;

    s1 = calloc(no,sizeof(char)*81);
    for (k=0; k<no; k++) s1[k] = strdup(mchar);
    ListChar(variable, s1, no, ",");
    memcpy(value, s1, no*sizeof(char)*81);
    free(s1);

    int i;
    for (i = 0; i < no; i++)
        printf("%s", value[i]);
    printf("\n");
    return 0;
}

在我的头文件中

#define mchar "A...(81times)" 

实施:

int ListChar(char *buf, char *list, int maxloop, char* delim)
{
    int n = 0;
    char *s,*t;
    s= strdup(buf);
    t= strtok(s,delim);
    while ( t && (n<maxloop))
    {
        if (list!=NULL) list[n] =strdup(t);
        n++;
        t=strtok(NULL,delim);
    }
    free(s);
    return(n);
}

在 calloc 内存分配期间,当我观看 s1 它的 0xsomeadress "" 在for循环之后s1变成0xsomeadress "Garbage value 81 times"s1 分配给list 时,它仍然读取相同的垃圾值。 而当list [n] = strdup(t)list[0]读取第一块垃圾值比如-21 '\221 ṗ'

t 被正确分隔。我什至尝试初始化char *s1[81] = {"something"} 并在j 上循环它,但它不起作用,同样的问题,我需要在最后释放s1,因为这个函数运行了很多次。我通过list[n]=atoi(t) 为整数和浮点数做了它工作正常。谁能给我一些建议?

【问题讨论】:

  • 并确保为所需的终止'\0's预留空间
  • 如果你用未初始化的no 调用calloc,结果可能是任何东西。 strdup 返回一个char *,您将其分配给s1[k],这是一个char,然后看起来像随机垃圾(因为指针值通常被视为整数)。在继续之前尝试启用编译器警告并修复它们。
  • 你怎么知道这会失败?没有打印输出。请构造一个minimal reproducible example
  • 如果您没有看到s1[k] = strdup(mchar); 的错误消息,请更改您的编译器设置,因为您正在浪费时间尝试运行不正确的代码
  • 大家好,很抱歉定义中有错字,还有@klutt 我已经让我的代码可重现,因为之前它只是一个 sn-p

标签: arrays c string char delimiter


【解决方案1】:

对于字符串的工作方式似乎存在根本性的误解。您的s1 显然需要是char ** 并且strdup 的用法不正确。如果s1char * 类型,那么s1[k]char 类型。但是strdup 返回一个char *,所以s1[k] = strdup ... 显然是一个错误,你的编译器应该警告你。也许你想要这样的东西:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void * xmalloc(size_t s);

void
ListChar(const char *buf, char **list, int maxloop, int delim)
{
    char set[] = {delim, 0};
    for( int n = 0; n < maxloop; n += 1 ){
        size_t len = strcspn(buf, set);
        list[n] = xmalloc(len + 1);
        memcpy(list[n], buf, len);
        buf += len + 1;
    }
}

int
main(int argc, char **argv)
{
    int delim = ',';
    (void)argc; /* Suppress compiler warning */
    while( *++argv ){
        char **s1;
        int k, num = 1;
        char *input = *argv;
        for( const char *p = input; *p; p += 1 ){
            if( *p == delim ){
                num += 1;
            }
        }
        s1 = xmalloc(num * sizeof *s1);
        ListChar(input, s1, num, delim);
        for( int i = 0; i < num; i += 1 ){
            printf("%s\n", s1[i]);
        }
        free(s1);
    }
    return 0;
}


void *
xmalloc(size_t s)
{
    void *rv = malloc(s);
    if( rv == NULL ){
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    return rv;
}

请注意,上面的代码对每个字符串扫描两次,这并不理想。与其扫描字符串以查找分隔符的数量然后解析字符串,不如一次性完成这两项工作。但是为了演示如何分解字符串,这似乎是不必要的复杂性。 (虽然它实际上更简单,IMO)

【讨论】:

  • s1 之前它就像一个魅力,但是我不想打印,而是将s1 复制到另一个void* realvaluerealvalue 是一个链接到另一个头文件值的值,其中所有字符都定义为固定大小 81。所以如果我的输入是 m_item,即“A1、A2、A3、A4、A8、A9”,我试过了通过memcpy(realvalue, s1, size of *s1)s1 分配给realvalueitem[40][81]。我不能将realvalue 视为试图解除对通用指针的引用。但是,当我在代码末尾观看 item 时,它仅在 [0]、[1] 和直到 [2] 处显示一些垃圾值。但我的num/maxloop 设置为 40。
  • 进一步检查list[n] 也在复制一些垃圾值。例如。 if len = 21 list[1] = "21correctcharacters\210",","ibibiibib"
猜你喜欢
  • 1970-01-01
  • 2021-12-06
  • 1970-01-01
  • 2011-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-21
相关资源
最近更新 更多