By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,173 Members | 1,686 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,173 IT Pros & Developers. It's quick & easy.

How to Return an array of strings in C (char**)

P: n/a
I am trying to implement the Split function in C ie.
if i have a string: char* S="This is a test";
and if i try to split based on space ' ' it should return an array of
strings like:

{"This","is","a","test"} .

I tried to implement it as given below but am getting a segmentation
fault. I would really appreciate if some one could give me an answer
on this issue:

char** split(char str[],int*c) {
int start=0;
int end =0 ;
char** temp=NULL;
char** ptr;
int count=0;
int length = strlen(str);
//first counting the number of spaces
// to know the number of elements in the array
while (str) {
if (*str==' ') count++;
}
printf("count value is %d \n",count);
// I am doubt ful about the malloc too
ptr = (char**) malloc(sizeof(char)*(count+1));
*c = count+1;

while(end<length) {
ptr = str + start;
if (str[end]!=' ' || length) {
end++;
}
if (str[end]!='\0') {// replacing spaces with \0
str[end]='\0';
}
if (!temp) temp= ptr;
ptr++;
}
return temp;
}

Thanks

Mar 25 '07 #1
Share this Question
Share on Google+
10 Replies


P: n/a
<vi*******@gmail.comwrote:
>I am trying to implement the Split function in C ie.
if i have a string: char* S="This is a test";
and if i try to split based on space ' ' it should return an array of
strings like:

{"This","is","a","test"} .

I tried to implement it as given below but am getting a segmentation
fault. I would really appreciate if some one could give me an answer
on this issue:

char** split(char str[],int*c) {
int start=0;
int end =0 ;
char** temp=NULL;
char** ptr;
int count=0;
int length = strlen(str);
//first counting the number of spaces
// to know the number of elements in the array
while (str) {
if (*str==' ') count++;
}
printf("count value is %d \n",count);
// I am doubt ful about the malloc too
ptr = (char**) malloc(sizeof(char)*(count+1));
*c = count+1;

while(end<length) {
ptr = str + start;
if (str[end]!=' ' || length) {
end++;
}
if (str[end]!='\0') {// replacing spaces with \0
str[end]='\0';
}
if (!temp) temp= ptr;
ptr++;
}
return temp;
}
I am not a fan of coding where the malloc and free are in different
functions unless there is a good reason to do so. So I would not return
anything (return void) from split: have the caller allocate the space, tell
split where the space is, modify it in place and have the caller be
responsible for doing the free. If this is a learning exercise, you will
have to make the array you are trying to return static. I hope the
information you need to continue is in the link to the FAQ, if not post
another question.

http://c-faq.com/~scs/cgi-bin/faqcat.cgi?sec=aryptr
Mar 25 '07 #2

P: n/a

<vi*******@gmail.comwrote in message
>I am trying to implement the Split function in C ie.
if i have a string: char* S="This is a test";
and if i try to split based on space ' ' it should return an array of
strings like:

{"This","is","a","test"} .

I tried to implement it as given below but am getting a segmentation
fault. I would really appreciate if some one could give me an answer
on this issue:

char** split(char str[],int*c) {
int start=0;
int end =0 ;
char** temp=NULL;
char** ptr;
int count=0;
int length = strlen(str);
This must be where you crashed, if you cut and pasted this code. The input
must be null or not set up correctly.
>
//first counting the number of spaces
// to know the number of elements in the array
while (str) {
if (*str==' ') count++;
}
The reason is that you fail to increment str. Unless input is an empty
string, this will run forever. Since the program didn't hang, probably the
crash was above.
>
printf("count value is %d \n",count);
// I am doubt ful about the malloc too
ptr = (char**) malloc(sizeof(char)*(count+1));
you want (count + 1) * sizeof(char *).
It is an array of pointers, not of chars.
>
*c = count+1;

while(end<length) {
*ptr = str + start.
ptr = str + start;
What is length doing in this condition ?
if (str[end]!=' ' || length) {
end++;
}
this should surely be an else if.
if (str[end]!='\0') {// replacing spaces with \0
str[end]='\0';
Now you need to set *ptr to str + start. You also need to update start, and
increment end.
{
This confused me. Much better to set temp before entering the loop.
if (!temp) temp= ptr;
ptr++;
}
return temp;
}

Thanks
Its nearly there. Generally the way to debug rotuintes like this is to slip
in diagnostic printfs. For instance you could have printfed your input
printf("***%s***\n", str) to see it was valid. The asterisks are there to
pick up any funny spaces. The you could have printed "here" before entering
the main loop to see if you actually got there, then str + start to see
where you go to in the string on each pass.

Mar 25 '07 #3

P: n/a
vi*******@gmail.com wrote:
>
I am trying to implement the Split function in C ie.
if i have a string: char* S="This is a test";
and if i try to split based on space ' ' it should return
an array of strings like:

{"This","is","a","test"} .

I tried to implement it as given below but am getting a
segmentation fault. I would really appreciate if some one
could give me an answer on this issue:
Search the google archives for my posting of "toksplic.c".

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

--
Posted via a free Usenet account from http://www.teranews.com

Mar 25 '07 #4

P: n/a

<vi*******@gmail.comha scritto nel messaggio
news:11**********************@y66g2000hsf.googlegr oups.com...
>I am trying to implement the Split function in C ie.
if i have a string: char* S="This is a test";
and if i try to split based on space ' ' it should return an array of
strings like:

{"This","is","a","test"} .

I tried to implement it as given below but am getting a segmentation
fault. I would really appreciate if some one could give me an answer
on this issue:
[snip]
while (str) {
if (*str==' ') count++;
}
You meant *str++, didn't you?
ptr = (char**) malloc(sizeof(char)*(count+1));
Unless you have 256 bytes of memory (or some system with CHAR_BIT 8) a
pointer to char will be definitely larger than a char.
if (!temp) temp= ptr;
When did you exactly use temp after initializing it to NULL?
Mar 25 '07 #5

P: n/a

<vi*******@gmail.comha scritto nel messaggio
news:11**********************@y66g2000hsf.googlegr oups.com...
>I am trying to implement the Split function in C ie.
if i have a string: char* S="This is a test";
and if i try to split based on space ' ' it should return an array of
strings like:

{"This","is","a","test"} .

I tried to implement it as given below but am getting a segmentation
fault. I would really appreciate if some one could give me an answer
on this issue:

char** split(char str[],int*c) {
[snip]
}
That's way too long for my standards, I'd use several functions.

/* BEGIN foo.c */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int count_char(char c, char *str);
int search_char(char c, char *str);

char **split(char *str, int *c)
{
int i, wlen;
int num = count_char(' ', str) + 1;
char **res = malloc(num * sizeof(char *));
*c = num;
if (res == NULL) {
perror("Unable to allocate memory");
return NULL;
}
for (i=0; i<num; i++) {
wlen = (i<num-1) ? search_char(' ', str) : strlen(str);
res[i] = malloc(wlen + 1);
if (res[i] == NULL) {
perror("Unable to allocate memory");
return NULL;
}
strncpy(res[i], str, wlen);
res[i][wlen] = '\0';
str += wlen + 1;
}
return res;
}

int count_char(char c, char *str)
{
int i, res = 0;
for (i=0; str[i] != '\0'; i++)
if (str[i] == c) res++;
return res;
}

int search_char(char c, char *str)
{
int i;
for (i=0; str[i] != '\0'; i++)
if (str[i] == c) return i;
return -1; /* c not found in str */
}

int main(void)
{
int i, n;
char **a = split("This is a test", &n);
printf("%d\n{", n);
for (i=0; i<n; i++)
printf("\"%s\",", a[i]);
puts("\b}");
return 0;
}

/* END foo.c */

army1987@army1987-laptop:~$ gcc foo.c -ansi -Wall -pedantic
army1987@army1987-laptop:~$ ./a.out
4
{"This","is","a","test"}
army1987@army1987-laptop:~$

(Anyway, in the if (res[i] == NULL) within the for loop in function split
I'd better free res[0], res[1], ... res[i-1] and res, and assign NULL to
res.)


Mar 25 '07 #6

P: n/a

"Army1987" <pl********@for.itha scritto nel messaggio
news:eu**********@tdi.cu.mi.it...
(Anyway, in the if (res[i] == NULL) within the for loop in function split
I'd better free res[0], res[1], ... res[i-1] and res, and assign NULL to
res.)
The last point of which is useless anyway, as res is local to split().
Mar 25 '07 #7

P: n/a

"CBFalconer" <cb********@yahoo.comha scritto nel messaggio
news:46***************@yahoo.com...
vi*******@gmail.com wrote:
Search the google archives for my posting of "toksplic.c".
The only one it finds is this one I'm replying to.
Mar 25 '07 #8

P: n/a
On 25 Mar 2007 07:40:02 -0700, vi*******@gmail.com wrote:
>I am trying to implement the Split function in C ie.
if i have a string: char* S="This is a test";
and if i try to split based on space ' ' it should return an array of
strings like:
If your code in the calling function really uses a char* that points
to a literal string, change it to use an array. Your function tries
to modify the string that is passed in and you are not allowed to
modify a string literal.
>
{"This","is","a","test"} .

I tried to implement it as given below but am getting a segmentation
fault. I would really appreciate if some one could give me an answer
on this issue:
You really should sit down with a piece of paper and desk check your
code by pretending to be the computer and manually performing each
step.
>
char** split(char str[],int*c) {
Unless you want to commit the exceptions to memory, you should avoid
any user defined function or object name beginning with str.
int start=0;
int end =0 ;
char** temp=NULL;
char** ptr;
int count=0;
int length = strlen(str);
//first counting the number of spaces
// to know the number of elements in the array
while (str) {
if (*str==' ') count++;
This will count consecutive spaces as if each bounded a word.
}
printf("count value is %d \n",count);
// I am doubt ful about the malloc too
ptr = (char**) malloc(sizeof(char)*(count+1));
Wrong on multiple counts:

Don't cast the return from malloc. It never helps and can cause
the compiler to suppress a diagnostic you would really want to see.
Did you #include stdlib.h. If not this invokes undefined behavior.

ptr is a char**. Therefore, whatever it points to is a char*. On
most systems, sizeof (char*) is a multiple of 4. However, you are
using sizeof (char) which is guaranteed to be 1. You are not
allocating enough space by at least 75%. Rather than go through the
mental gymnastics of keeping the types straight in your head, let the
compiler do it for you with
ptr = malloc((count+1) * sizeof (*ptr));
This will work for any type of ptr except void*.

You should always check malloc for success.
*c = count+1;
All of your count+1 terms seem wrong.
>
while(end<length) {
ptr = str + start;
Didn't your compiler give you a diagnostic here? ptr is a char**. str
is char*. The expression str+start also has type char*. There is no
implicit conversion between the two.

What happened to the memory you just allocated? Who points to it? Do
str or start ever change values?

What you really want is
start = end;
here.
if (str[end]!=' ' || length) {
If length is positive, this always evaluates to true. Make sure you
understand why. You probably meant
if (str[end] != ' ' && end < length) {
Make sure you understand why && and not ||.
end++;
}
if (str[end]!='\0') {// replacing spaces with \0
str[end]='\0';
You need to increment end so the next iteration through the loop does
not start on the '\0' you just inserted.
}
if (!temp) temp= ptr;
This should be done unconditionally right after the malloc.
ptr++;
What you really want here is
*ptr++ = &str[start];
Now figure out why.
}
return temp;
}

Remove del for email
Mar 25 '07 #9

P: n/a
Army1987 wrote, On 25/03/07 22:18:
<vi*******@gmail.comha scritto nel messaggio
<snip>
> ptr = (char**) malloc(sizeof(char)*(count+1));
Unless you have 256 bytes of memory (or some system with CHAR_BIT 8) a
pointer to char will be definitely larger than a char.
Which is why we generally recommend using the form
ptr = malloc(N * sizeof *ptr);
Note the lack of a cast, since casts can hide the serious error of not
including stdlib.h, and using sizeof *ptr so you don't have to worry
about getting the type right.
--
Flash Gordon
Mar 25 '07 #10

P: n/a
Army1987 wrote:
"CBFalconer" <cb********@yahoo.comha scritto nel messaggio
>Search the google archives for my posting of "toksplic.c".

The only one it finds is this one I'm replying to.
That should be toksplit.c

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
--
Posted via a free Usenet account from http://www.teranews.com

Mar 26 '07 #11

This discussion thread is closed

Replies have been disabled for this discussion.