Search code examples
cfunctionreturn

Why does function not start after user input being returned from another function


That's the code in C:

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

typedef struct {
    char street;
    int number;
    char postalcode;
} Person;

void print(Person p) {
    printf("Street: %s\n", p.street);
    printf("Number: %d\n", p.number);
    printf("Postal code: %s\n", p.postalcode);
}

Person signUp() {
  Person person;

  printf("In which street do you live on?: \n");
  scanf("%s", &person.street);

  printf("What is your number?: \n");
  scanf("%d", &person.number);

  printf("what is your postal code?: \n");
  scanf("%s", &person.postalcode);

  return person;
 }

int main(void) {
  Person person;

  person = signUp();
    print(person); 

  return 0;
}

I tried to make the "signUp" function return the user inputs to another function called "print", so it would print the values from the previous function. The "signUp" function works just fine, but the "print" function never starts.


Solution

    1. You reading and writing strings with %s but your variables are a single char (which would be the format string %c).
    2. When reading a string with scanf() always use a maximum field width. I am using a str() macro here to not repeat myself. Note: usually we prefer using sizeof() but you need sizeof(p->street)-1 and the order of evaluation of macros gets in the way.
    3. There is nothing wrong with passing in a struct by value and returning them by value, however, this implies copies so we usually pass these in via a pointer instead.
    #include <stdio.h>
    #include <stdlib.h>
    
    #define POSTALCODE_LEN 5
    #define STREET_LEN 20
    #define str(s) str2(s)
    #define str2(s) #s
    
    typedef struct {
        char street[STREET_LEN+1];
        int number;
        char postalcode[POSTALCODE_LEN+1];
    } Person;
    
    void print(const Person *p) {
        printf("Street: %s\n", p->street);
        printf("Number: %d\n", p->number);
        printf("Postal code: %s\n", p->postalcode);
    }
    
    void signUp(Person *person) {
        printf("In which street do you live on?: \n");
        scanf("%" str(STREET_LEN) "s", person->street);
    
        printf("What is your number?: \n");
        scanf("%d", &person->number);
    
        printf("what is your postal code?: \n");
        scanf("%" str(POSTALCODE_LEN) "s", person->postalcode);
    }
    
    int main(void) {
        Person person;
        signUp(&person);
        print(&person);
    }
    

    I realize that the typedef saves you from writing struct Person but the downside is that it imports "Person" into the same name space as variable so you cannot do Person Person but have to use a lowercase person. If you need to talk to someone about your code it becomes more tedious "lowercase person" or "uppercase person" to differentiate. Personally (pun), I would use use a short variable name to get around it, i.e. Person p.

    I also find snake case easier to read than camel case (sign_up() vs signUp()), and I find the namespace rules easier to remember (constants are upper case, rest is lowercase; with camel case it's methods starts with lower case and then you upper case each words except ... etc).