0

Through a tcp socket I get a string like this: "SmallTitle fromhost 9595".

Upon reciving it I would like to divide it in to a struct so it's easier to work with.

This is what I have come up with. But there are problems. 1 it is nasty. 2 When printing the struct in the end i recieve garbage output after the string. See output example at the bottom. Should not printf stop at '\0'? Then it might be missing such.

struct recieved {
    char what[50];
    char from[50];
    int value;
};


int main(int argc, char const *argv[]) {
    struct recieved leaderRec;

    char *word;
    char buf[] = "leadervalue host 9569"; //Example recieved input from socket.

    word = (char *) malloc(sizeof(char) * 50);
    int i = 0;
    int count = 1;

    do{
        if((buf[i] == ' ') || (buf[i+1] == '\0')){
            //End of word
            //word[strlend(word)+1] = '\0';
            //printf("%s\n", word);
            if(count == 3){
                //The value is here
                //get the last number
                strncat(word,&buf[i], 1);
                leaderRec.value = atoi(word);
                //printf("%d\n", value);
            }

            if(count == 1)
                strncpy(leaderRec.what, word, strlen(word));
            else if(count == 2)
                strncpy(leaderRec.from, word, strlen(word));
            free(word);
            word = (char *) malloc(sizeof(char) * 50);
            count++;
        }
        else {
            //printf("%d\n",i );
            //printf("%s\n", &buf[i]);
            strncat(word,&buf[i], 1);
        }
        //printf("%s", &buf[i]);
        //printf("%d -", i);
        i++;
    } while(buf[i] != '\0');

    printf("%s\n", leaderRec.what);
    printf("%s\n", leaderRec.from);
    printf("%d\n", leaderRec.value);
    return 0;
}

Output:

leadervalue
host__vdso_get
9569

Any better ways to do this? How would I avoid the garbage output at the second print in the example output?

13
  • 1
    Please write code as though humans will read it. Commented Feb 20, 2018 at 19:16
  • Note that the way you are using malloc() makes it look like you don't understand what malloc() is for. Likely your strncpy() migh be a little bit wrong. I just never use it, because IMHO it's better to use memcpy() and write the '\0' by hand. Commented Feb 20, 2018 at 19:19
  • 1
    This is mystery to me — word = (char *) malloc(sizeof(char) * 50); /*...*/ free(word); word = (char *) malloc(sizeof(char) * 50); Commented Feb 20, 2018 at 19:24
  • 1
    Use strtok .. Commented Feb 20, 2018 at 19:27
  • 1
    ... which you could acheive with word = malloc(50); *word = '\0'; Commented Feb 20, 2018 at 19:50

1 Answer 1

2

But there are problems. 1 it is nasty. 2 When printing the struct in the end i recieve garbage output after the string.

The "garbage" prints, as have been noted in the comments, are because you are not properly null terminating your strings. For instance, you are not initializing word to an empty string (single null character) before calling strncat.

Any better ways to do this?

Most certainly. I'd suggest using strtok as so:

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

struct received {
    char what[50];
    char from[50];
    int value;
};

int main(void)
{
  char buf[] = "leadervalue host 9569";
  struct received leaderRec; 
  /* Initialize leaderRec here */      
  memset(&leaderRec, 0, sizeof(leaderRec));

  char *s = strdup(buf);
  char *p = strtok(s, " ");
  if (p != NULL) {
     strncpy(leaderRec.what, p, sizeof(leaderRec.what));
     p = strtok(NULL, " ");
  }
  if (p != NULL) {
     strncpy(leaderRec.from, p, sizeof(leaderRec.from));
     p = strtok(NULL, " ");
  }
  if (p != NULL) {
     leaderRec.value = atoi(p);
  }
  free(s);

  printf("%s %s %d\n", leaderRec.what, leaderRec.from, leaderRec.value);
  return 0;
}
Sign up to request clarification or add additional context in comments.

1 Comment

That's true, I'll delete my first comment: I gave UV before commenting anyway.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.