-1

I am trying to write a C program that ask a user for a number 'n' of cars that he/she wish to catalog and then dynamically create an array of that number of cars. Each element of the array is a variable of type 'car'. the structure 'car' has two members variables:1) make(which is a string that represent the make of the car) and 2) year(an integer representing the year of manufacture of the car). What I want is my program to read the make and the year for each element of the array stated above. At the end I will print each element of that array. My code is below. But this code cannot read the make and the year for the car stored in the array.`

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

struct car {
    char *make;
    int year;
};

typedef struct car Car;

char *getname()
{
    char *str, c;
    int i = 0, j = 1;

    str = (char *)malloc(sizeof(char));

    printf("Enter the make: ");

    while (c != '\n') {
        // read the input from keyboard standard input
        c = getc(stdin);

        // re-allocate (resize) memory for character read to be stored
        str = (char *)realloc(str, j * sizeof(char));

        // store read character by making pointer point to c
        str[i] = c;

        i++;
        j++;
    }

    str[i] = '\0';      // at the end append null character to mark end of string

    return str;
    free(str)       // important step the pointer declared must be made free
}

int main(void)
{
    int i, j, n;
    printf("How many cars do you wish to catalog? :");
    scanf("%d", &n);
    Car *vti;       //a pointer so that I will use to store n cars //
    vti = (Car *) malloc(n * sizeof(Car));
    for (i = 0; i < n; i++) {
        printf("Car #%d", i);
        vti[i].*(make) = getname();
        printf("Enter the year made:");
        scanf("%d", &(vti[i].year));

    }

    for (i = 0; i < n; i++) {
        printf("Here is your collection\n");
        printf("%s%d\n", vti[i].make, vti[i].year);

    }

    return 0;
}

Paul R
  • 208,748
  • 37
  • 389
  • 560
  • `vti[i].*(make)=getname();` -> `vti[i].make=getname();` – Paul R Dec 24 '20 at 14:52
  • `free(str)// important step the pointer declared must be made free` should be removed because 1. This will lead to compilation error because a semicolon is missing. 2. After adding a semicolon, this line become just meaningless because this line is after `return str;` and will never be reached. 3. You must not free what will be used, so you do not need `free()` here anyway. – MikeCAT Dec 24 '20 at 15:23
  • Also related: [c - fgets doesn't work after scanf - Stack Overflow](https://stackoverflow.com/questions/5918079/fgets-doesnt-work-after-scanf) – MikeCAT Dec 24 '20 at 15:31
  • Although, rather than `vti[i].make = getname()`, it would be far more idiomatic to increment the pointer and write `v->make = getname()` – William Pursell Dec 25 '20 at 23:20
  • You should probably stop thinking of standard input as being in any way related to a keyboard. Your programs will be much more robust if you are able to break that association in your mind. Avoid comments like "keyboard standard input". – William Pursell Dec 25 '20 at 23:30

1 Answers1

1

This is intended more as a comment that an answer, but it's tough to format in a comment. There are several aspects of your code that I would consider to be non-idiomatic. It would be more typical to do something like:

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

struct car {
        char *make;
        int year;
};

int
main(void)
{
        size_t cap = 128;
        char buf[1024];
        struct car *cars = realloc(NULL, cap * sizeof *cars);
        struct car *c = cars;
        if( cars == NULL ){
                err(EXIT_FAILURE, "out of memory");
        }
        while( 2 == scanf("%1023[^\n]%d", buf, &c->year) ){
                if( (c->make = strdup(buf)) == NULL ){
                        err(EXIT_FAILURE, "out of memory");
                }
                if( ++c == cars + cap ){
                        struct car *t = realloc(cars, (cap += 128) * sizeof *cars);
                        if( t == NULL ){
                                err(EXIT_FAILURE, "out of memory");
                        }
                        c = t + (c - cars);
                        cars = t;
                }
        }
        for( ; cars < c; cars++ ){
                printf("%s: %d\n", cars->make, cars->year);
                free(cars->make);
        }
}

But even this is a bit odd. It might be better to used getline instead of 2 conversion specifiers in a scanf. YMMV. I would advise against using scanf at all, frankly.

William Pursell
  • 204,365
  • 48
  • 270
  • 300