How can I return list in C?

Viewed 160

I am trying to divide the string with *, and return the divided strings, as follows.

abc*d*efg*hijk -> [abc,d,efg,hijk]

This is my code, where *pattern is the given string, and I first count the number of asterisk(cnt), and make a empty list with length cnt. But it keeps getting the error and I don't get it... Can anyone help me?

error message

  1. value computed is not used (*star_cnt++;)
  2. function returns address of local variable(return units;) Number 2 is my main error. I can't return the list
int Slice(char *pattern) {

  int *star_cnt;
  int cnt;

  *star_cnt = *pattern;
  cnt = 0;

  while (*star_cnt != '\0') {
    if (*star_cnt == '*') {
      cnt++;
    }
    *star_cnt++;
  }

  int units[cnt];
  int *unit;
  int unit_cnt;
  unit_cnt = 0;
  *unit = *pattern;

  while (*unit != '\0') {
    int *new_unit;
    while (*unit != '*'){
      *new_unit = *unit;
      unit++;
      new_unit++;
    }
    unit++;
    units[unit_cnt] = *new_unit;
  }
  return units;
2 Answers

I felt there were a number of things wrong, and that looking at a working example might actually help a bit more here.

You could try something like this:

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>

/**
 * @fn Slice()
 * @param [IN] pattern  - pointer to string to be analysed
 * @param 
 * @return pointer to array for strings, array is terminated by NULL
 * */
char** Slice(char *pattern) {

  char *star_cnt;
  int cnt;
  char** resultlist;

  star_cnt = pattern;
  cnt = 0;

  while (*star_cnt != '\0') {
    if (*star_cnt == '*') {
      cnt++;
    }
    star_cnt++;
  }

  printf("%d items\n",cnt+1);

  resultlist = malloc(sizeof(char*) * (cnt+2));
  memset(resultlist,0,sizeof(char*) * (cnt+2));
  star_cnt = pattern;

  cnt = 0;  
  resultlist[cnt] = star_cnt;
  //printf("item %d: %s\n",cnt,resultlist[cnt]);
  cnt++;
  while (*star_cnt != '\0') {
    if (*star_cnt == '*') {
      *star_cnt = '\0';
      resultlist[cnt] = star_cnt+1;
      //printf("item %d: %s\n",cnt,resultlist[cnt]);
      cnt++;
    }
    star_cnt++;
  }
  return resultlist;
}

int main()
{
  char working_string[] = "abc*d*efg*hijk";
  char* backup_string = strdup(working_string);
  char** list = NULL;
   
  list = Slice(working_string);
  int i;

  i = 0;
  if (list != NULL)
  {
    while(list[i] != NULL)
    {
        printf("%d : %s\n",i,list[i]);
        i++;
    }
    free(list);
  }

  printf("original_string = %s\n",backup_string);
  free(backup_string);
}

It produces an output like this:

4 items
0 : abc
1 : d
2 : efg
3 : hijk
original_string = abc*d*efg*hijk

The Slice function basically returns a pointer to char* strings, and the array list is terminated with a NULL in the last element. Keep in mind that in this solution the original string is modified so it cannot be used again.

For storing and returning the result you can also define string container like:

struct c_str_container{
    char **arr;
    size_t size;
};

And then you can define functions like init_c_str_container, add_element_to_c_str_container and free_c_str_container for dealing with the container.

then you can write the substrings function with using strchr function for finding the delimiters and splitting the string in to sub-strings.

Finally you can use this function to create the container and then after displaying the result from the container (and possibly doing other things with the container) you free the allocated memory by the predefined function free_c_str_container:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct c_str_container{
    char **arr;
    size_t size;
};

void init_c_str_container(struct c_str_container *container){
    container->arr = NULL;
    container->size = 0;
}

int add_element_to_c_str_container(struct c_str_container *container, const char *txt, size_t length){
    char **newarr = (char **) realloc(container->arr, (container->size + 1) * (sizeof(char *)));
    if(!newarr){
        newarr =  (char **) malloc((container->size + 1) * (sizeof(char *)));
        if(!newarr){
            return -1;
        }else{
            for(size_t counter = container->size; counter--;){
                newarr[counter] = container->arr[counter];
            }
            if(container->size){
                free(container->arr);
            }
        }
    }
    newarr[container->size] = malloc((length + 1) * sizeof(char));
    memcpy(newarr[container->size], txt, length);
    newarr[container->size][length] = '\0';
    container->arr = newarr;
    ++container->size;
    return 0;
}

void free_c_str_container(struct c_str_container *container){
    for(size_t counter = container->size; counter--;){
        free(container->arr[counter]);
    }
    free(container->arr);
    container->size = 0;
}


struct c_str_container substrings(const char *input, const char delimiter){
    const char *input_end = input + strlen(input);
    struct c_str_container container;
    init_c_str_container(&container);

    while(strchr(input, delimiter) == input){
        ++input;
    }

    const char *end_point;
    while((end_point = strchr(input, delimiter))){
        add_element_to_c_str_container(&container, input, (end_point - input));
        while(strchr(end_point, delimiter) == end_point){
            ++end_point;
        }
        input = end_point;
    }

    if(input < input_end){
        add_element_to_c_str_container(&container, input, (input_end - input));
    }

    return container;
}

int main(void) {

    struct c_str_container container = substrings("***as***we*grow*up", '*');

    printf("number of elements is : %zu\n", container.size);
    for(size_t counter = 0; counter < container.size; ++counter){
        printf("element %zu is : %s\n", counter, container.arr[counter]);
    }
    free_c_str_container(&container);
    printf("now elements are : %zu\n", container.size);

    return EXIT_SUCCESS;
}

for the test string ="***as***we*grow*up" delimeter = '*' the result of the program is:

number of elements is : 4
element 0 is : as
element 1 is : we
element 2 is : grow
element 3 is : up
now elements are : 0
Related