Copying specific number of characters from a string to another

Viewed 210

I have a variable length string that I am trying to divide from plus signs and study on:

            char string[] = "var1+vari2+varia3";
            for (int i = 0; i != sizeof(string); i++) {               
                memcpy(buf, string[0], 4);
                buf[9] = '\0';
            }

since variables are different in size I am trying to write something that is going to take string into loop and extract (divide) variables. Any suggestions ? I am expecting result such as:

var1
vari2
varia3
4 Answers

You can use strtok() to break the string by delimiter

   char string[]="var1+vari2+varia3";
   const char delim[] = "+";
   char *token;
   
   /* get the first token */
   token = strtok(string, delim);
   
   /* walk through other tokens */
   while( token != NULL ) {
      printf( " %s\n", token );
    
      token = strtok(NULL, delim);
   }

More info about the strtok() here: https://man7.org/linux/man-pages/man3/strtok.3.html

You can use a simple loop scanning the string for + signs:

    char string[] = "var1+vari2+varia3";
    char buf[sizeof(string)];
    int start = 0;
    for (int i = 0;;) {
        if (string[i] == '+' || string[i] == '\0') {
            memcpy(buf, string + start, i - start);
            buf[i - start] = '\0';
            // buf contains the substring, use it as a C string
            printf("%s\n", buf);
            if (string[i] == '\0')
                break;
            start = ++i;
        } else {
            i++;
        }
    }
        

It seems to me that you don't just want to want to print the individual strings but want to save the individual strings in some buffer.

Since you can't know the number of strings nor the length of the individual string, you should allocate memory dynamic, i.e. use functions like realloc, calloc and malloc.

It can be implemented in several ways. Below is one example. To keep the example simple, it's not performance optimized in anyway.

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

char** split_string(const char* string, const char* token, int* num)
{
    assert(string != NULL);
    assert(token != NULL);
    assert(num != NULL);
    assert(strlen(token) != 0);

    char** data = NULL;
    int num_strings = 0;
    while(*string)
    {
       // Allocate memory for one more string pointer
       char** ptemp = realloc(data, (num_strings + 1) * sizeof *data);
       if (ptemp == NULL) exit(1);
       data = ptemp;
       
       // Look for token
       char* tmp = strstr(string, token);
       
       if (tmp == NULL) 
       {
           // Last string
           // Allocate memory for one more string and copy it
           int len = strlen(string);
           data[num_strings] = calloc(len + 1, 1);
           if (data[num_strings] == NULL) exit(1);
           memcpy(data[num_strings], string, len);

           ++num_strings;    
           
           break;
       }
       
       // Allocate memory for one more string and copy it
       int len = tmp - string;
       data[num_strings] = calloc(len + 1, 1);
       if (data[num_strings] == NULL) exit(1);
       memcpy(data[num_strings], string, len);
       
       // Prepare to search for next string
       ++num_strings;
       string = tmp + strlen(token);
    }
    
    *num = num_strings;
    return data;
}

int main()
{
    char string[]="var1+vari2+varia3";
    
    // Split the string into dynamic allocated memory
    int num_strings;    
    char** data = split_string(string, "+", &num_strings);

    // Now data can be used as an array-of-strings
    
    // Example: Print the strings
    printf("Found %d strings:\n", num_strings);
    for(int i = 0; i < num_strings; ++i) printf("%s\n", data[i]);
    
    // Free the memory
    for(int i = 0; i < num_strings; ++i) free(data[i]);
    free(data);

}

Output

Found 3 strings:
var1
vari2
varia3

Your code does not have any sense.

I wrote such a function for you. Analyse it as sometimes is good to have some code as a base

char *substr(const char *str, char *buff, const size_t start, const size_t len)
{
    size_t srcLen;
    char *result = buff;

    if(str && buff)
    {
        if(*str)
        {
            srcLen = strlen(str);
            if(srcLen < start + len)
            {
                if(start < srcLen) strcpy(buff, str + start);
                else buff[0] = 0;          
            }
            else
            {
                memcpy(buff, str + start, len);
                buff[len] = 0;
            }
        }
        else
        {
            buff[0] = 0;
        }
    }
    return result;
}

https://godbolt.org/z/GjMEqx

Related