Thread: Function returning array of strings.

  1. #1
    Registered User
    Join Date
    Jun 2010
    Posts
    9

    Function returning array of strings.

    Hi,

    I want to write a function to parse a string, which will return the parsed strings in the array format.
    I just wanted to know how should I declare my function which will return me an array of strings.
    I tried to do something like this:

    Code:
    char **parse_my_string(char *string_to_be_parsed, char delimiter)
    {
         char arr_str[5][10];
    
          function body;
          return arr_str;
    }

  2. #2
    Registered User
    Join Date
    Dec 2011
    Posts
    795
    That won't work because you're returning a pointer to something that's already been freed. (stack variables are freed when the function exits).

    Instead, pass the array of strings to the function and allocate it beforehand.

  3. #3
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    I have a better idea, (not tested though):
    Replace all the 'delimiter's in the 'string_to_be_parsed' with '\0' and return a char** casted 'string_to_be_parsed' .

  4. #4
    Registered User
    Join Date
    Jun 2010
    Posts
    9
    I tried to allocate char arr_str[5][10] before the function definition. It complied without any errors. But, when I tried to test it in the main, It is giving me error: "error C2664: 'strcpy' : cannot convert parameter 2 from 'char **' to 'const char *' "

    How to check it?

    I did something like this:

    Code:
    char test_arr_str[5][10];
    
    int main(void)
    {
       -----
      strcpy(test_arr_str, parse_my_string(str, ' '));
      -----
    }

  5. #5
    Registered User
    Join Date
    Dec 2011
    Posts
    795
    What? No.

    Modify your function prototype to accept a 2D array (not a global!) and allocate it right before you pass the variable. Also, you need to strcpy() into one of the strings, not the entire array.

  6. #6
    Registered User
    Join Date
    Jun 2010
    Posts
    9
    I made the following changes:
    Code:
    char **parse_2D(char parsed_arr[5][20], char *str_to_be_parsed,  char ch)
    {
        strcpy(parsed_arr[0], str_to_be_parsed);
        --------
        --------
        return parsed_arr;
    }
    It is still not working.

  7. #7
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    How is it not working? What is in str_to_be_parsed? If it's any more than 19 characters long, you have a buffer overflow. Also, you aren't actually parsing str_to_be_parsed. Not just that, you aren't showing us how you declare the 2-d array in main and how you call parse_2D. The error may be in there.

    We need a clear description of the problem and all the relevant source code.

  8. #8
    Registered User
    Join Date
    Jun 2010
    Posts
    9
    something like this:

    Code:
    #include <stdio.h>
    #include <string.h>
    
    char **parse_my_string(char [][], char *, char *);
    
    char parsed_str[5][20];
    char *str = "abcd efg ij";
    
    
    int main(void)
    {
    	int count = 0;
    
    	count = count_spaces(str);
    
    	parse_string(parsed_str , str, ' ');
    
    	for(int i = 0; i <= count; i++)
    	{
    		printf("%s\n", temp_str[i]);
    	}
    	
    	getchar();
    
    	return 0;
    
    }
    
    char **parse_my_string(char parse_arr[5][20], char *str_to_be_parsed, char *ch)
    {
    	char *temp;
    	char *temp_str;
    	int i = 0;
    
    	strcpy(temp_str, str_to_be_parsed);
    
    	temp = strtok(temp_str, ch);
    
    	strcpy(parse_arr[i], temp);
    	i++;
    
    	while((temp = strtok('\0', ch)) != '\0')
    	{
    		strcpy(parse_arr[i], temp);
    		i++;
    	}
    	return parse_arr;
    }

  9. #9
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    There's so much wrong with this it's hard to know where to start.
    1. Don't make parsed_str and str global. Declare them in main.
    2. count_spaces does not exist.
    3. temp_str is not accessible in main.
    4. In parse_my_string, temp_str has no storage allocated to it.
    5. You're using strtok incorrectly. Don't pass '\0' as the first param. Pass NULL.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  10. #10
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Much of what oogabooga mentioned, and what I'm mentioning should result in warnings or errors from your compiler. If you don't see them, turn up the settings, and if you do, fix them!


    1. You never allocate space for temp_str, it's just a pointer that points to random/garbage memory. There is nowhere to copy str_to_be_parsed, so most likely, line 35 will cause a seg fault, since you're accessing memory you don't own.
    2. In parse_my_string, the ch parameter is a char pointer, but you pass in ' ' (single quotes), which is just a plain char.
    3. If your string has two spaces in a row, strtok will skip both of them. That means that count is not an accurate reflection of how many words the string was parsed into (unless your count_spaces function does not do precisely what it's name implies). A better solution would be to make parse_my_string return an int, and have it return i, which is the number of words it found. You no longer need to return the 2-d array since you already declared it and have access to it in main.

  11. #11
    Registered User
    Join Date
    Jun 2010
    Posts
    9
    I made following changes.
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    
    void parse_my_string(char**, char *, char *);
    int count_spaces(char*);
    
    int main(void)
    {
        int count = 0, i = 0;
        char **parsed_str; 
        char *str = "abcd efg ij";
    
        count = count_spaces(str);
    
        parse_my_string(parsed_str , str, ' ');
    
        for(i = 0; i <= count; i++)
        {
            printf("%s\n", parsed_str[i]);
        }
    
        getchar();
    
        return 0;
    
    }
    
    int count_spaces(char* str)
    {
    	int i, count = 0;
    	for(i = 0; i < strlen(str); i++)
    	{
    		if(str[i] == ' ')
    			count++;
    	}
    	return count;
    }
    
    void parse_my_string(char **parse_arr, char *str_to_be_parsed, char *ch)
    {
        char *temp;
        char *temp_str;
        int i = 0;
    
        temp_str = (char *) malloc(strlen(str_to_be_parsed) + 1);
    
        strcpy(temp_str, str_to_be_parsed);
    
        temp = strtok(temp_str, ch);
    
        strcpy(parse_arr[i], temp);
        i++;
    
        while((temp = strtok(NULL, ch)) != '\0')
        {
            strcpy(parse_arr[i], temp);
            i++;
        }
        parse_arr[i] = NULL;
    
        free(temp_str);
    
    }

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Unfortunately, there are still problems to resolve. Let's start with main:
    Code:
    parse_my_string(parsed_str , str, ' ');
    You pass parsed_str, which means that any changes to parsed_str from within the function will not be reflected in main. This is fine if parsed_str already points to the first pointer in an array of pointers, but it does not point to anything. Since you don't know the number of strings in advance (actually you do, but I recommend getting rid of count_spaces - see my point later), one way is to pass a pointer to parsed_str, but then you would be dealing with a char***, which is kind of too many levels of indirection.

    There are two ways around this: you could return a char**, or you could create a struct to hold the char**, then pass a pointer to the struct. Either way, you need to allocate space for the pointers to char.

    Furthermore, you declared the third parameter of parse_my_string to be a char*, yet you passed ' ' as the argument (note the difference between ' ' and " ").

    Then, look at:
    Code:
    for(i = 0; i <= count; i++)
    This loop will loop count - 0 + 1 times. Typically, to loop count times, we will write:
    Code:
    for(i = 0; i < count; i++)
    Next, in parse_my_string, you use malloc for temp_str. Well and good. But you did not allocate space for any of the individual strings, yet you attempt to strcpy to parse_arr[i]. One approach is to simply assign pointers:
    Code:
    parse_arr[i] = temp;
    However, this means that you cannot free(temp_str) in parse_my_string, which is a problem.

    My suggestion is to use this approach, but dispense with temp_str. That is, you use strtok with str_to_be_parsed. If you need the original input string, make a copy of it before calling parse_my_string.

    Oh, and instead of having a count_spaces function, just get parse_my_string to return the number of tokens. If you opt to return a char**, have an int* parameter to serve as an out parameter for the number of token.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Returning Array from Function
    By tarunjain07 in forum C Programming
    Replies: 4
    Last Post: 09-03-2011, 01:26 PM
  2. returning a 2D array from a function
    By sauwen in forum C Programming
    Replies: 5
    Last Post: 11-19-2010, 05:51 PM
  3. c++ -- returning an array from function
    By p4plus2 in forum C++ Programming
    Replies: 25
    Last Post: 08-18-2008, 01:48 PM
  4. Replies: 6
    Last Post: 11-09-2006, 03:28 AM
  5. returning strings - function.
    By Vber in forum C Programming
    Replies: 11
    Last Post: 03-23-2003, 05:24 PM