I am trying to create a function that will accept a string, and return an array of words in the string. Here is my attempt:
#include "main.h"
/**
* str_split - Splits a string
* @str: The string that will be splited
*
* Return: On success, it returns the new array
* of strings. On failure, it returns NULL
*/
char **str_split(char *str)
{
char *piece, **str_arr = NULL, *str_cpy;
int number_of_words = 0, i;
if (str == NULL)
{
return (NULL);
}
str_cpy = str;
piece = strtok(str_cpy, " ");
while (piece != NULL)
{
if ((*piece) == '\n')
{
piece = strtok(NULL, " ");
continue;
}
number_of_words ;
piece = strtok(NULL, " ");
}
str_arr = (char **)malloc(sizeof(char *) * number_of_words);
piece = strtok(str, " ");
for (i = 0; piece != NULL; i )
{
if ((*piece) == '\n')
{
piece = strtok(NULL, " ");
continue;
}
str_arr[i] = (char *)malloc(sizeof(char) * (strlen(piece) 1));
strcpy(str_arr[i], piece);
piece = strtok(NULL, " ");
}
return (str_arr);
}
Once I compile my file, I should be getting:
Hello
World
But I am getting:
Hello
Why is this happening? I have tried to dynamically allocate memory for the new string array, by going through the copy of the original string and keeping track of the number of words. Is this happening because the space allocated for the array of strings is not enough?
CodePudding user response:
The code seems fine overall, with just some issues:
You tried to copy str
, as strtok
modifies it while parsing.
This is the right approach. However, the following line is wrong:
str_cpy = str;
This is not a copy of strings, it is only copying the address of the string. You can use strdup
function here.
Also, you need to return the number of words counted otherwise the caller will not know how many were parsed.
Finally, be careful when you define the string to be passed to this function. If you call it with:
char **arr = str_split ("Hello World", &nwords);
Or even with:
char *str = "Hello World";
char **arr = str_split (str, &nwords);
The program will crash as str
here is read-only (see this).
Taking care of these, the program should work with:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/**
* str_split - Splits a string
* @str: The string that will be splited
*
* Return: On success, it returns the new array
* of strings. On failure, it returns NULL
*/
char **str_split(char *str, int *number_of_words)
{
char *piece, **str_arr = NULL, *str_cpy = NULL;
int i = 0;
if (str == NULL)
{
return (NULL);
}
str_cpy = strdup (str);
piece = strtok(str_cpy, " ");
while (piece != NULL)
{
if ((*piece) == '\n')
{
piece = strtok(NULL, " ");
continue;
}
(*number_of_words) ;
piece = strtok(NULL, " ");
}
str_arr = (char **)malloc(sizeof(char *) * (*number_of_words));
piece = strtok(str, " ");
for (i = 0; piece != NULL; i )
{
if ((*piece) == '\n')
{
piece = strtok(NULL, " ");
continue;
}
str_arr[i] = (char *)malloc(sizeof(char) * (strlen(piece) 1));
strcpy(str_arr[i], piece);
piece = strtok(NULL, " ");
}
if (str_cpy)
free (str_cpy);
return (str_arr);
}
int main ()
{
int nwords = 0;
char str[] = "Hello World";
char **arr = str_split (str, &nwords);
for (int i = 0; i < nwords; i ) {
printf ("word %d: %s\n", i, arr[i]);
}
// Needs to free allocated memory...
}
Testing:
$ gcc main.c && ./a.out
word 0: Hello
word 1: World