我忘记了大部分的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;将在我运行数组时显示。
答案 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;
}