我读到了关于指向tutorialsPoint的指针的指针。
我自己做了一点测试。我想按空格切片,以便每个单词(包括标点符号)都被视为一个标记,并且逐行返回标记。以下是代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char** split(const char* s)
{
int i = 0, j = 0;
char** word = malloc(strlen(s)+1);
* word = malloc(strlen(s)+1);
while (*s != '\0') {
if (*s == ' ') {
i++;
} else {
word[i][j] = *s;
j++;
}
i++;
s++;
}
return word;
//free(word); //with or without this i get the same outcome.
}
int main(void)
{
char** words = split("He said 'hello' to me!");
int i = 0;
while (words[i] != NULL) {
puts(words[i]);
free(words[i]);
i += 1;
}
free(words);
}
它编译,但当我在终端上运行时,我得到分段错误。我在if语句中添加了printf
,它会打印每个字母。
我也使用了valgrind
,但我无法理解它的含义。
预期产出:
He
said
'hello'
to
me!
答案 0 :(得分:1)
split
就是这样解决的。
char **split(const char *s){
int i = 0, j;
int len = strlen(s);
len += (len & 1);//+1 if len is odd
char **word = malloc((len / 2 + 1) * sizeof(*word));//+1 for NULL
while (*s) {
while(*s == ' ')
++s;//skip spaces
if(!*s)
break;
for(len = 0; s[len] && s[len] != ' '; ++len)
;
word[i] = malloc(len + 1);
for(j = 0; j < len; ++j)
word[i][j] = *s++;
word[i++][j] = '\0';
}
word[i] = NULL;
return word;
}
答案 1 :(得分:0)
首先,我会评论你的尝试:
下面:
return word;
free(word);
免费获胜不会被执行!你看到在<{em> return
语句之后的任何内容,都没有执行!
此外,使用malloc()
动态分配的空间是错误的,请检查我们如何在2D dynamic array中执行此操作,或/并阅读下面的示例。
你看,在没有分配足够的情况下,你正在访问超出内存,这将导致未定义的行为,但你很幸运得到一个分段错误,它会提醒你! :)
我不会调试你的代码,因为这是一个很好的练习机会,但如果你想要更多的话。
以下是我将如何做到这一点,这是一种更简单的方法,但如果你做到了,那么你就可以自己动手了! :)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// We return the pointer
char **get(int N, int M) // Allocate the array */
{
// TODO: Check if allocation succeeded. (check for NULL pointer)
int i;
char** table;
table = malloc(N*sizeof(char *));
for(i = 0 ; i < N ; i++)
table[i] = malloc( M*sizeof(char) );
return table;
}
void free2Darray(char** p, int N) {
int i;
for(i = 0 ; i < N ; i++)
free(p[i]);
free(p);
}
void zeroFill(char** p, int N, int M) {
int i, j;
for(i = 0 ; i < N ; i++)
for(j = 0 ; j < M ; j++)
p[i][j] = 0;
}
void print(char** p, int N, int M) {
int i;
for(i = 0 ; i < N ; i++)
if(strlen(p[i]) != 0)
printf("array[%d] = %s\n", i, p[i]);
}
void split(const char* s, char** words) {
int i = 0, word_idx = 0, char_idx = 0;
while(s[i] != '\0') {
if(s[i] != ' ') {
words[word_idx][char_idx++] = s[i];
} else {
word_idx++;
char_idx = 0;
}
++i;
}
}
int main(void)
{
char** words = get(10, 15); // 10 words, 14 chars max (+1 for n$
zeroFill(words, 10, 15);
split("He said 'hello' to me!", words);
print(words, 10, 15);
free2Darray(words, 10);
return 0;
}
输出:
C02QT2UBFVH6-lm:~ gsamaras$ nano main.c
C02QT2UBFVH6-lm:~ gsamaras$ gcc -Wall main.c
C02QT2UBFVH6-lm:~ gsamaras$ ./a.out
array[0] = He
array[1] = said
array[2] = 'hello'
array[3] = to
array[4] = me!
解释:
split()
。现在,让我再解释一下split()
函数:
实际上你的尝试非常好,所以你可能已经知道我在做什么了:
word_idx
让我记住了哪一个
我现在正在填写这个词,以及那个词的哪个特征
char_idx
。else
案例)时,我必须前进
下一个字(不需要NULL - 终止我填写的字符串
之前,因为我没有初始化我的2D数组),通过递增
word_idx
由1.我还将char_idx
设置为0,以便我可以开始
填写位置0的新单词。