2D指针到2D指针

时间:2014-09-11 20:46:07

标签: c arrays pointers 2d

我忘记了大部分的C,所以如果这是一个愚蠢的问题,请原谅我。因为我需要将一串单词分成单个单词。

#include "argsInfo.h"
#include <stdlib.h>

/* Parses string argument which contains words
 * separated by whitespace.  It returns an
 * argsInfo data structure which contains an
 * array of the parsed words and the number
 * of words in the array.
 */

argsInfo getArgsInfo(char * string) {
    argsInfo info;
    char ** temp;
    int nWords=1;
    int i=0;
    int j,k;
    //Test if the the input string is empty
    if (string[0] == '\0'){
        nWords=0;
    }else{
        //First I need to check how long the input String is, as-well as cout how many words are in the string.
        while (string[i] != '\0'){
            if (string[i] == ' '){
               nWords++;
            }
            i++;
        }
    }
    //This allocates enough memory for each word.
    temp = (char**) malloc(nWords*sizeof(char*));

    for (j=0;j<nWords;j++){
        temp[j] = (char*) malloc(i*sizeof(char));
    }
    j=0;
    k=0;
    // If I encounter a white space, it signifies a new word, and I need to move it to the next element
    while (j < i){
        if (string[j] == ' '){
            k++;
        }
        temp[k][j] = string[j];
        j++;
    }
    info.argc = nWords;
    info.argv = temp;
    return info;
}

第3个最后一个LINE。那就是我认为问题所在。 info.argv = temp;

这就是结构的样子:

 typedef struct {
    int argc;
    char ** argv;
 } argsInfo;

示例输入和输出:

输入:&#34; ax bcd efghij&#34;

输出:ax

如果删除k ++行,输出变为:ax bcd efghij

同样,如果我输入一个b c。只有&#39; a&#39;将在我运行数组时显示。

2 个答案:

答案 0 :(得分:2)

首先,这部分效率低下但有效:

for (j=0;j<nWords;j++){
    temp[j] = (char*) malloc(i*sizeof(char));
}

您正在使用i的值,该值将等于原始输入字符串中的字符总数。这意味着对于每个单独的单词,您分配的空间足以存储原始句子,这是浪费空间。 例如,当你计算单词时,你也可以记住迄今为止看到的最长的单词,并将其用作分配因子,这可能远远小于整个句子。我们从1开始长度以包含终止字符'\0'

int longest = 1;
int tempLength = 1;
//Test if the the input string is empty
if (string[0] == '\0'){
    nWords=0;
}else{
    //First I need to check how long the input String is, 
    //as-well as count how many words are in the string.
    while (string[i] != '\0'){
        if (string[i] == ' '){
           if(tempLength > longest) {
               longest = tempLength;
           }
           nWords++;
        } else {
            tempLength++; // count characters of current word
        }
        i++;
    }
}

for (j=0;j<nWords;j++){
    temp[j] = (char*) malloc(longest*sizeof(char));
}

最后,代码的最后一部分需要修复。它不起作用,因为您在整个句子中使用j作为索引,在单个单词中使用索引作为索引。您永远不会重置j。 让我们说第一个单词是

apple

一旦遇到空格,您将拥有:

j = 5
temp[0] = "apple"

现在您将k增加到1,但j保持不变,因此您将开始存储位置5而不是0的下一个字的字符:

temp[1][5] = string[5];

而不是:

temp[1][0] = string[5];

因此,您需要担心3个索引:

  • 迭代输入字符串的索引a
  • 索引b迭代字符串的单个单词。
  • 索引c迭代单词数组。

代码:

int a, b, c;
for(a = 0, b = 0, c = 0; a < i; a++) {  // index i holds the total number of chars in input string
    if(string[a] != ' ') {
        temp[c][b] = string[a];
        b++;
    } else {
        temp[c][b] = '/0'; // add terminating character to current word
        b = 0;
        c++;
    }
}
info.argc = nWords;
info.argv = temp;
return info;

答案 1 :(得分:2)

很确定这就是你所追求的。这应该只需要扫描字符串一次。您的索引数学有几个问题:

  • 您对i的计算效率低下。
  • nWords似乎经历了疑问
  • 您似乎没有兴趣终止每个单词,非常错误。

也就是说,在调试器中仔细浏览以下 very 以了解它是如何工作的。

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

argsInfo getArgsInfo(const char * s)
{
    argsInfo info = {0,NULL};

    while (*s)
    {
        // find start of next word
        while (*s && isspace((unsigned char)*s))
            ++s;

        // find end of next word
        const char *beg = s;
        while (*s && !isspace((unsigned char)*s))
            ++s;

        if ((s - beg) > 0)
        {
            char **tmp = realloc(info.argv, (info.argc+1)*sizeof(*tmp));
            if (tmp)
            {
                info.argv = tmp;
                tmp[info.argc] = malloc((s - beg + 1) * sizeof(char));
                if (tmp[info.argc] != NULL)
                {
                    memcpy(tmp[info.argc], beg, s-beg);
                    tmp[info.argc++][s-beg] = 0; // <<= TERMINATE
                }
                else
                {
                    perror("Failed to allocate string");
                    exit(EXIT_FAILURE);
                }
            }
            else
            {
                perror("Failed to expand string pointer array");
                exit(EXIT_FAILURE);
            }
        }
    }
    return info;
}