Search code examples
cvoid

C Void ending issue


I am trying to write a simple parking arrangement code, I want to sort the capacity by 1000 vehicles, color, license plate and model

#include <stdio.h>
#include <stdlib.h>
void NewCar()
{
    char model[1000][20];
    char color [1000][20];
    char number[1000][20];
    int x = 1;
        printf("\nModel: ");
        scanf("%s",model[x]);
        printf("Color: ");
        scanf("%s",color[x]);
        printf("Number: ");
        scanf("%s",number[x]);
}
void CarList()
{
    int x;
    char model[1000][20];
    char color [1000][20];
    char number[1000][20];
    for (x ; x >= 1 ; x--)
    {
        printf("\n%d. Car: %s %s %s",x,number[x],model[x],color[x]);
    }
}
int main()
{
    char model[1000][20];
    char color [1000][20];
    char number[1000][20];
    char menu;
    int x = 1;
    flag:
    printf("New Car(N)\nCar List(L)\n");
    scanf("%s",&menu);
    if (menu == "n" || menu == "N")
    {
        NewCar();
        goto flag;
    }
    if (menu == "l" || menu == "L")
    {
        CarList();
        goto flag;
    }
}

Code Output

when i don't use void, the code works but i have to use void

Example of the output I want;

 1. Car Red Jeep FGX9425
 2. Car Yellow Truck OKT2637
 3. Car Green Sedan ADG4567
 ....

Solution

  • This is prefaced by my top comments.

    Never use goto. Use (e.g.) a while loop.

    Your scanf for menu would [probably] overflow.

    As others have mentioned, a number of bugs.

    I've refactored your code with your old code and some new code. This still needs more error checking and can be generalized a bit more, but, I've tested it for basic functionality:

    #include <stdio.h>
    #include <stdlib.h>
    
    // description of a car
    struct car {
        char model[20];
        char color[20];
        char number[20];
    };
    
    int
    NewCar(struct car *cars,int carcount)
    {
        struct car *car = &cars[carcount];
    
        printf("\nModel: ");
        scanf("%s", car->model);
    
        printf("\nColor: ");
        scanf("%s", car->color);
    
        printf("\nNumber: ");
        scanf("%s", car->number);
    
        ++carcount;
    
        return carcount;
    }
    
    void
    CarList(struct car *cars,int carcount)
    {
        struct car *car;
        int caridx;
    
        for (caridx = 0;  caridx < carcount;  ++caridx) {
            car = &cars[caridx];
            printf("%d. Car: %s %s %s\n",
                caridx + 1, car->number, car->model, car->color);
        }
    }
    
    int
    main(int argc,char **argv)
    {
    #if 1
        int carcount = 0;
        struct car carlist[1000];
    #endif
    #if 0
        char menu;
        int x = 1;
    #else
        char menu[20];
    #endif
    
        // force out prompts
        setbuf(stdout,NULL);
    
        while (1) {
            printf("New Car(N)\nCar List(L)\n");
    #if 0
            scanf("%s", &menu);
    #else
            scanf(" %s", menu);
    #endif
    
            // stop program
            if ((menu[0] == 'q') || (menu[0] == 'Q'))
                break;
    
            switch (menu[0]) {
            case 'n':
            case 'N':
                carcount = NewCar(carlist,carcount);
                break;
    
            case 'l':
            case 'L':
                CarList(carlist,carcount);
                break;
            }
        }
    
        return 0;
    }
    

    UPDATE:

    As you said, there are a few minor errors, it's not a problem for me, but I can write errors if you want to know and fix them.(if you write the plate with a space between it, the code repeats the "new car car list" command many times)

    Okay, I've produced an enhanced version that replaces the scanf with a function askfor that uses fgets. The latter will prevent [accidental] buffer overflow. And, mixing scanf and fgets can be problematic. Personally, I always "roll my own" using fgets as it can provide finer grain control [if used with wrapper functions, such as the askfor provided here]

    Edit: Per chux, I've replaced the strlen for removing newline with a safer version that uses strchr:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define STRMAX      20
    
    // description of a car
    struct car {
        char model[STRMAX];
        char color[STRMAX];
        char number[STRMAX];
    };
    
    // askfor -- ask user for something
    void
    askfor(const char *tag,char *ptr)
    {
    
        printf("Enter %s: ",tag);
        fflush(stdout);
    
        fgets(ptr,STRMAX,stdin);
    
        // point to last char in buffer
        // remove newline
    #if 0
        ptr += strlen(ptr);
        --ptr;
        if (*ptr == '\n')
            *ptr = 0;
    #else
        // remove trailing newline [if it exists]
        ptr = strchr(ptr,'\n');
        if (ptr != NULL)
            *ptr = 0;
    #endif
    }
    
    int
    NewCar(struct car *cars,int carcount)
    {
        struct car *car = &cars[carcount];
    
        askfor("Model",car->model);
        askfor("Color",car->color);
        askfor("Number",car->number);
    
        ++carcount;
    
        return carcount;
    }
    
    void
    CarList(struct car *cars,int carcount)
    {
        struct car *car;
        int caridx;
    
        for (caridx = 0;  caridx < carcount;  ++caridx) {
            car = &cars[caridx];
            printf("%d. Car: %s %s %s\n",
                caridx + 1, car->number, car->model, car->color);
        }
    }
    
    int
    main(int argc,char **argv)
    {
        int carcount = 0;
        struct car carlist[1000];
        char menu[STRMAX];
    
        // force out prompts
        setbuf(stdout,NULL);
    
        while (1) {
            askfor("\nNew Car(N)\nCar List(L)",menu);
    
            // stop program
            if ((menu[0] == 'q') || (menu[0] == 'Q'))
                break;
    
            switch (menu[0]) {
            case 'n':
            case 'N':
                carcount = NewCar(carlist,carcount);
                break;
    
            case 'l':
            case 'L':
                CarList(carlist,carcount);
                break;
            }
        }
    
        return 0;
    }
    

    UPDATE #2:

    Thank you for your bug fix, but as I said in my question, I have to do the "New car" feature using void. You did it with int, can you do it with void?

    Okay. When you said "using void", what you meant wasn't totally clear to me [or some others]. There were enough bugs that they overshadowed some other considerations.

    So, I have to assume that "using void" means that the functions return void.

    Your original functions were defined as void NewCar() and void CarList(). Those could not have done the job as is, so they had to be changed.

    If you have similar criteria, a better way to phrase that would be:

    I must create two functions, with the following function signatures ...

    Anyway, here's the updated code:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define STRMAX      20
    
    // description of a car
    struct car {
        char model[STRMAX];
        char color[STRMAX];
        char number[STRMAX];
    };
    
    // askfor -- ask user for something
    void
    askfor(const char *tag,char *ptr)
    {
    
        printf("Enter %s: ",tag);
        fflush(stdout);
    
        fgets(ptr,STRMAX,stdin);
    
        // remove trailing newline [if it exists]
        ptr = strchr(ptr,'\n');
        if (ptr != NULL)
            *ptr = 0;
    }
    
    void
    NewCar(struct car *cars,int *countptr)
    {
        int carcount = *countptr;
        struct car *car = &cars[carcount];
    
        askfor("Model",car->model);
        askfor("Color",car->color);
        askfor("Number",car->number);
    
        carcount += 1;
        *countptr = carcount;
    }
    
    void
    CarList(struct car *cars,int carcount)
    {
        struct car *car;
        int caridx;
    
        for (caridx = 0;  caridx < carcount;  ++caridx) {
            car = &cars[caridx];
            printf("%d. Car: %s %s %s\n",
                caridx + 1, car->number, car->model, car->color);
        }
    }
    
    int
    main(int argc,char **argv)
    {
        int carcount = 0;
        struct car carlist[1000];
        char menu[STRMAX];
    
        // force out prompts
        setbuf(stdout,NULL);
    
        while (1) {
            askfor("\nNew Car(N)\nCar List(L)",menu);
    
            // stop program
            if ((menu[0] == 'q') || (menu[0] == 'Q'))
                break;
    
            switch (menu[0]) {
            case 'n':
            case 'N':
    #if 0
                carcount = NewCar(carlist,carcount);
    #else
                NewCar(carlist,&carcount);
    #endif
                break;
    
            case 'l':
            case 'L':
                CarList(carlist,carcount);
                break;
            }
        }
    
        return 0;
    }
    

    However, given your original functions, it may be possible that the signatures have to be: void NewCar(void) and void CarList(void) and that the car list variables must be global scope.

    This would be a less flexible and desirable way to do things, but here is a version that uses only global variables for the lists:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define STRMAX      20
    
    // description of a car
    struct car {
        char model[STRMAX];
        char color[STRMAX];
        char number[STRMAX];
    };
    
    #if 1
    int carcount = 0;
    struct car carlist[1000];
    #endif
    
    // askfor -- ask user for something
    void
    askfor(const char *tag,char *ptr)
    {
    
        printf("Enter %s: ",tag);
        fflush(stdout);
    
        fgets(ptr,STRMAX,stdin);
    
        // remove trailing newline [if it exists]
        ptr = strchr(ptr,'\n');
        if (ptr != NULL)
            *ptr = 0;
    }
    
    void
    NewCar(void)
    {
        struct car *car = &carlist[carcount];
    
        askfor("Model",car->model);
        askfor("Color",car->color);
        askfor("Number",car->number);
    
        carcount += 1;
    }
    
    void
    CarList(void)
    {
        struct car *car;
        int caridx;
    
        for (caridx = 0;  caridx < carcount;  ++caridx) {
            car = &carlist[caridx];
            printf("%d. Car: %s %s %s\n",
                caridx + 1, car->number, car->model, car->color);
        }
    }
    
    int
    main(int argc,char **argv)
    {
    #if 0
        int carcount = 0;
        struct car carlist[1000];
    #endif
        char menu[STRMAX];
    
        // force out prompts
        setbuf(stdout,NULL);
    
        while (1) {
            askfor("\nNew Car(N)\nCar List(L)",menu);
    
            // stop program
            if ((menu[0] == 'q') || (menu[0] == 'Q'))
                break;
    
            switch (menu[0]) {
            case 'n':
            case 'N':
    #if 0
                carcount = NewCar(carlist,carcount);
    #else
                NewCar();
    #endif
                break;
    
            case 'l':
            case 'L':
    #if 0
                CarList(carlist,carcount);
    #else
                CarList();
    #endif
                break;
            }
        }
    
        return 0;
    }