-1

I am trying to create a car renting project. I create a linked list in function createCarList(), where struct car is defined in f.h. When I enter one car, everything works fine. When I enter two cars, I always get infinite loops such as when printing the list with printAllCars() or if I try to check whether the car is already in the list.

Here is my code:

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



/*car struct */

typedef struct car{
    unsigned int plate_number;
    unsigned int vin_number;
    char *Manufacturer_Name;
    char *model;
    char *colour;
    unsigned int year_Manufactured;
    unsigned int realseYear;
    unsigned int payment;
    unsigned int value;
    unsigned int engine_power;
    struct car *next;

}car;

car *cars;

/*function to scan and check the int input*/
int CheckIntinput(unsigned int *a)
{

    char temp[20];
    int i;
    int flag=1;
    while(1)
    {
    scanf("%s",temp);
    for(i=0;i<strlen(temp);i++)
    {
        if(!isdigit(temp[i]))
        {
            flag=0;
            printf("You did not enter a number , Please enter an argument's number\n");
            break;
        }
    }
    if(flag)
    {
        break;
    }
    flag=1;
  }
    
    *a=strtoul(temp,NULL,10);
    return 1;
}

/*function to check if the information of the car are correct*/
void checkifcarnputiscorrect(unsigned int *plate_number,unsigned int *vin_number,unsigned int *year_Manufactured,unsigned int *realseYear
,unsigned int *payment,unsigned int *value,unsigned int *engine_power){
    int flag=1;

     while(1)
     {
        printf("enter plate number :");
        CheckIntinput(plate_number);
        if(*plate_number>9999999 || *plate_number<1000000)
         {
            printf("plate number should be 7 digits try again \n");
            flag=0;
         }
         /*
         if(!checkifcaralreadyinlist(*plate_number))
            {
                printf("the car is already in the list \n");
                flag=0;
            }*/
         if(flag){break;}
         flag=1;
     }

     while(1)
     {
         printf("enter vin number :");
         CheckIntinput(vin_number);
     if(*vin_number>99999 || *vin_number<10000)
     {
         printf("vin_number should be 5 digits try again\n");
         flag=0;
     }
     if(flag){break;}
     flag=1;
     }

    while(1)
    {
        printf("enter year manfucatured :");
        CheckIntinput(year_Manufactured);
     if(*year_Manufactured>9999||*year_Manufactured<1000)
     {
         printf("yeaer_manfucatured should be 4 digits try again\n");
         flag=0;
     }
     if(flag){break;}
     flag=1;
    }

    while(1)
    {
        printf("enter realese year :");
        CheckIntinput(realseYear);
     if(*realseYear>9999||*realseYear<1000){
         printf("realse year  should be 4 digits try again \n");
        flag=0;
     }
     if(flag){break;}
     flag=1;
    }

    while(1){
        printf("enter payment :");
       CheckIntinput(payment);
     if(*payment>9999999||*payment<0){
         printf("payment should be between 0-9999999 digits\n");
         flag=0;
     }
     if(flag){break;}
     flag=1;
    }

    while(1){
        printf("enter value :");
        CheckIntinput(value);
     if(*value>9999999||*value<0){
         printf("value should be between 0-9999999 digits\n");
         flag=0;
     }
     if(flag){break;}
     flag=1;
    }

    while(1){
        printf("enter engine_power :");
       CheckIntinput(engine_power);
     if(*engine_power>9999||*engine_power<1000){
         printf("engine power be 4 digits\n");
         flag=0;
     }
     if(flag){break;}
     flag=1;
}
}

/*function to scan and check if the input is only chars*/
void Checkstringifonlychars(char *str){
    int i;
    int flag=1;
   while(1)
   {
       scanf("%s",str);
       for(i=0;i<strlen(str);i++)
       {
           if(!isalpha(str[i]))
           {
               flag=0;
               printf("wrong input try input only chars.");
               break;
           }
       }
       if(flag)
       {
           break;
       }
       flag=1;
   }
   
   
}



int CheckLonginput(unsigned long *a)
{

    char temp[20];
    int i;
    int flag=1;
    while(1)
    {
    scanf("%s",temp);
    for(i=0;i<strlen(temp);i++)
    {
        if(!isdigit(temp[i]))
        {
            flag=0;
            printf("You did not enter a number , Please enter an argument's number\n");
            break;
        }
    }
    if(flag)
    {
        break;
    }
    flag=1;
  }
    
    *a=strtoul(temp,NULL,10);
    return 1;
}

/*creating empty car list */


int createCarList()
{
    car *cars=(car*)malloc(sizeof(car));
    if(!cars)
    {
        return 0;
    }
    cars->next=NULL;
    return 1;
}

int addNewCar()
{
    unsigned int plate_number,vin_number,realseYear,year_Manufactured,payment,value,engine_power;
    char *Manufacturer_Name,*model,*colour,c;
    car * temp=NULL;
    car * p=NULL;
    temp=NULL;
    temp=(car*)malloc(sizeof(car));
    while(1){
        checkifcarnputiscorrect(&plate_number,&vin_number,&year_Manufactured,&realseYear,&payment,&value,&engine_power);

        Manufacturer_Name=(char*)malloc(5 * sizeof(char));
        printf("enter Manufacturer Name:");
        Checkstringifonlychars(Manufacturer_Name);
    
        model=(char*)malloc(5 * sizeof(char));
        printf("enter model:");
        Checkstringifonlychars(Manufacturer_Name);
    
        colour=(char*)malloc(5 * sizeof(char));
        printf("enter colour of the car:");
        Checkstringifonlychars(Manufacturer_Name);
    
        temp->plate_number=plate_number;
        temp->vin_number=vin_number;
        strcpy(temp->Manufacturer_Name,Manufacturer_Name);
        strcpy(temp->model,model);
        strcpy(temp->colour,colour);
        temp->year_Manufactured=year_Manufactured;
        temp->realseYear=realseYear;
        temp->payment=payment;
        temp->value=value;
        temp->engine_power=engine_power;
        temp->next=NULL;

        if(cars==NULL)
        {
            cars=temp;
        }
        else
        {
            p=cars;
            while(p->next!=NULL)
            {
                p=p->next;
            }
            p->next=temp;
        }  

        printf("\n done adding? if yes press y ");
        scanf(" %c",&c);
        if(c=='y')
        {
            break;
        }

   
    }
    if(cars==NULL)
    {
        return 0;
    }
    return 1;
}



void printAllCars(void){

    car *tmp=cars;

    if(!cars){ 
        printf("No Cars in list to Shown\n");
        return;
    }
    
    printf("\nCar List :\n\n");
    printf("LicenseNum | chassisNum | makerName | modelName | color | productionYear | onRoadYear |  price  |  paidMoney  | engine");
    printf("\n----------------------------------------------------------------------------------------------------------------------\n");
    while(tmp!=NULL)
    {
        printf("%-11u ",tmp->plate_number);
        printf("%-13u ",tmp->vin_number);
        printf("%-11s ",tmp->Manufacturer_Name);
        printf("%-11s ",tmp->model);
        printf("%-7s ",tmp->colour);
        printf("%-16u ",tmp->year_Manufactured);
        printf("%-11u ",tmp->realseYear);
        printf("%-9u ",tmp->value);
        printf("%-14u ",tmp->payment);
        printf("%u\n",tmp->engine_power);
        tmp=tmp->next;
    }

    printf("\n");
}

int main()
{
    createCarList();
    addNewCar();
    printAllCars();
    return 0;
}

input:

enter plate number :1234567
enter vin number :12345
enter year manfucatured :1994
enter realese year :1995
enter payment :30000
enter value :25000
enter engine_power :3000
enter Manufacturer Name:bmw
enter model:bmw
enter colour of the car:red

output:

plate number :1234567
vin number :12345
year manfucatured :1994
realese year :1995
enter payment :30000
enter value :25000
engine_power :3000
Manufacturer Name:bmw
model:bmw
colour of the car:red

when i added a secound car or more.

enter plate number :1234567
enter vin number :12345
enter year manfucatured :1994
enter realese year :1995
enter payment :30000
enter value :25000
enter engine_power :3000
enter Manufacturer Name:bmw
enter model:bmw
enter colour of the car:red

output: prints first car then infinite time secound car.

I checked the while loops for all the functions, but I couldn't find the error. What could be the problem?

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
am_sa
  • 27
  • 5
  • 4
    createCarList creates a local variable cars which is lost when it returns – stark May 29 '21 at 12:32
  • ... which makes me suspect that the code presented is not representative of the real problem. – John Bollinger May 29 '21 at 12:37
  • 1
    Please provide a [mre] of the problem with exact input, intended output and actual output. – Andreas Wenzel May 29 '21 at 12:43
  • `car * temp=NULL; temp=NULL; temp=(car*)malloc(sizeof(car));` without reading in between? Why don't you just have `car* temp = (car*)malloc(sizeof(car));` – Aconcagua May 29 '21 at 12:43
  • if i get 1 car from the input it works and its print the car with the specific details from the input and all the funcitons that i didnt wrote here works fine , but when i enter 2+ cars then there is the problem its enter an inifinity loop suck as its start printing and don't stop – am_sa May 29 '21 at 12:44
  • @AndreasWenzel tried to upload an image for the input/ouput not working because of low reputation, when i input car details for 1 car the program works fine it prints all car details as it asked same as other functions, but when i enter 2 cars or more it start printing without stopping , infinite loop its like its stuck in the secound node of the linked list and keep printing it. – am_sa May 29 '21 at 12:59
  • Please don't attempt to upload images of output. It is better to add them to the question **as text** (the same way you added the code). You may want to read this: [Why not upload images of code/errors when asking a question?](https://meta.stackoverflow.com/q/285551/12149471) – Andreas Wenzel May 29 '21 at 13:02
  • This is only a personal design recommendation. I would pass your `car` objects to each of your functions - init (create), add, remove, print/show, etc. –  May 29 '21 at 13:13
  • @AndreasWenzel i had coppied the code from file.h into 1 file.c so all the code needed to check the problem would be here. thanks for the advice. – am_sa May 29 '21 at 13:28
  • Have you tried running your code line by line in a debugger while monitoring the values of all variables, in order to determine at which point your program stops behaving as intended? If you did not try this, then you probably want to read this: [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/q/25385173/12149471) – Andreas Wenzel May 29 '21 at 14:08
  • I have reverted your most recent edit, in which you fixed most of the bugs that I mentioned in my answer, because this invalidated my answer. Now, the answer and the question fit together again. In future, please don't invalidate answers by fixing bugs mentioned in answers. If you want to show us your updated code, then you can either post a new question or you can add it to the bottom of the existing question. As long as the original question remains intact, the answers will not be invalidated. – Andreas Wenzel Jun 03 '21 at 09:30

1 Answers1

0

I found 5 bugs in your code. After fixing these bugs, your program seems to work. I haven't tested all kinds of input, though.


First bug:

In the function createCarList, the line

car *cars=(car*)malloc(sizeof(car));

does not write to your global variable cars. Instead, it creates a new local variable with that name, and writes to that one instead. If you want to write to the global variable, you should write cars=(car*)malloc(sizeof(car)); instead. However, I don't see much point in that, as this will do nothing else than make cars point to a mostly uninitialized node. It would probably be best to remove the function createCarList completely.


Second bug:

In the function addNewCar, in the lines

model=(char*)malloc(5 * sizeof(char));
printf("enter model:");
Checkstringifonlychars(Manufacturer_Name);

you need to replace Manufacturer_Name with model. You make the same mistake later in your code with the variable colour:

colour=(char*)malloc(5 * sizeof(char));
printf("enter colour of the car:");
Checkstringifonlychars(Manufacturer_Name);

Third bug:

In the function addNewCar, in the line

strcpy(temp->Manufacturer_Name, Manufacturer_Name);

you write to the address of the uninitialized pointer temp->Manufacturer_Name, which causes undefined behavior. You must first allocate memory for the new string (for example with malloc) and make temp->Manufacturer_Name point to that memory. However, since you already did that for Manufacturer_Name, it would probably be sufficient not to use strcpy, but to instead simply copy the pointer, like this:

temp->Manufacturer_Name = Manufacturer_Name;

The following lines have the same problem as described above:

strcpy(temp->model,model);
strcpy(temp->colour,colour);

Fourth bug:

With the line

Manufacturer_Name = (char*)malloc(5 * sizeof(char));

you allocate space for 5 characters, including the terminating null character. Since you use the %s scanf format specifier, if the user enters "Honda", this will cause a buffer overflow, because storing that string requires 6 bytes including the terminating null character. Such a buffer overflow causes undefined behavior. Therefore, instead of reading input with the line

scanf("%s",str);

it would be better to use

scanf("%4s",str);

which limits the input to 4 characters, so that a buffer overflow cannot occur.


Fifth Bug:

In the function addNewCar, the line

temp = (car*)malloc(sizeof(car));

is only executed once, because it is outside the while loop. You must move it inside the while loop, so that it is executed once for every car added. Otherwise, your program will reuse the same memory address for every linked list node, so that every node will point to itself. This will later cause an infinite loop when printing out the nodes in the function printAllCars.


Additional concerns:

  • The functions CheckIntinput, checkifcarnputiscorrect, Checkstringifonlychars and CheckLonginput have misleading names. The word "check" in this context implies that the functions merely perform input validation, but not that the functions actually read input.
  • It is unsafe to use scanf without checking the return value. Also, for line-based input, I recommend that you always use fgets instead of scanf. See this page for further information: A beginners' guide away from scanf()
  • You should always check the return value of malloc in order to verify that it is not NULL.
  • Your casts of the result of malloc are not necessary. You may want to read the following question: Do I cast the result of malloc?
Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
  • thank you about those bugs some of it just because i coppied and pasted while writing the code , about the problem i have still not fixed when i try to print the linkedlist i still get infinit loop and start printing the last element in the linkedlist without stopping – am_sa May 29 '21 at 19:40
  • @am_sa: I am unable to reproduce your problem, because on my computer, your program crashes beforehand, due to the third bug mentioned above. Since some of the mentioned bugs cause undefined behavior, they could be the reason for your problem. Undefined behavior can cause anything to happen. Therefore, I suggest that you first fix all mentioned bugs, and if you still have the problem, you can post the updated code. Don't overwrite the original question, though, as this would invalidate my answer. You can add your updated code to the bottom of the question. – Andreas Wenzel May 29 '21 at 20:26
  • i updated after fixing the bugs... to compiler i always use :gcc mySource.c -ansi -Wall -pedantic-errors -lm -o myProg ...and its works good with 1 object in the linkedlist but when entering the secound always getting infinite loops – am_sa May 29 '21 at 20:37
  • @am_sa: When I now run your program using Microsoft Visual Studio on Windows, it now crashes due to the problem mentioned under "first bug". Your function `createCarList` makes `cars` point to mostly uninitialized node. All node contents are uninitialized, except for the `next` pointer. This later causes a crash in `printAllCars`. If I simply remove the function call to `createCarList`, the programs stops crashing, and I am now able to reproduce the problem that you mentioned in your question for the first time. I am now looking into that problem using my debugger. – Andreas Wenzel May 29 '21 at 21:30
  • @am_sa: Using the debugger, I was able to find the problem. I have now added a "fifth bug" to my answer. – Andreas Wenzel May 29 '21 at 21:57
  • @am_sa: If you want to be able to diagnose and fix such bugs yourself, I strongly suggest that you learn how to use a [debugger](https://stackoverflow.com/q/25385173/12149471). With a debugger, you can execute your code line by line, while monitoring the values of all variables. That way, you can see why your program is behaving in a certain way, and what went wrong in your program. It would have been much harder for me to find the bug without a debugger. Although I don't use the gcc compiler, I believe it is common to use [gdb](https://en.wikipedia.org/wiki/GNU_Debugger) with it. – Andreas Wenzel May 29 '21 at 23:12
  • noted ... i tried to use gdb but kinda failed...but i'am gonna learn ASAP. thanks again for the advice. – am_sa May 29 '21 at 23:22
  • @am_sa: If you are using an [IDE](https://en.wikipedia.org/wiki/Integrated_development_environment), then you may be able to use it as a front-end for debugging, while it uses gdb as a backend. Most IDEs offer some kind of debugging facilities. That way, you won't have to use gdb directly. Your IDE will take care of that for you. – Andreas Wenzel May 29 '21 at 23:23