Duarte Pereira
Duarte Pereira

Reputation: 1

How do i fix an bus error in c in this program with dynamic-memory-allocation?

Why am i receiving a bus error?

I´m making a simple program that abbreviate the middle names, for example, we have Artur José Bastos Costa and it should print “Artur J. B. Costa”.

Here is my code: enter image description here enter image description here

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

char* abrevia(char full_name[]){
    int numNames = 0, i = 0;
    char* abbreviation = (char*) malloc(strlen(full_name) * sizeof(char));
    char* name = strtok(full_name, " ");
    strcpy(abbreviation, name);
    strncat(abbreviation, " ", 1);
    while (name != NULL){
        numNames++;
        name = strtok(NULL, " "); 
    }

    char* nomeCopy = (char*) malloc(strlen(full_name) * sizeof(char));
    strcpy(nomeCopy, full_name);
    char* name2 = strtok(nomeCopy, " ");
    while (name2 != NULL){
        if (i != numNames -1){
            strncat(abbreviation, &name2[0], 1);
            abbreviation[strlen(abbreviation)] = '.';
            abbreviation[strlen(abbreviation)] = ' ';
        }
        else {
            strcat(abbreviation, name2);
        }
        name2 = strtok(NULL, " ");
        i++;
    }
    free(nomeCopy);
    return abbreviation;
}

int main(){
    char* abr = abrevia("Artur José Bastos Costa");
    printf("%s", abr);
    free(abr);
    return 0;
}

First i didn´t copied the full_name, but i tried doing that becausa i was using strtok twice and there wasn´t more tokens in the first time, so i tought that in the second loop it will crash because of that. But i couldnt fix it. Sorry my english is not my first language

Upvotes: 0

Views: 148

Answers (1)

user9706
user9706

Reputation:

  1. The bus error / segfault is due to passing a read-only string literal to abrevia() but strtok() modifies it's first argument. You can pass an array like this:
    char *abr = abrevia((char []) { "Artur José Bastos Costa"});

or even better if you want to use strtok() (opposed to strpbrk()) have abrevia() copy the string into an array. This allows you to make the input a pointer to a constant value.

  1. malloc(strlen(full_name)) is 1 byte too small.

  2. Prefer passing a variable instead of a type of sizeof(). Less code duplication. Assizeof(char) is defined as 1 so I would just leave it out.

  3. Don't cast the void * from malloc().

  4. You don't do anything with the 2nd middle name.

The basic idea is to handle the first and last token as special cases. To figure out if it's the last token you need to do 1 token look-ahead:

#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char *abrevia(const char *full_name){
    char *full_name2 = strdup(full_name);
    char *name = strtok(full_name2, " ");
    if(!name) {
        free(full_name2);
        return NULL;
    }
    char *abbreviation = malloc(strlen(full_name2) + 1);
    strcpy(abbreviation, name);
    name = strtok(NULL, " ");
    for(;;) {
        char *name2 = strtok(NULL, " ");
        if(!name2)
            break;
        strcat(abbreviation, " ");
        strncat(abbreviation, name, 1);
        strcat(abbreviation, ".");
        name = name2;
    }
    if(name) {
        strcat(abbreviation, " ");
        strcat(abbreviation, name);
    }
    free(full_name2);
    return abbreviation;
}

int main(){
    char *abr = abrevia("Artur José Bastos Costa");
    printf("%s\n", abr);
    free(abr);
    return 0;
}

and here is the output:

Artur J. B. Costa

Upvotes: 1

Related Questions