the function: createTripData() calls scanf()
but fails to check the returned value (not the parameter values) so if the user enters just a return key or enters anything but digit(s) then the code accepts the nothing input, This is an error
The function: main()
has two parameters, but neither is being used. the function main()
has two valid signatures:
int main( int argc, char *argv[] )
int main( void )
since the parameters are not used, the code should use the signature:
int main( void )
The function: main()
is getting the menu selection from the user via:
scanf( "%d", &option );
but not checking the returned value (not the parameter values) so when the user only enters a 'return' or any character other than a digit, the prior value in the field option
is used. if the user entered any digit besides 1 or 2 then the code 'screams' through the while()
loop, doing either nothing or per what ever value was previously in the variable option
.
I.E. ALWAYS check the returned value from calls to any of the scanf()
family of functions and handle errors.
in the function: main()
, a assumption is made that the user entered either 1 or 2. That is NOT a valid assumption. (never trust the user to do the right thing) Strongly suggest the if( option == 1
and else if(option == 2)
be replaced with a switch() statement that includes a
default` case for when the user enters any number other than 1 or 2 I.E.
switch( option )
{
case 1:
...
break;
case 2:
...
break;
default:
printf( "INVALID option: %d, valid options are 1, 2\n", option );
break;
}
this field, in the definition of struct list
Trip* Trip;
It is very poor programming practice to name a variable the same as the type of the variable. A possible fix:
Trip *myTrip;
Then update the other references in the code to use myTrip
It is very poor programming practice to name a variable the same as the type of the variable, with the only difference being the capitalization. Such practice leads to confusion in the human reading the code.
In function: create_list()
what happens when the call to malloc()
fails? A NULL pointer is returned to function: add_List()
which returns that NULL pointer to function: main()
, which (successful or not) overlays the value in the variable trips
.
the statement:
fflush(stdin);
while being allowed in visual studio, is NOT portable. suggest using something like:
int ch;
while( (ch = getchar()) != EOF && '\n' != ch );
regarding the calls to scanf()
, here is one way to handle the error events:
if( 1 != scanf( "%d", &trip->code ) )
{ // then error occurred as 'scanf' returns number of successful input/conversions
perror( "scanf for code failed" );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
The above suggested method immediately exits the program (leaving the OS to cleanup all the allocated memory, which would be poor programming practice) You might want to, instead code a loop that informs the user of the problem, empties stdin and allowing the user to try again.
this statement:
printf("Select an option: \n 1-add new trip \n 2-Iterate\n");
will become very 'difficult' to read and understand if there are several choices in the menu. suggest making use of the C feature of bring all the consecutive strings together and writing the statement like this:
printf("Select an option: \n"
" 1-add new trip \n"
" 2-Iterate\n");
Note: the suggested formatting also pays attention to the right edge of the printed page, making for a much nicer layout.
the function: delete_List()
is never called, so the 'menu' in main()
is missing an option.
BTW: the function: delete_List()
uses recursion, which is OK if the linked list is rather short. However, if there are a lot of entries in the linked list then (especially on windows) there is a high probability of overflowing the stack. I suggest using a loop to walk the linked list, passing each entry to free()
after saving the ->next
pointer Then it does not matter how many entries are in the linked list
for ease of readability and understanding:
1. separate code blocks (for, if, else, while, do... while, switch, case, default) via a single blank line
2. separate functions by 2 or 3 blank lines (be consistent)
3. follow the axiom: only one statement per line and (at most) one variable declaration per statement.
Now, why are you seeing the problem you mention in the question:
the second pointer passed to add_List()
is to a uninitialized local pointer on the stack in main()
, not to the actual pointer to the linked list that was declared by: List* trips;
Suggest using unique names so YOU can keep track of what is pointing to what.
Also,in function: create_List()
, the new node is being set to point to that uninitialized pointer in main(), rather than to the desired entry in trips
in main.
Note, in function: main()
, in modern C compilers, if the returned value is always 0, then the return
statement is not needed.
Note: the statement return
is not a function, so there is no need (unless wrapping multiple expression into a single result value) to have parens around the value passed back by return
.
for simplification, suggest elimination of the variable first
, changing List* trips;
to List *trips = NULL;
and replacing: if(first == 1)
with: if( !trips )
I.E. always try to write the simplest code that still performs the functionality.