【问题标题】:Implementing a C function that splits a string on a given character and returns an array of strings after the split (along with length of array)实现一个 C 函数,在给定字符上拆分字符串并在拆分后返回一个字符串数组(以及数组的长度)
【发布时间】:2020-05-31 00:00:11
【问题描述】:

我正在尝试实现一个 C 函数,该函数接受一个字符串,然后在某个字符上打破该字符串,并在拆分后返回一个字符串数组以及该数组的大小。我为此使用了一个数据结构,因为返回一个二维数组(拆分后的字符串数组)并且它的长度是不可能的。我的代码如下:

struct charArr {
    char *arr[10000];
    int size;
};    

struct charArr *stringSplitter(char *str, char c) {
    struct charArr *splitString = (struct charArr *)malloc(sizeof(struct charArr));
    if (splitString == NULL) {
        fprintf(stderr, "malloc failed\n");
        exit(1);
    }
    splitString->size = 0;
    int i = 0;
    int j = 0;

    while (str[i] != '\0') {
        if (str[i] == c) {
            splitString->arr[splitString->size][j] = '\0';

            (splitString->size)++;
            j = 0;
            i++;

            while (str[i] == c) {    /* this loop is to ignore continuous occurrences of the character c */
                i++;
            }
        } else {
            splitString->arr[splitString->size][j] = str[i];
            i++;
            j++;
        }
    }
    splitString->arr[splitString->size][j] = '\0';
    return splitString;
}

int main(int argc, char *argv[]) {

    // take input from command line
    if (argc == 1) {
        //buffer to store lines
        size_t buffer_size = 128;
        char *buffer = malloc(buffer_size * sizeof(char));
        if (buffer == NULL) {
            fprintf(stderr, "malloc failed\n");
            exit(1);
        }

        // loop continuously till user exits by ctrl+c
        while (1) {
            printf("Enter Input> ");
            getline(&buffer, &buffer_size, stdin);

            char *str = strdup(buffer);

            struct charArr *splitString = stringSplitter(str, '&');

            for (int i = 0; i<splitString->size; i++) {
                printf("%s ", splitString->arr[i]);
            }
        }
    }
    return 0;
}

在一个简单的输入上运行代码,例如(输入连续从命令行获取):

输入输入>这个&那个

我希望输出是:

这个

但是,我得到了错误:

分段错误(核心转储)

如果输入如下图(即连续出现分割字符):

输入输入>这个&&&那个

那么输出也必须是:

这个

编辑: 我正在尝试扩展它以在多个分隔符上拆分一个字符串(一次),所以在上面的函数中代替 char c , 如果 char *c 被传递,它是一个分隔符字符串(例如 c = " \t\n" 从给定字符串中删除所有空格),那么它也是应该按预期工作并在数组的拆分和长度之后返回一个字符串数组。 例如,如果输入是(多个空格、制表符和换行符):

Enter Input>      this                               that         

那么返回的数组(它是返回结构的一部分)的大小必须为 2,并且只包含 2 个字符串 - “this”和“that”。

【问题讨论】:

  • 您在结构中的指针指向任何地方,因为您没有设置任何值,然后您尝试取消引用它们。这是未定义的行为,可能导致任何事情发生,包括经常出现段错误。
  • @SamiKuhmonen 我可以知道我需要对我的代码进行哪些更改吗?我对编程很陌生,不完全理解如何根据您的评论修复我的代码。
  • 你需要为你正在写的字符串分配内存。目前,您只为指针分配内存,而不是为它们应该指向的内容分配内存
  • 你的意思是,你正在尝试重新实现strtok?
  • @Peter-ReinstateMonica 我正在尝试实现一个函数,该函数将返回在给定字符上拆分的字符串数组(以及数组的大小)。所以实际上它是 strtok 函数的一种变体。

标签: c arrays shell


【解决方案1】:

这是对函数的重写,其中包含使用 strdup() 正确分配每个找到的字符串所需的更正:

您可以找到我的修改前面带有以“以前”开头的 cmets:

struct charArr* stringSplitter(char *str, char c){
    struct charArr* splitString = (struct charArr*)malloc(sizeof(struct charArr));
    char buffer[ MAX_BUFF ] ;
    if(splitString == NULL){
        fprintf(stderr, "malloc failed\n");
        exit(1);
    }
    splitString->size = 0;
    int i=0;
    int j=0;

    while(str[i] != '\0'){

        if(str[i] == c){
            //Previously:  splitString->arr[splitString->size][j] = '\0';
            splitString->arr[splitString->size] = strndup( buffer , j ); 

            (splitString->size)++;
            j = 0;
            i++;

            while(str[i] == c){    /* this loop is to ignore continuous occurrences of the character c */
                i++;
            }
        } else {
            // Previously:  splitString->arr[splitString->size][j] = str[i];
            buffer[j] = str[i];
            i++;
            j++;
        }

    }
    //Previously:  splitString->arr[splitString->size][j] = '\0';
    splitString->arr[splitString->size++] = strndup( buffer , j ); 
    return splitString;
}

【讨论】:

    【解决方案2】:

    我已经很久没有写过任何 C 语言了,所以我认为这将是一个挑战。这是 stringSplitter 函数的重写。

    struct charArr* stringSplitter(char *str, char c){
        struct charArr* splitString = (struct charArr*)malloc(sizeof(struct charArr));
        if(splitString == NULL){
            fprintf(stderr, "malloc failed\n");
            exit(1);
        }
        splitString->size = 0;
        char sep[2];
        sep[0] = c;
        sep[1] = (char) 0;
    
        char* next;
        while( (next = strtok( str, sep )) )
        {
          str = NULL;
          splitString->arr[ splitString->size++ ] = next;
        }
    
        return splitString;
    }
    

    以上,我只是使用strtok。查看 strtok() 的手册页以了解其细微差别。

    【讨论】:

      猜你喜欢
      • 2019-06-13
      • 2023-03-10
      • 2018-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多