Program stops execution halfway through in C - c

This might be a dumb question but basically this program which uses pointer lists but stops execution after the first use of my showliste function which I use to I print out the list and I have no idea why. If I remove the showliste function then it runs the rest of the code just fine however I really have no idea why since I don't modify anything in that function and its only purpose is to print out the elements.
If somebody could help me out that would be very useful. Thank you in advance!
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define max 10
struct book{
char name[50];
float price;
struct book *next;
};
typedef struct book BOOK;
BOOK * createlist(BOOK *);
void showliste(BOOK *);
BOOK * deleteElem(BOOK *);
int main()
{
BOOK *pstart = NULL;
pstart = createlist(pstart);
printf("\nHere is the ordered list: \n");
showliste(pstart); //stops excution after this for some reason
pstart = deleteElem(pstart);
printf("\nHere is the list with the element deleted: \n");
showliste(pstart);
return 0;
}
BOOK * createlist(BOOK *pdebut)
{
int i, choice = 0;
BOOK *pparcour = NULL, *pprecedent = NULL, *pnew = NULL;
for(i = 0; i < max && choice == 0; i++)
{
pnew = (BOOK *)malloc(sizeof(BOOK));
printf("Enter name: ");
fflush(stdin);
gets(pnew->name);
printf("Enter Price: ");
scanf("%f", &pnew->price);
if(pdebut == NULL)
{
pdebut = pnew;
}
else{
pparcour = pdebut;
pprecedent = NULL;
while(pparcour != NULL && pnew->price > pparcour->price)
{
pprecedent = pparcour;
pparcour = pparcour->next;
}
if(pprecedent == NULL)
{
pnew->next = pparcour;
pdebut = pnew;
}
else{
pprecedent->next = pnew;
pnew->next = pparcour;
}
}
printf("Do you want to continue? \n");
printf("0 - Yes 1 - NO\n");
printf("Choice: ");
scanf("%d", &choice);
}
return pdebut;
}
void showliste(BOOK *pdebut)
{
while(pdebut != NULL)
{
printf("Name: %s\n", pdebut->name);
printf("Price: %.3f\n\n", pdebut->price);
pdebut = pdebut->next;
}
}
BOOK * deleteElem(BOOK *pdebut)
{
char cible[50];
BOOK *pprecedent = NULL, *pparcour = NULL;
printf("Enter the name of the book you want to delete: ");
fflush(stdin);
gets(cible);
pparcour = pdebut;
pprecedent = NULL;
while(pparcour != NULL && strcmpi(cible, pparcour->name))
{
pprecedent = pparcour;
pparcour = pparcour->next;
}
if(pparcour == NULL)
{
printf("\nEntered name is not in the list!!!!\n");
}
else{
if(pprecedent == NULL)
{
pdebut = pdebut->next;
free(pparcour);
}
else{
pprecedent->next = pparcour->next;
free(pparcour);
}
}
return pdebut;
}
pdebut is the head of the list.
pparcour is a pointer which I use to go through my list without modifying it.
pprecedent is basically the element just before pparcour, mainly used to add a new book in the correct position in a ordered list (if the price of the new book is smaller than the price located in pparcour->price)

These lines
pparcour = pdebut;
/* ... */
pparcour = pparcour->next;
setup access to the uninitialized next member of the recently malloc'd structure, which contains an indeterminate pointer value. Attempting to to read a price member via this indeterminate pointer value
while(pparcour != NULL && pnew->price > pparcour->price)
will invoke Undefined Behaviour on subsequent iterations of the loop.
Use calloc, or manually set the newly allocated node's next member to NULL.
for(i = 0; i < max && choice == 0; i++)
{
pnew = malloc(sizeof *pnew);
pnew->next = NULL;
/* ... */

Related

How do I debug a Segmentation fault when I nothing is wrong before the fault or after?

The particular problem I have is that in my main function, I have added a print statement before and after I call the "bad" function. It always shows the before statement, but never the after statement. I also added a print statement to the end of the "bad" function, and I can see that it runs properly to the very last line of the "bad" function, so it should return normally. After the functions last print and before the main function print, I get the segfault. Any ideas? Here is the code:
int main(int argc, char* argv[])
{
char myItem[100];
int i = 0;
while (i < 100) {
scanf("%[^\n]", myItem);
i++;
if (myItem == EOF) {
break;
}
int c;
while ((c = getchar()) != '\n' && c != EOF);
//printf("string read in from user typing: %s\n", myItem);
printf("i = %d\n", i);
emailFilter(myItem);
printf("done with email filter in main\n");
//printf("item from this pass is:%s\n\n", myItem);
}
return 0;
}
and the "bad" function:
void emailFilter(char* mySubject)
{
printf(" Just entered the emailFilter() .\n");
char * event_holder[5]; //holds five separate char ptrs
for (int i = 0; i < 5; i++)
{
event_holder[i] = ((char*)malloc(100 * sizeof(char*)));
}
char command_type = parseSubject(mySubject, event_holder); //parses subject line and fills event_holder. returns command type, from parsing
//call proper parsing result
if (command_type == 'C')
{
create(event_holder);
}
else if (command_type == 'X')
{
change(event_holder);
}
else if (command_type == 'D')
{
delete(event_holder);
}
printf("Leaving emailfilter()...\n");
}
and running this code provides me:
$:
i = 1
Just entered the emailFilter() .
C, Meeting ,01/12/2019,15:30,NEB202
Leaving emailfilter()...
done with email filter in main
i = 2
Just entered the emailFilter() .
Leaving emailfilter()...
Segmentation fault
This shows that I always make it through the function, but still don't return properly.
Here is my entire code to reproduce the error.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct node {
char * event_data[5];
struct node * next;
};
struct node *head = NULL;
struct node *current = NULL;
char* earliest = NULL;
char* substring (char* orig, char* dest, int offset, int len)
{
int input_len = strlen (orig);
if (offset + len > input_len)
{
return NULL;
}
strncpy (dest, orig + offset, len);
//add null char \0 to end
char * term = "\0";
strncpy (dest + len, term, 1);
return dest;
}
char * firstItem(char* shortenedSubject)
{
int i = 0;
int currentLength = 0;
int currentCharIndex = 0;
int eventIndex = 0;
char * toReturn = (char*)malloc(100);
while ((shortenedSubject[currentLength] != '\0') && (shortenedSubject[currentLength] != ',') )//50 is my safety num to make sure it exits eventually
{
currentLength++;
}
if (shortenedSubject[currentLength] == ',') {
substring(shortenedSubject, toReturn, 0, currentLength);
}
return toReturn;
}
char parseSubject(char* subject,char * eventDataToReturn[5]) //returns "what type of command called, or none"
{
char toReturn;
char * shortenedSubject = (char*)malloc(100);
substring(subject,shortenedSubject,9,strlen(subject)-9);//put substring into tempString
int currentCharIndex = 0;// well feed into index of substring()
int eventIndex = 0; //lets us know which event to fill in
int currentLength = 0;//lets us know length of current event
int i = 0; //which char in temp string were alooking at
char * action = firstItem(shortenedSubject);
if (strlen(action) == 1)
{
if ( action[0] == 'C')
{
toReturn = 'C';
}
else if (action[0] == 'X')
{
toReturn = 'X';
}
else if (action[0] == 'D')
{
toReturn = 'D';
}
else
{
toReturn = 'N'; //not valid
//invalid email command, do nothing
}
}
else
{
toReturn = 'N'; //not valid
//invalid email command, do nothing
}
char* debug2;
while ((shortenedSubject[i] != '\0') && (i <= 50) )//50 is my safety num to make sure it exits eventually
{
char debugvar = shortenedSubject[i];
currentLength++;
if (shortenedSubject[i] == ',')
{
//eventDataToReturn[i] = substring2(shortenedSubject,currentCharIndex,currentLength);
substring(shortenedSubject,eventDataToReturn[eventIndex],currentCharIndex,currentLength-1);
debug2 = eventDataToReturn[eventIndex];
currentCharIndex= i +1;
eventIndex++;
currentLength = 0;
//i++;
}
i++;
}
substring(shortenedSubject,eventDataToReturn[4],currentCharIndex,currentLength);
return toReturn;
}
void printEventData(char* my_event_data[])
{
//printf("\nPrinting event data...\n");
for (int i = 1; i < 4; i++)
{
printf("%s,",my_event_data[i]);
}
//print last entry, no comma
printf("%s",my_event_data[4]);
}
void printEventsInorder()
{
struct node * ptr = head;
while (ptr != NULL)//if not empty, check each one and add when ready
{
printEventData(ptr->event_data);
printf("\n");
ptr = ptr->next;
}
}
void insertFront(char* my_event_data[5])
{
struct node *link = (struct node*) malloc(sizeof(struct node));
link->next = NULL;
for (int i = 0; i < 5; i++)
{
link->event_data[i] = my_event_data[i];
}
head = link;
}
int isEarlier(char* event_data_L[5], char* event_data_R[5])
{// will be given like 12:30 12:45,turn timeL into timeL1 and timeL2, and time R1 and timeR2
//compare dates for earlier
int month_L,day_L,year_L;
int month_R,day_R,year_R;
char* char_holder;
substring(event_data_L[2],char_holder,0,2);//extract first half of time
month_L = atoi(char_holder); //convert first half of time to int
substring(event_data_L[2],char_holder,3,2);//extract first half of time
day_L = atoi(char_holder); //convert first half of time to int
substring(event_data_L[2],char_holder,6,4);//extract first half of time
year_L = atoi(char_holder); //convert first half of time to int
substring(event_data_R[2],char_holder,0,2);//extract first half of time
month_R = atoi(char_holder); //convert first half of time to int
substring(event_data_R[2],char_holder,3,2);//extract first half of time
day_R = atoi(char_holder); //convert first half of time to int
substring(event_data_R[2],char_holder,6,4);//extract first half of time
year_R = atoi(char_holder); //convert first half of time to int
int time_L1,time_L2,time_R1,time_R2;
substring(event_data_L[3],char_holder,0,2);//extract first half of time
time_L1 = atoi(char_holder); //convert first half of time to int
substring(event_data_L[3],char_holder,3,2);//extract second half of time
time_L2 = atoi(char_holder); //convert second half of time to int
substring(event_data_R[3],char_holder,0,2);
time_R1 = atoi(char_holder);
substring(event_data_R[3],char_holder,3,2);
time_R2 = atoi(char_holder);
//convert to 2 ints, first compare left ints, then right ints
if(year_L < year_R)
{
return 1;
}
else if ( year_L == year_R)
{
if (month_L < month_L)
{
return 1;
}
else if (month_L == month_L)
{
if (day_L < day_R)
{
return 1;
}
else if (day_L == day_R)
{
if (time_L1 < time_R1)
{
return 1;
}
else if (time_L1 == time_R1)
{
if (time_L2 < time_R2)
{
return 1;
}
else if (time_L2 == time_R2)
{
return 2;
}
else//else, time is greater
{
return 3;
}
}
else //left time is greater, return 3
{
return 3;
}
}
else
{
return 3;
}
}
else
{
return 3;
}
}
else //its left is greater than right so return 3 to show that
{
return 3;
}
}
void create(char* my_event_data[5]) {
//print required sentence
char * debugvar2 = my_event_data[3];
if (head == NULL)//if empty calendar, just add it
{
insertFront(my_event_data);
//printf("EARLIEST bc empty list, \n");
printf("C, ");
printEventData(my_event_data);
printf("\n");
return;
}
else
{
struct node *link = (struct node*) malloc(sizeof(struct node));
link->next = NULL;
for (int i = 1; i < 5; i++)
{
link->event_data[i] = my_event_data[i];
}
struct node *ptr = head;
struct node *prev = NULL;
if (ptr->next == NULL) //if this is the last node to check against
{
if (isEarlier(my_event_data, ptr->event_data) == 1)
{ //check against it
printf("C, ");
printEventData(my_event_data);
printf("\n");
if (prev != NULL) //if this is first item in linked list...
{
link->next = head; //assign something before head
head = link; //move head to that thing
}
if (prev != NULL)
{
prev->next = link;
}
link->next = ptr;
return;
}
else //else is equal to or later, so tack it on after:
{
ptr->next = link;
}
}
else
{
while (ptr->next != NULL)//if not empty, check each one and add when ready
{
//if next node is later than current, we are done with insertion
if (isEarlier(my_event_data,ptr->event_data) == 1)
{
if (head == ptr) //if earlier than head... insert and print
{
//printf("earlier than head!");
printf("C, ");
printEventData(my_event_data);
printf("\n");
link->next = ptr;
head = link;
}
else //if earlier than non head, insert, but dont print
{
if (prev != NULL)
{
prev->next = link;
}
link->next = ptr;
}
return;
}
else
{
prev = ptr;
ptr = ptr->next;
}
}
if (isEarlier(my_event_data,ptr->event_data) == 1) //while ptr-> is null now
{
printf("C, ");
printEventData(my_event_data);
printf("\n");
if (prev != NULL)
{
prev->next = link;
}
link->next = ptr->next;
return;
}
else
{
prev = link;
link = ptr;
}
}
return;
}
//if it gets here, it is the latest meeting, tack it on the end
//prev->ptr = link;
}
void change(char* my_event_data[5]) {
//create a link
struct node *ptr = head;
while (ptr->next != NULL)//if not empty, check each one and add when ready
{
//if next node is later than current, we are done with insertion
if (*ptr->event_data[1] == *my_event_data[1])
{
for (int i = 1; i < 5; i++)
{
ptr->event_data[i] = my_event_data[i];
}
printf("X, ");
printEventData(my_event_data);
printf("\n");
return;
}
ptr = ptr->next;
}
if (*ptr->event_data[1] == *my_event_data[1]) //check final node
{
for (int i = 0; i < 5; i++)
{
ptr->event_data[i] = my_event_data[i];
}
printf("X, ");
printEventData(my_event_data);
printf("\n");
return;
}
printf("event to change not found");
return;
//if it gets here, nothing matched the title to change
}
void delete(char* my_event_data[5])
{
struct node *ptr = head;
struct node *prev = NULL;
while (ptr != NULL)//if not empty, check each one and add when ready
{
//if next node is later than current, we are done with insertion
if ( strcmp( ptr->event_data[1], my_event_data[1] ) == 0) // if title matches, delete it
{
if (prev != NULL)
{
prev->next = ptr->next;
}
if (ptr == head)
{
head = ptr->next;
}
free(ptr);
printf("D, ");
printEventData(my_event_data);
printf("\n");
return;
}
prev = ptr;
ptr = ptr->next;
}
}
void emailFilter(char* mySubject)
{
if (strlen(mySubject) < 9)
{
return;
}
char * event_holder[5]; //holds five separate char ptrs
for (int i = 0; i < 5; i++)
{
event_holder[i] = ((char*)malloc(100 * sizeof(char*)));
}
char command_type = parseSubject(mySubject, event_holder); //parses subject line and fills event_holder. returns command type, from parsing
//call proper parsing result
if (command_type == 'C')
{
create(event_holder);
}
else if (command_type == 'X')
{
change(event_holder);
}
else if (command_type == 'D')
{
delete(event_holder);
}
}
int main(int argc, char* argv[])
{
char myItem[100];
int i = 0;
while (i < 100)
{
scanf("%[^\n]", myItem);
i++;
if ( myItem == EOF )
{
break;
}
int c;
while ((c = getchar()) != '\n' && c != EOF);
printf("i = %d\n", i);
emailFilter(myItem);
}
return 0;
}
Also please note that this error happens when I use a txt file as STDIN via the ">" symbol on the command line. Here is the file I use:
Subject: C,Meeting ,01/12/2019,15:30,NEB202
Subject: C,Meeting ,01/12/2019,16:30,NEB202
Subject: C,Meeting ,01/12/2019,11:30,NEB202
Having tried to find something to contribute, there's this:
The code is dealing with the date/time. Below is the declaration and use of a "destination buffer" into which is copied fragments of the string:
int isEarlier(char* event_data_L[5], char* event_data_R[5])
{// will be given like 12:30 12:45 // ....
//compare dates for earlier
int month_L,day_L,year_L;
int month_R,day_R,year_R;
char* char_holder;
substring(event_data_L[2],char_holder,0,2);//extract first half of time
month_L = atoi(char_holder); //convert first half of time to int
//...
Notice that char_holder isn't pointing anywhere in particular. UB...
While it represents a beginner's approach, it is actually painful to see code like this. Below is a more concise version of isEarlier() (untested.)
int isEarlier( char *ed_L[5], char *ed_R[5] ) {
char l[16], r[16];
memcpy( l + 0, ed_L[2][6],4 ); // YYYY
memcpy( l + 4, ed_L[2][0],2 ); // MM
memcpy( l + 6, ed_L[2][3],2 ); // DD
memcpy( l + 8, ed_L[3][0],2 ); // hh
memcpy( l + 10, ed_L[3][3],2 ); // mm
memcpy( r + 0, ed_R[2][6],4 ); // YYYY
memcpy( r + 4, ed_R[2][0],2 ); // MM
memcpy( r + 6, ed_R[2][3],2 ); // DD
memcpy( r + 8, ed_R[3][0],2 ); // hh
memcpy( r + 10, ed_R[3][3],2 ); // mm
int res = memcmp( l, r, 12 );
return res < 0 ? 1 : res == 0 ? 2 : 3;
}
Note: The sample data provided indicates 2 digits for both month and day, and is ambiguous as to "mm/dd" or "dd/mm" format. The offset values used here come from the OP code.
One way to reduce the possibility of bugs in code is to both write less but more capable code, if you can, and to perform "unit testing" on code that you write. Focus on one function at a time and do not use global variables. Another is to become as familiar as you can with the proven capabilities of functions in the standard library.
EDIT: Looking at this answer, it occurs to me that this function should, itself, be refactored:
void reformatDateTime( char *d, char *s[5] ) {
memcpy( d + 0, s[2][6],4 ); // YYYY
memcpy( d + 4, s[2][0],2 ); // MM
memcpy( d + 6, s[2][3],2 ); // DD
memcpy( d + 8, s[3][0],2 ); // hh
memcpy( d + 10, s[3][3],2 ); // mm
}
int isEarlier( char *ed_L[5], char *ed_R[5] ) {
char l[16], r[16];
reformatDateTime( l, ed_L );
reformatDateTime( r, ed_R );
int res = memcmp( l, r, 12 );
res = res < 0 ? 1 : res == 0 ? 2 : 3;
printf( "isEarlier() '%.12s' vs '%.12s' result %d\n", l, r, res ); // debug
return res;
}
and I can see that it runs properly
You contradict yourself, you say that it sometimes or always seg faults. It's rather unlikely that some C code would crash at the point of leaving a function, since there's no "RAII" and in this case no multi-threading either. A stack corruption could have destroyed the function return address however.
The best way of debugging is not so much about focusing on the symptom, as it trying to pinpoint where something goes wrong. You've already done as much, so that's most of the debug effort already done.
One way of debugging from there is step #1: stare at the function for one minute. After around 5 seconds: event_holder[i] = ((char*)malloc(100 * sizeof(char*))); Well that's an obvious bug. After some 30 seconds more: wait, who cleans up this memory? The delete function perhaps but why is it then executed conditionally? (Turns out delete doesn't free() memory though.) The function leaks memory, another bug. Then after one full minute we realize that parseSubject does a whole lot of things and we'll need to dig through that one in detail if we want to weed out every possible chance of bugs. And it will take a lot more time to get to the bottom of that. But we already found 2 blatant bugs just by glancing at the code.
Fix the bugs, try again, is the problem gone?
At another glance there's a bug in main(), myItem == EOF is senseless and shouldn't compile. This suggests that you are compiling with way too lax warning levels or ignoring warnings, either is a very bad thing. What compiler options are recommended for beginners learning C?
We might note that extensive use of "magic numbers" make the code hard to read. It is also usually a sure sign of brittle code. Where do these 5 and 9 and so on come from? Use named constants. We will also fairly quickly note the lack of const correctness in something that's only supposed to parse, not change data. And so on.
I didn't read the code in detail, but the overall lack of following best practices and 3 bugs found just by brief glances suggests there's a whole lot more bugs in there.

Why does the returned array differ from the array that uses the return value in my program?

I have a program where I want to add a new element into an array of structs.
In my add function it seems to be working, but when I try to use it in the main function, it seems to differ from what's being originally returned.
I have my main.c like this:
int main(void) {
Recept * receptek;
int valasztas;
int *hossz = 0; //A receptek száma.
receptek = betolt("receptek.txt", &hossz);
if (receptek != NULL) {
menu();
printf("Valasztott opcio: ");
while(scanf("%d", &valasztas) == 1) {
if(valasztas == 1) {
Recept * uj = recept_felvesz(receptek, hossz);
printf("%dTH VALUE HERE: %s\n", (int)hossz, uj[(int)hossz].nev);
if(uj != NULL) {
printf("Recept sikeresen felveve.\n\n");
hossz = (int)hossz + 1;
} else {
printf("Nem sikerult a receptet felvenni.\n\n");
}
} else if(valasztas == 2) {
kiir(receptek, (int)hossz);
} else if(valasztas == 6) {
break;
} else {
system("cls");
menu();
printf("Ervenytelen opcio.\n\n");
}
printf("Valasztott opcio: ");
}
} else {
printf("Nem sikerult betolteni a tarolofajlt!\n");
}
return 0;
}
And I store my add function (recept_felvesz) in a different .h file.
Recept* recept_felvesz(Recept* receptek, int* hossz) {
printf("Hossz 1: %d", (int)hossz);
setbuf(stdin, NULL);
char bekert_nev[30];
char bekert_ot[300];
printf("Add meg a recept nevet: ");
if(fgets(bekert_nev, 30, stdin))
bekert_nev[strcspn(bekert_nev, "\n")] = '\0'; //A \n karaktert kicseréli \0-ra
printf("Add meg a recept osszetevoit: ");
if(fgets(bekert_ot, 300, stdin))
bekert_ot[strcspn(bekert_ot, "\n")] = '\0'; //A \n karaktert kicseréli \0-ra.
system("cls");
menu();
Recept uj = {(int)hossz, bekert_nev, bekert_ot};
receptek = (Recept*) realloc(receptek, ((int)hossz + 1) * sizeof(Recept));
receptek[(int)hossz] = uj;
if (receptek == NULL) return NULL;
FILE *file = fopen("receptek.txt", "a");
if (file == NULL) return NULL;
fprintf(file, "\n%s;%s;", bekert_nev, bekert_ot);
fclose(file);
printf("\n%dTH VALUE HERE: %s\n", (int)hossz, receptek[(int)hossz].nev);
return receptek;
}
Here is the buggy output at the moment:
15TH VALUE HERE: 32423
15TH VALUE HERE: ☺
Recept sikeresen felveve.
Why does the actual return value (32423) differ from what's being used in the main function(☺)?
Edit: structure Recept looks like this:
typedef struct Recept {
int azonosito;
char *nev;
char *osszetevok;
} Recept;
In this code memory of local variables bekert_nev and bekert_ot are used outside of the scope where they are defined (function recept_felvesz). They are allocated on stack so after exit from function recept_felvesz their memory can be used by anyone else as it is considered unused. For example printf can store its internal variables in this memory block.
One way to fix this issue is to allocate bekert_nev and bekert_ot in global memory using malloc function:
char* bekert_nev = malloc(30);
char* bekert_ot = malloc(300);
Remember to free this memory with free function when you will destroy your main receptek array:
Recept* rec = receptek;
for( int i = 0; i < hossz; ++i) {
free( rec->nev );
free( rec->osszetevok );
rec++;
}
Alternatively, you can put this arrays inside of your Recept struct and write directly into them
typedef struct Recept {
int azonosito;
char nev[30];
char osszetevok[300];
} Recept;

Modifying data in a Linked List in C?

When I modify the linked list (based on the ID), it modifies the node successfully but deletes the rest of the list. The whole list stays only if I modify the most recent node that I've added to the list.
I know that the problem is at the end where it says:
phead=i;
return phead;
But I don't know how to fix it as I haven't found anything to help me, even though I'm sure it is simple to know why it is wrong.
struct ItemNode *modify1Item(struct ItemNode *phead){
int modID;
int lfound=0;
int lID;
char lDesc[30];
char lName[30];
double lUPrice;
int lOnHand;
struct ItemNode *i=phead;
printf("Enter the ID of the item that you want to modify\n");
scanf("%d", &modID);
while(i != NULL){
if(i->ID == modID){
break;
}
i= i->next;
}
if(i==NULL){
printf("An item with that ID wasn't found.\n");
return 0;
}
else{
printf("Enter new Name\n");
scanf("%s", lName);
strcpy(i->name, lName);
printf("Enter new Description\n");
scanf("%s", lDesc);
strcpy(i->desc, lDesc);
printf("Enter new Unit Price $\n");
scanf("%lf", &lUPrice);
i->uPrice = lUPrice;
printf("Enter new Number of Items On Hand\n");
scanf("%d", &lOnHand);
i->onHand = lOnHand;
}
phead=i;
return phead;
}
When I return it, i say head=modify1Item(phead);
I tested your code everything worked as expected. Without seeing your code, I can't comment much. But I think, for your code, the only time everything would get delete is if you assign the return value incorrectly. So this below is probably something close to your code. For the test code below, unless you modify it, the IDs are 0, 1, and 2. Oh and the reason why I commented only work for 0 to 9 is because I don't want to make up the entire char string so I used i ^ 48. Of which, 0 - 9 ^ 48 would turn into the correspondent ASCII code of 0 - 9. If you go beyond that, you may get weird result for that two string that all.
I just noticed that you use NULL in your search. Thus, I updated the code so the "next" of last index will be NULL otherwise if your code found nothing, it will run forever.
#include <stdio.h>
#include <string.h>
typedef struct ItemNode {
int ID;
int uPrice;
int onHand;
char name[30];
char desc[30];
struct ItemNode * next;
} ItemNode ;
struct ItemNode * modify1Item(struct ItemNode * phead){
int modID;
int lfound=0;
int lID;
char lDesc[30];
char lName[30];
double lUPrice;
int lOnHand;
struct ItemNode *i = phead;
printf("Enter the ID of the item that you want to modify\n");
scanf("%d", &modID);
while(i != NULL){
if(i->ID == modID){
break;
}
i = i->next;
}
if(i==NULL){
printf("An item with that ID wasn't found.\n");
return 0;
} else {
printf("Enter new Name\n");
scanf("%s", lName);
strcpy(i->name, lName);
printf("Enter new Description\n");
scanf("%s", lDesc);
strcpy(i->desc, lDesc);
printf("Enter new Unit Price $\n");
scanf("%lf", &lUPrice);
i->uPrice = lUPrice;
printf("Enter new Number of Items On Hand\n");
scanf("%d", &lOnHand);
i->onHand = lOnHand;
}
phead=i;
return phead;
}
int main(){
// only work for 0 - 9.
int index = 3;
ItemNode iArr[index];
for ( int i = 0; i < index; i++ ){
iArr[i].ID = i;
iArr[i].uPrice = i + i;
iArr[i].onHand = i * i;
iArr[i].name[0] = i ^ 48;
iArr[i].desc[0] = i ^ 48;
// If last index link back to first index.
// Updated: but for you usage case
// because of your search function
// last index should be NULL otherwise your
// search will run forever
if ( i < index - 1 ) iArr[i].next = &iArr[i + 1];
else iArr[i].next = NULL; // if change search method with unique ID then you can use -> &iArr[0];
}
// Mod 0
ItemNode * test = modify1Item(iArr);
printf("0 name: %s\n\n",iArr[0].name );
// Mod 1
ItemNode * test1 = modify1Item(iArr);
printf("1 name: %s\n\n",iArr[1].name );
// Mod 2
ItemNode * test2 = modify1Item(iArr);
printf("2 name: %s\n\n",iArr[2].name );
// Check if 0 is still there.
printf("0 name: %s\n\n",iArr[0].name );
return 0;
}

How to return linked list from a function?

Firstly, sorry for my bad english, hope you understand me.
I'm new into programming in general and need help in a small project our teacher asked us to do. (Homework.)
In this homework I created a linked list:
struct No {
char Nome[30];
char Endereco[30];
int Numero;
int aux;
struct No *prox;
};
typedef struct No no;
Then, I added functions to populate an array. The problem is just that one of my function isn't changing the array in any way, its like if I'm not calling the function at all.
Here are the important parts:
int main(void)
{
no *lista = (no *) malloc(sizeof(no)); //This is the linked list I'm talking about.
Contagem=0;
int iOpcao;
while(iOpcao) {
iOpcao=Escolha();
if(selecionarOpcao(lista,iOpcao) == 0)
return 0;
}
return 0;
}
int selecionarOpcao(no *entrada, int op)
{
no *tmp;
switch(op){
case 0:
return 0;
case 1:
ListarContatos(entrada);
break;
case 2:
AdicionarContato(entrada);
break;
case 3:
RemoverContato(entrada);
break;
case 4:
EditarContato(entrada);
break;
case 5:
entrada = OrganizarLista(entrada); //This is the function not working correctly, the other ones are working perfectly fine.
break;
default:
printf("Comando invalido\n\n");
}
return 1;
}
And finally the function itself:
no* OrganizarLista(no* entrada) {
no* ordenada = (no *) malloc(sizeof(no));
no* temp = entrada;
no* maiorNo = NULL;
while(1 == 1) {
while(temp != NULL) {
temp = temp->prox;
if(temp != NULL) {
if(JaExistente(ordenada, temp->Numero) == 1)
continue;
if(temp->prox != NULL && maiorNo == NULL) {
if(JaExistente(ordenada, temp->prox->Numero) == 1) {
maiorNo = temp;
continue;
}
//printf("%s contra %s", temp->Nome, temp->prox->Nome);
if(maiorNo == NULL)
maiorNo = CompararNos(temp, temp->prox);
//printf("%s ganhou.\n", maiorNo->Nome);
}
else if(maiorNo != NULL) {
//printf("%s contra %s", maiorNo, temp->Nome);
maiorNo = CompararNos(maiorNo, temp);
//printf("%s ganhou.\n", maiorNo->Nome);
}
}
}
if(maiorNo != NULL) {
//printf("Maiorno->nome = %s", maiorNo->Nome);
AdicionarLista(ordenada, maiorNo->Nome, maiorNo->Endereco, maiorNo->Numero, 1);
temp = entrada;
maiorNo = NULL;
}
else {
temp = entrada;
while(temp != NULL) {
if(JaExistente(ordenada, temp->Numero) == 0)
AdicionarLista(ordenada, temp->Nome, temp->Endereco, temp->Numero, 1);
temp = temp->prox;
}
break;
}
}
free(temp);
return ordenada;
}
I spent the whole day trying to figure it out however it is still not working. When I check the values inside the function they are all correct but when the values are returned it seems like the program just ignore them.
Any help is appreciated, again, sorry for my english and thanks everyone!
You are trying to set a new value for parameter that was sent by value.
In order to send a pointer or any variable to a function and let the function change its value, you should send it by reference, its address.
Assumimg you have the following functions:
void changePtr(no **ptr) {
*ptr = // .. some value
}
void dontChangePtr(no *ptr) {
ptr = // some value
}
You should notice the differences between the function calls:
no *n = (no*)malloc(sizeof(no));
dontChangePtr(n); // n will be sent by value and will not be changed
changePtr(&n); // n will be sent by reference and will be changed

Searching through a linked list.

So i've been trying to understand the difference between a regularly defined structure without using malloc linked list that does utilize malloc.
The issue that i'm having right now is trying to search through the structure (pi) to find each part number that has a cost greater than what was entered into the search. this is my entire program so far. I've added comments for each section.
I'm simply not sure how i am suppose to search through each structure to compare its price to the search price.
#include <stdio.h>
#include <stdlib.h>
struct Item {
int quantity;
float cost;
char partNum[10];
struct Item *next;
};
void printItem(struct Item* pi);
void enterItem(struct Item* pi);
char search [100];
void main(int argc, char* argv[])
{
struct Item *pi;
struct Item *head;
int done = 0;
int i,j;
char choice;
// ENTERING ITEM INTO THE STRUCTURE
head = NULL;
while (!done) {
printf("Enter another item? (y/n)");
choice = getchar();
if (choice == 'y' || choice == 'Y') {
pi = (struct Item *)malloc(sizeof(struct Item));
enterItem(pi);
pi->next = head;
head = pi;
} else {
done = 1;
}
}
// SEARCHING FOR ITEM BY PRICE
printf("Enter a price to find all items more expensive, or type 'exit':");
while (strcmp(search, "exit") !=0) {
gets(search);
for (j = 0; j<i ; i++) {
if (strcmp(pi[j].cost, search) ==0) {
printItem(pi);
pi = pi->next;
}
}
}
}
getchar();
getchar();
}
// FUNCTION FOR PRINTING STRUCTURE ITEM
void printItem(struct Item* pi) {
printf("Quantity: %d\n", pi->quantity);
printf("Cost: $%.2f\n", pi->cost);
printf("Part # %s\n", pi->partNum);
printf("\n\n");
}
// FUNCITON FOR ENTERING IN NEW ITEM
void enterItem(struct Item* pi) {
printf("Quantity? ");
scanf("%d", &pi->quantity);
printf("Cost? ");
scanf("%f", &pi->cost);
getchar(); //need to clear out the carriage return from typeing in the cost
printf("Part Number? ");
gets(pi->partNum);
}
What you were doing wrong is comparing string(search variable) with a float(cost variable) using strcmp. This won't give you the desired output.
Instead, lets use -1 to indicate the exit, since parsing string and converting it to float is off-topic. Start iterating from head up to finding NULL, and compare the prices of the each item.
float price;
struct Item *it = head;
printf("Enter a price to find all items more expensive, or type '-1' to exit:");
scanf("%f", price);
// check price for the 'exit' -- compare with -1
while (it != NULL) {
if (it->cost > price)
printItem(pi);
it = it->next;
}

Resources