user8314628
user8314628

Reputation: 2042

How can I cut a string in C?

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

int main(int argc, char **argv) {
    if (argc != 3) {
        fprintf(stderr, "Usage: greeting message name\n");
        exit(1);
    }
    char greeting[20];
    char *name = argv[2];

    // Your code goes here
    for (int i = 0; i < strlen(argv[1]); i++) {
        if (i < 20) {
            greeting[i] = argv[1][i];
        }
        else {
            greeting[i] = '\0';
        }
    }

    int greeting_len = strlen(greeting);
    strcat(greeting, " ");
    strncat(greeting, name, 20-greeting_len-2);

    printf("%s\n", greeting);
    return 0;
}

In this practice, I am required to concatenate the two command line arguments, which are greeting and name, together and separated by a space. What's more, the greeting and the string after concentrated cannot be longer than 20 characters.

When I run ./a.out "Good morninggggggggggggggggggg" "Emmanuel", there is an error saying

*** stack smashing detected ***: ./a.out terminated
Aborted (core dumped)

How can I fix it?

Upvotes: 0

Views: 81

Answers (2)

user3629249
user3629249

Reputation: 16540

the following proposed code:

  1. cleanly compiles
  2. performs the desired functionality
  3. properly checks for (and handles) errors
  4. has no openings for undefined behavior nor buffer overflows
  5. places a space between argv[1] and argv[2]

and now, the proposed code:

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

int main(int argc, char **argv) 
{
    if (argc != 3) 
    {
        fprintf(stderr, "Usage: greeting message name\n");
        exit(1);
    }


    char *greeting = malloc( strlen( argv[1] ) + strlen( argv[2] ) +1 +1 );
    if( !greeting )
    {
        perror( "malloc failed" );
        exit( EXIT_FAILURE );
    }


    strcpy( greeting, argv[1] );
    strcat( greeting, " " );
    strcat( greeting, argv[2] );


    printf("%s\n", greeting);

    free( greeting );
    return 0;
}

Upvotes: 0

Barmar
Barmar

Reputation: 780673

If the message argument is longer than 20 characters, your first loop will write outside the bounds of greeting. The if statement doesn't stop the loop, it keeps going, but assigns null bytes instead of argv[1][i].

And if the message argument fits into greeting, you never add a null byte at all. The loop stops after copying the last character, not including the null terminator.

You can simply use strncpy(), and then set the last byte of greeting to a null byte.

strncpy(greeting, argv[1], sizeof greeting);
greeting[sizeof greeting - 1] = '\0';

You need to check if you've hit the limit before adding the space:

if (greeting_len < 18) {
    greeting[greeting_len] = ' ';
    greeting[greeting_len+1] = '\0';
    greeting_len++;
}
if (greeting_len < 18) {
    strncat(greeting, name, 19-greeting_len);
}

But if you can use snprintf() it's all much easier:

snprintf(greeting, sizeof greeting, "%s %s", argv[1], name);

Upvotes: 2

Related Questions