2

I'm trying to split a string into chunks of 6 using C and I'm having a rough time of it. If you input a 12 character long string it just prints two unusual characters.

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

void stringSplit(char string[50])
{
    int counter = 0;
    char chunk[7];

    for (unsigned int i = 0; i < strlen(string); i++)
    {
        if (string[i] == ' ')
        {
            continue;
        }

        int lastElement = strlen(chunk) - 1;
        chunk[lastElement] = string[i];
        counter++;

        if (counter == 6)
        {
            printf(chunk);
            memset(chunk, '\0', sizeof chunk);
            counter = 0;
        }
    }
    if (chunk != NULL)
    {
        printf(chunk);
    }

}

int main()
{
    char string[50];
    printf("Input string. \n");
    fgets(string, 50, stdin);
    stringSplit(string);
    return(0);
}

I appreciate any help.

WewLad
  • 717
  • 2
  • 11
  • 22
  • 2
    These statements int lastElement = strlen(chunk) - 1; and if (chunk != NULL) { printf(chunk); } do not make sense. – Vlad from Moscow Feb 21 '17 at 16:56
  • 1
    Note: in `for (unsigned int i = 0; i < strlen(string); ..` the `strlen` function _is executed every iteration_ but the string length doesnt change. You are wasting machine cycles! – Paul Ogilvie Feb 21 '17 at 17:01

2 Answers2

1

Your problem is at

int lastElement = strlen(chunk) - 1;

Firstly, strlen counts the number of characters up to the NUL character. Your array is initially uninitialized, so this might cause problems.

Assuming your array is filled with NULs, and you have, let's say, 2 characters at the beginning and you are looking to place the third one. Remember that your 2 characters are at positions 0 and 1, respectively. So, strlen will return 2 (your string has 2 characters), you subtract one, so the lastElement variable has the value 1 now. And you place the third character at index 1, thus overwriting the second character you already had.

Also, this is extremely inefficient, since you compute the number of characters each time. But wait, you already know how many characters you have (you count them in counter, don't you?). So why not use counter to compute the index where the new character should be placed? (be careful not to do the same mistake and overwrite something else).

Paul92
  • 8,827
  • 1
  • 23
  • 37
  • Too add onto this and possibly clarify: the lines `int lastElement = strlen(chunk) - 1;` and `chunk[lastElement] = string[i];` are **always placing the char at the same location**. – Aroic Feb 21 '17 at 17:06
1

The function is wrong.

This statement

int lastElement = strlen(chunk) - 1;

can result in undefined behavior of the function because firstly the array chunk is not initially initialized

char chunk[7];

and secondly after this statement

memset(chunk, '\0', sizeof chunk);

the value of the variable lastElement will be equal to -1.

This if statement

if (chunk != NULL)
{
    printf(chunk);
}

does not make sense because the address of the first character of the array chunk is always unequal to NULL.

It seems that what you mean is the following.

#include <stdio.h>
#include <ctype.h>

void stringSplit( const char s[] )
{
    const size_t N = 6;
    char chunk[N + 1];

    size_t i = 0;

    for ( ; *s; ++s )
    {
        if ( !isspace( ( unsigned char )*s ) )
        {
            chunk[i++] = *s;

            if ( i == N )
            {
                chunk[i] = '\0';
                i = 0;
                puts( chunk );
            }
        }
    }

    if ( i != 0 )
    {
        chunk[i] = '\0';
        puts( chunk );
    }
}

int main(void) 
{
    char s[] = "   You and I are beginners in C    ";

    stringSplit( s );
}   

The program output is

Youand
Iarebe
ginner
sinC

You can modify the function such a way that the length of the chunk was specified as a function parameter.

For example

#include <stdio.h>
#include <ctype.h>

void stringSplit( const char s[], size_t n )
{
    if ( n )
    {
        char chunk[n + 1];

        size_t i = 0;

        for ( ; *s; ++s )
        {
            if ( !isspace( ( unsigned char )*s ) )
            {
                chunk[i++] = *s;

                if ( i == n )
                {
                    chunk[i] = '\0';
                    i = 0;
                    puts( chunk );
                }
            }
        }

        if ( i != 0 )
        {
            chunk[i] = '\0';
            puts( chunk );
        }
    }       
}

int main(void) 
{
    char s[] = "   You and I are beginners in C    ";

    for ( size_t i = 3; i < 10; i++ )
    {
        stringSplit( s, i );
        puts( "" );
    }       
}   

The program output will be

You
and
Iar
ebe
gin
ner
sin
C

Youa
ndIa
rebe
ginn
ersi
nC

Youan
dIare
begin
nersi
nC

Youand
Iarebe
ginner
sinC

YouandI
arebegi
nnersin
C

YouandIa
rebeginn
ersinC

YouandIar
ebeginner
sinC
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335