0

我正在尝试使用 strtok 和动态数组创建拆分函数。但是,我不知道哪里出了问题:没有信息性错误消息。它确实说分段错误,但我不明白堆是如何损坏的或发生了什么原因。有人愿意向我解释什么是错的以及如何正确地做吗?

编辑 11:16 CST 代码:

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

char **toArray(char **array, char str[], char sep[], int *count);
char** my_split(const char* str, char delim, int* size);

int main(int argc, char* argv[]) {
    char* test = "Hello there lol";
    int *count = 0;
    char **array = malloc(sizeof(char*) * 5);
    toArray(array, test, " ", count);
    printf("Count: %d\n", *count);

    int array_i;
    for (array_i = 0; array_i < *count; array_i++) {
        printf("array %d: %s\n", array_i, array[array_i]);
        free(array[array_i]);
    }
    free(array);
    return 1;
}

char **toArray(char **array, char str[], char sep[], int *count) {
    char *temp = str;
    temp = strtok(temp, sep);
    array[0] = temp;
    *count = 1;
    while ((temp = strtok(NULL, sep)) != NULL ) {
        array[(*count)++] = temp;
    }
    return array;
}
4

2 回答 2

2

编译器消息是我们的朋友。我简单地用它们来追踪你的问题。 尝试以下操作,并将所做的与您所做的进行比较。特别注意指针变量的声明和使用... :)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char **toArray(char **array, char str[], char sep[], int *count);

int main(int argc, char* argv[]) {
    char test[] = "Hello there lol";
    int count = 0;
    char **array = malloc((sizeof(char*) * 5) +1); //added "+ 1" here, read why
    toArray(array, test, " ", &count);             //in comment below
    printf("Count: %d\n", count);

    int array_i;
    for (array_i = 0; array_i < count; array_i++) {
        printf("array %d: %s\n", array_i, array[array_i]);
        //free(array[array_i]);
    }
    getchar();
    free(array);
    return 1;
}

char **toArray(char **array, char str[], char sep[], int *count) {
    char *temp = str;
    temp = strtok(temp, sep);
    array[0] = temp;
    *count = 1;
    while ((temp = strtok(NULL, sep)) != NULL) {
        array[(*count)++] = temp;
    }
    return array;
}

[编辑]示例输出:
在此处输入图像描述

。该行char **array = malloc(sizeof(char*) * 5);,需要是 char **array = malloc(sizeof(char*) * 5 + 1); 因为“你好”实际上是 5 个字符加上一个 NULL 字符,'\0'

C 字符串的一些经验法则

1)使用 malloc 或 calloc 时,不要忘记为'\0'.

     `char *buf1;` //buffer needed to manipulate buf2  
     `char  buf2[]="someString";`  
     `buf1 = malloc(strlen(buf2)+1);` or `buf1 = malloc(sizeof(buf2));`    
                                         (note:, no '+1'.  see '4)' below. ) 

2)在使用前清除(初始化)新分配的变量。例如:

memset(buf, 0, strlen("someString")+1);  //preferred, all bytes are zeroed

或者

buf[0]=0;  //useful, but use with care (only first byte is zeroed.)  

3)完成后释放所有动态分配的内存。例如:

free(buf);   

4)使用strlen()函数或sizeof()宏。(在 中都很流行[mc]alloc()
给定:
char *buf1 ="Hello"; //6 个字符 |H|e|l|l|o|\0|
char buf2[] ="Hello"; //6 个字符 |H|e|l|l|o|\0|
char buf3[5]="Hello"; //5 个字符 |H|e|l|l|o|
char buf4[5]="Hel"; //4 个字符 |H|e|l|\0| |
char buf5[5]="Helloo";//应该得到编译错误,太多初始化器

比较strlen() - sizeof()结果:

strlen(buf1); //->5(在 malloc 中需要 +1 才能使新变量 req'd 保存“Hello\0”)
sizeof(buf1); //->4(返回 sizof (char *),而不是字符串中的 # 字符)

strlen(buf2); //->5(需要在 malloc 中 +1 才能获得新变量 req'd yo hold "Hello\0")
sizeof(buf2); //->6(计算所有字符,包括 '\0')

strlen(buf3); //-> (错误:字符串参数中缺少终止 NULL)
sizeof(buf3); //->5(计算所有字符,但此字符串中没有 '\0' - 错误!)

strlen(buf4); //->3(计算字符,但不包括 '\0')
sizeof(buf4); //->5(计算所有分配的空间,包括 '\0')

于 2013-10-13T04:20:11.327 回答
2

你正在传递char *test = "Hello there lol";给你的toArray(). 不幸的是,该字符串不可修改,因此当您尝试使用 修改它时strtok(),您会遇到分段错误。

最简单的解决方法是:

char test[] = "Hello there lol";

你还有:

int *count = 0;

你调用这个函数:

toArray(array, test, " ", count);

你需要一个整数,并传递它的地址:

int count = 0;
...
toArray(array, test, " ", &count);

您还试图释放由 in 中的元素指向的字符串array,但这些字符串从未分配过(它们是 string 的一部分test)。不要释放未分配给malloc()et al 的东西。

有了这些修复,这段代码就可以工作了:

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

char **toArray(char **array, char str[], char sep[], int *count);

int main(void)
{
    char test[] = "Hello there lol";
    int count = 0;
    char **array = malloc(sizeof(char *) * 5);

    toArray(array, test, " ", &count);
    printf("Count: %d\n", count);

    for (int i = 0; i < count; i++)
        printf("array %d: %s\n", i, array[i]);
    free(array);
    return 0;
}

char **toArray(char **array, char str[], char sep[], int *count)
{
    char *temp = str;
    temp = strtok(temp, sep);
    array[0] = temp;
    *count = 1;
    while ((temp = strtok(NULL, sep)) != NULL)
        array[(*count)++] = temp;
    return array;
}

输出:

Count: 3
array 0: Hello
array 1: there
array 2: lol
于 2013-10-13T04:26:29.513 回答