【问题标题】:C - Split Slows Down My ComputerC - 分裂减慢我的电脑
【发布时间】:2016-09-19 11:01:34
【问题描述】:

我正在尝试编写一个拆分程序,该拆分程序接收一个包含多个单词的字符数组,并将每个单词分成它们自己的较小的字符数组。较小的字符数组的所有指针都保存在一个指针数组中,因此我可以返回一个双指针。

你能看看我的代码,看看你是否发现任何错误。当我尝试运行我的程序时,我的计算机逐渐变慢,3-4 秒后我无法移动鼠标或 alt+f4 我的编辑器。所以肯定有严重的问题!

而且我对 C 编程完全陌生,所以我肯定会犯一个愚蠢的错误。

char **split(char *s) {

char **result;
int wrd_cnt = 2; //I'm adding NULL at the end of the pointer-array.


//Counts the number of words to allocate memory for the pointer-array.
for(int i = 0; i < strlen(s); i++) {
    if(s[i] == ' ') {
        wrd_cnt++;
    }
}
result = malloc(wrd_cnt * sizeof(char*));

//Counts letters in each word to allocate memory for every single small char-array with malloc.
for(int i = 0; i < strlen(s); i++) {
    for(int j = 0; j < (wrd_cnt); j++) {
        int char_cnt = 0;
        for(int k = 0; s[i] != ' ' || s[i] != '\0'; k++, i++) {
            char_cnt++;
            result[j] = malloc(char_cnt * sizeof(char));
        }
    }
}

//Puts each word into their own place in the pointer array.
for(int i = 0; i < strlen(s); i++) {
    for(int j = 0; j < (wrd_cnt); j++) {
        for(int k = 0; s[i] != ' ' || s[i] != '\0'; k++, i++) {
            result[j][k] = s[i];
        }
    }
}

result[wrd_cnt-1] = NULL;
return result;
}

【问题讨论】:

  • s[i] != ' ' || s[i] != '\0' 应该是s[i] != ' ' &amp;&amp; s[i] != '\0',否则会超出字符串范围。
  • 应该考虑\t和\v
  • @AndreaBiondo 这不是意味着条件是 s[i] 既是 ' ' 又是 '\0' 来满足条件?这不可能?
  • @Magnarok 不,&amp;&amp; 你是说“如果字符不是空格 并且 不是 NUL 则循环”,而使用 || 你是说“如果字符不是空格不是NUL,则循环”。 s[i] != ' ' || s[i] != '\0'始终为真,因为s[i] != ' 's[i] != '\0' 之一将始终为真。所以你有一个无限循环。
  • 正如@user3121023 所说,result[j] = malloc(...) 应该在j 循环中,而不是在k 循环中。

标签: c arrays pointers split double-pointer


【解决方案1】:

在这种情况下,可以删除使用 j 和 k 的循环,而是在处理 s 数组时根据 i 循环递增和重置 i、j 和 char_cnt,类似于您在第一个循环中对 wrd_cnt 所做的操作

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

char **split(char *s);

int main ( void) {
    char **output = NULL;
    int each = 0;

    char line[99] = " string to   parse for words ";
    output = split ( line);

    each = 0;
    while ( output[each]) {
        printf ( "%s\n", output[each]);
        each++;
    }
    each = 0;
    while ( output[each]) {
        free ( output[each]);
        each++;
    }
    free ( output);

    exit ( 0);
}

char **split(char *s) {

    char **result;
    int wrd_cnt = 2; //I'm adding NULL at the end of the pointer-array.
    int char_cnt = 0;
    int i = 0;
    int j = 0;
    int k = 0;

    //Counts the number of words to allocate memory for the pointer-array.
    for(i = 0; i < strlen(s); i++) {
        if(s[i] == ' ') {
            wrd_cnt++;
        }
    }
    if ( ( result = malloc(wrd_cnt * sizeof(char*))) == NULL) {
        fprintf ( stderr, "malloc failure\n");
        exit ( 1);
    }
    //Counts letters in each word to allocate memory for every single small char-array with malloc.
    char_cnt = 1;
    j = 0;
    for( i = 0; i < strlen(s); i++) {
        if ( s[i] == ' ') {
            if ( ( result[j] = malloc(char_cnt * sizeof(char))) == NULL) {
                fprintf ( stderr, "malloc failure\n");
                exit ( 1);
            }
            j++;
            char_cnt = 1;
            continue;
        }
        char_cnt++;
    }
    if ( j == wrd_cnt - 2) {
        //allocate for last word
        if ( ( result[j] = malloc(char_cnt * sizeof(char))) == NULL) {
            fprintf ( stderr, "malloc failure\n");
            exit ( 1);
        }
        j++;
        result[j] = NULL;
    }
    result[wrd_cnt - 1] = NULL;//just to make sure the last pointer is null

    //Puts each word into their own place in the pointer array.
    j = 0;
    k = 0;
    for( i = 0; i < strlen(s); i++) {
        if ( s[i] == ' ') {
            result[j][k] = '\0';//for space only so [j][0] is '\0'
            k = 0;
            j++;
            continue;
        }
        result[j][k] = s[i];
        k++;
        result[j][k] = '\0';//for last word if there is no final space in s[]
    }
    return result;
}

【讨论】:

    【解决方案2】:

    除了上面的 cmets 之外,你的代码让我害怕,因为你做了所有 malloc() 调用,每个单词一个。这意味着您还必须释放每个单词。这会使程序容易发生内存泄漏。

    鉴于这是允许大量转换的 C,您可以使用单个 malloc 来保存 (char *) 指针数组和实际单词。

    char **split(char const *s) { char **结果; // 字符*目标; // 结果字符存储在哪里 size_t s_strlen = strlen(s); // s 的长度 int wrd_cnt = 2; //我在指针数组的末尾添加 NULL。 { 字符常量 *sx; for ( sx = s; sx = strpbrk( sx, " \t\n\r" ); sx++ ) { wrd_cnt++; } } 结果 = malloc( (wrd_cnt * sizeof(char *)) + s_strlen + 2 ); /* 允许 \0 和可能的 ' ' */ 目标 = (char *)(结果 + wrd_cnt); /* 保存单词的位置 */ strcpy(目标, s); /* 复制到已知足够大的目标 */ 如果 ( s_strlen > 0 && 目标[s_strlen-1] != ' ' ) strcat(目标 + s_strlen,“”); /* 保证以空格结尾 */ { 字符 *tx, *tnext; 诠释n; n = 0; 对于 ( tx = 目标; tnext = strpbrk( tx, " \t\n\r" ); tx = tnext + 1 ) { 结果[n++] = tx; /* 记住指针 */ *tnext = '\0'; /* 终止单词 */ } 结果[n] = NULL; /* 空终止 */ } 返回结果; }

    【讨论】:

      猜你喜欢
      • 2015-11-24
      • 2019-02-22
      • 1970-01-01
      • 1970-01-01
      • 2012-03-10
      • 1970-01-01
      • 2021-03-26
      • 2011-08-28
      相关资源
      最近更新 更多