Jake Smith
Jake Smith

Reputation: 199

Updating string until period is found in C

In this function I am going to be receiving char * words such as

person.vet.blah

and

word.friends.joe

I want to extract the first word. So for the first one I want to extract

 person 

and the second one I want to extract

 word

How can I correctly do this? Here is my code:

char *separate_name(char *machine_name)
{
    //iterate until you find period. then return
    char absolute_name[1000];
    int i;
    for (i =0; i < strlen(machine_name); i++)
    {
        if (machine_name[i] == '.')
          absolute_name[i] = machine_name[i];

    }


    return absolute_name;
}

This is just segfaulting. Any ideas what I should be doing? machine_name is going to be the "person.vet.blah" and then return absolute_name which would be "person"

Upvotes: 0

Views: 113

Answers (2)

Tom Fenech
Tom Fenech

Reputation: 74685

Fixing your code

As others have pointed out, you can't use absolute_name outside of the function in which it was defined. This is because you're when you return the variable from your function, all that is being returned is a pointer to the beginning of the array. Outside the function, the array itself no longer exists, so the pointer is invalid and you get a segfault if you try and dereference it.

You can get around this by using malloc. Don't forget to free the memory you have allocated when you are done using it.

By the way, as well as changing your loop to a while, I also fixed the check (you were checking machine_name[i] == '.', the opposite to what you wanted).

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

char *separate_name(char *machine_name)
{
    // allocate memory on the heap
    char *absolute_name = malloc(strlen(machine_name)+1);

    int i = 0;    
    while (i < strlen(machine_name) && machine_name[i] != '.') {
        absolute_name[i] = machine_name[i];
        ++i;
    }
    absolute_name[i] = '\0';

    return absolute_name;
}

int main() 
{
    char name1[] = "person.vet.blah";
    char *first1 = separate_name(name1);
    if (first1 != NULL) {
        printf("%s\n", first1);
        free(first1);
    }

    char name2[] = "word.friends.joe";
    char *first2 = separate_name(name2);
    if (first2 != NULL) {
        printf("%s\n", first2);
        free(first2);
    }

    return 0;
}

A better alternative

strtok is the perfect tool for the job:

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

char *separate_name(char *machine_name)
{
    return strtok(machine_name, ".");
}

int main() 
{
    char name1[] = "person.vet.blah";
    char *first1 = separate_name(name1);
    if (first1 != NULL) printf("%s\n", first1);

    char name2[] = "word.friends.joe";
    char *first2 = separate_name(name2);
    if (first2 != NULL) printf("%s\n", first2);

    return 0;
}

As pointed out in the comments (thanks @John), strtok modifies the string that is passed to it (it replaces the delimiter . by the \0 null byte to mark the end of the string). This isn't a problem here but is something to be aware of.

Output using either program:

person
word

Upvotes: 6

BLUEPIXY
BLUEPIXY

Reputation: 40145

#include <stdio.h>

char *separate_name(const char *machine_name){
    static char absolute_name[1000];
    int i;
    for (i =0; i < sizeof(absolute_name)-1 ; i++){
        if(machine_name[i] == '.' || machine_name[i] == '\0'){
            absolute_name[i] = '\0';
            break;
        } else {
            absolute_name[i] = machine_name[i];
        }
    }

    return absolute_name;
}
int main(void){
    printf("%s\n", separate_name("person.vet.blah"));
    printf("%s\n", separate_name("word.friends.joe"));
    return 0;
}

Upvotes: 1

Related Questions