C编程打印链表,不沿列表移动并崩溃
C programming printing a linked list, not moving along list and crashing
我正在尝试打印一个链表,它的行为很奇怪,当它应该移动到下一个项目时它不会,例如第一个打印的项目是 "Granny Smith" 然后其余的在结构,当它转到下一行时,新食物应该是 "ranny Smith" 总是没有 G,并且大多数其他细节都已损坏或乱码。任何帮助将不胜感激。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define cls system("cls");
#define flush fflush(stdin)
#define pause system("pause");
struct food // Declaration of struct
{
char produce[20];
char type[20];
char soldBy[20];
float price;
int quantityInStock;
struct food *next;
};
void addPres(struct food** tip, char tokenPro[20], char tokenType[20], char tokenSold[20], float tokenFloat, int tokenInt);
void display ();
void displayMenu ();
int getChoice ();
void readDataIn();
int main()
{
int choice = 0;
int ;
struct food first;
char *saveFloat, *saveInt;
char tokenPro[20], tokenType[20], tokenSold[20], savePro[20], saveType[20], saveSold[20], j[1900];
float tokenFloat, messFloat;
int danint, tokenInt;
struct food* a = NULL;
FILE* file;
a = NULL; // sets the first item on the list to empty
//readDataIn();
do
{
choice = getChoice();//function to present choices and receive an answer
switch (choice)//switch routes the choice
{
case 1: //to enter a new node on the list
cls;
printf("Enter the produce type: ");
fgets(tokenPro, 20, stdin);
printf("Enter the type: ");
fgets(tokenType, 20, stdin);
printf("Enter the units of measurement: ");
fgets(tokenSold, 20, stdin);
printf("\nEnter the price per %s: ", &tokenSold);
scanf("%f", &tokenFloat );
printf("\nEnter the quantity in stock: ");
scanf("%i", &tokenInt );
//pause;
addPres(&a, tokenPro, tokenType, tokenSold, tokenFloat, tokenInt);
break;
case 2: //to display the linked list
display(a);
break;
case 3: //to reverse the order
if((file=fopen("AssignmentTwoInput.txt", "r")) != NULL) //opens files
{
while(fgets(j, sizeof(j), file)) //while information is being sent to j from the file
{
strcpy(savePro, strtok(j, ","));
strcpy(saveType, strtok(NULL, ","));
strcpy(saveSold, strtok(NULL, ","));
saveFloat = strtok(NULL, ",");
saveInt = strtok(NULL, "\n");
messFloat = atof(saveFloat); //ID number is assigned to token2
danint = atoi(saveInt); //converts the value token2 points to into an int (previously read in as an string)
addPres(&a, savePro, saveType, saveSold, messFloat, danint); //sends the name and ID to the function to add a person
//printf("\n %s \t %s \t %s \t %f \t %i", savePro, saveType, saveSold, messFloat, danint);
//pause;
}//end while loop
}//end if loop
printf("\nSuccessfully loaded input file\n\n\n"); //message to tell user the back was found and imported successfully
pause;
fclose(file);
break;
case 4: //to export data
break;
case 5: //option to exit
exit(0);
break;
default://error checking
printf("Please enter a valid choice.\n");
break;
}//switch loop close
}
while (choice != 5); //end menu choices
return 0;
}//end main
void addPres(struct food** tip, char tokenPro[20], char tokenType[20], char tokenSold[20], float tokenFloat, int tokenInt)
{
struct food* temp =
(struct food*) malloc(sizeof(struct food));
strcpy(temp->produce, tokenPro);
strcpy(temp->type, tokenType);
strcpy(temp->soldBy, tokenSold);
temp->price = tokenFloat;
temp->quantityInStock = tokenInt;
//printf("\n %s \t %s \t %s \t %f \t %i", temp->produce, temp->type, temp->soldBy, temp->price, temp->quantityInStock);
//pause;
if (tip == NULL) //if the tip node is empty
{
tip = temp; //tip node becomes this node
(*tip)->next = NULL; // since there are no others yet the next node will be empty
}
else
{
temp->next = tip; // reassigns the tip node to the next one
(*tip) = temp; //inserts current node as the tip
}
}
void display(struct food* c)
{
//c = first; //assigns c to the first node on the linked list
int count = 1;
struct food *temp;
temp = c;
cls;
printf("==========================================================================\n"); //prints a header to say which info is which
printf(" Item # Produce Type Sold By Price In Stock\n");
printf("==========================================================================\n");
while( c != NULL)
{
printf("%3i \t", count);
printf("%s \t", c->produce ); //prints name
printf("%s \t", c->type ); //prints name
printf("%s \t", c->soldBy); //prints name
printf("%-3.2f \t", c->price); //prints ID
printf("%i\n", c->quantityInStock); //prints ID
pause;
count = count + 1;
c = c->next; //advances to next item in the linked list
if(c == NULL)
{
printf("\n end \n"); //once end is found user is told
pause;
}
}
printf("\n done \n");
pause;
}//end display
你犯了三个重要的错误,其中一个好像是复制粘贴了一些代码造成的,
此 printf()
语句会导致未定义的行为
printf("\nEnter the price per %s: ", &tokenSold);
因为你传递了正确的地址但指针类型错误所以指针运算将导致内部未定义的行为printf()
printf("\nEnter the price per %s: ", tokenSold);
/* remove the & --------------------^ here */
您向 addPres
传递了一个双指针,但您从未取消引用它以访问实际的指针,这就是您要修改的内容,这会导致未定义的行为和观察到的一个空列表的效果,因为一旦函数 returns 它没有改变原来的指针,你应该在这个函数中使用解引用运算符访问双指针,例如而不是
if (tip == NULL)
必须
if (*tip == NULL)
同样适用于此函数内的每次访问。
我怎么这么快就发现了所有这些问题?
Because I compiled your programs with compiler warnings enabled and it started showing those problems.
您的代码中还会有其他问题吗?
Yes probably, but you need to fix these first.
你fflush(stdin)
,一个很常见的错误,似乎来自一些教程或书籍或在线资源,标准明确指出fflush()
是用于输出流,并且输入流的行为未定义,以下摘自 C11 草案
7.21.5.2 The fflush function
- If stream points to an output stream or an update stream in which the most recent
operation was not input, the
fflush
function causes any unwritten data for that stream
to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined.
我正在尝试打印一个链表,它的行为很奇怪,当它应该移动到下一个项目时它不会,例如第一个打印的项目是 "Granny Smith" 然后其余的在结构,当它转到下一行时,新食物应该是 "ranny Smith" 总是没有 G,并且大多数其他细节都已损坏或乱码。任何帮助将不胜感激。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define cls system("cls");
#define flush fflush(stdin)
#define pause system("pause");
struct food // Declaration of struct
{
char produce[20];
char type[20];
char soldBy[20];
float price;
int quantityInStock;
struct food *next;
};
void addPres(struct food** tip, char tokenPro[20], char tokenType[20], char tokenSold[20], float tokenFloat, int tokenInt);
void display ();
void displayMenu ();
int getChoice ();
void readDataIn();
int main()
{
int choice = 0;
int ;
struct food first;
char *saveFloat, *saveInt;
char tokenPro[20], tokenType[20], tokenSold[20], savePro[20], saveType[20], saveSold[20], j[1900];
float tokenFloat, messFloat;
int danint, tokenInt;
struct food* a = NULL;
FILE* file;
a = NULL; // sets the first item on the list to empty
//readDataIn();
do
{
choice = getChoice();//function to present choices and receive an answer
switch (choice)//switch routes the choice
{
case 1: //to enter a new node on the list
cls;
printf("Enter the produce type: ");
fgets(tokenPro, 20, stdin);
printf("Enter the type: ");
fgets(tokenType, 20, stdin);
printf("Enter the units of measurement: ");
fgets(tokenSold, 20, stdin);
printf("\nEnter the price per %s: ", &tokenSold);
scanf("%f", &tokenFloat );
printf("\nEnter the quantity in stock: ");
scanf("%i", &tokenInt );
//pause;
addPres(&a, tokenPro, tokenType, tokenSold, tokenFloat, tokenInt);
break;
case 2: //to display the linked list
display(a);
break;
case 3: //to reverse the order
if((file=fopen("AssignmentTwoInput.txt", "r")) != NULL) //opens files
{
while(fgets(j, sizeof(j), file)) //while information is being sent to j from the file
{
strcpy(savePro, strtok(j, ","));
strcpy(saveType, strtok(NULL, ","));
strcpy(saveSold, strtok(NULL, ","));
saveFloat = strtok(NULL, ",");
saveInt = strtok(NULL, "\n");
messFloat = atof(saveFloat); //ID number is assigned to token2
danint = atoi(saveInt); //converts the value token2 points to into an int (previously read in as an string)
addPres(&a, savePro, saveType, saveSold, messFloat, danint); //sends the name and ID to the function to add a person
//printf("\n %s \t %s \t %s \t %f \t %i", savePro, saveType, saveSold, messFloat, danint);
//pause;
}//end while loop
}//end if loop
printf("\nSuccessfully loaded input file\n\n\n"); //message to tell user the back was found and imported successfully
pause;
fclose(file);
break;
case 4: //to export data
break;
case 5: //option to exit
exit(0);
break;
default://error checking
printf("Please enter a valid choice.\n");
break;
}//switch loop close
}
while (choice != 5); //end menu choices
return 0;
}//end main
void addPres(struct food** tip, char tokenPro[20], char tokenType[20], char tokenSold[20], float tokenFloat, int tokenInt)
{
struct food* temp =
(struct food*) malloc(sizeof(struct food));
strcpy(temp->produce, tokenPro);
strcpy(temp->type, tokenType);
strcpy(temp->soldBy, tokenSold);
temp->price = tokenFloat;
temp->quantityInStock = tokenInt;
//printf("\n %s \t %s \t %s \t %f \t %i", temp->produce, temp->type, temp->soldBy, temp->price, temp->quantityInStock);
//pause;
if (tip == NULL) //if the tip node is empty
{
tip = temp; //tip node becomes this node
(*tip)->next = NULL; // since there are no others yet the next node will be empty
}
else
{
temp->next = tip; // reassigns the tip node to the next one
(*tip) = temp; //inserts current node as the tip
}
}
void display(struct food* c)
{
//c = first; //assigns c to the first node on the linked list
int count = 1;
struct food *temp;
temp = c;
cls;
printf("==========================================================================\n"); //prints a header to say which info is which
printf(" Item # Produce Type Sold By Price In Stock\n");
printf("==========================================================================\n");
while( c != NULL)
{
printf("%3i \t", count);
printf("%s \t", c->produce ); //prints name
printf("%s \t", c->type ); //prints name
printf("%s \t", c->soldBy); //prints name
printf("%-3.2f \t", c->price); //prints ID
printf("%i\n", c->quantityInStock); //prints ID
pause;
count = count + 1;
c = c->next; //advances to next item in the linked list
if(c == NULL)
{
printf("\n end \n"); //once end is found user is told
pause;
}
}
printf("\n done \n");
pause;
}//end display
你犯了三个重要的错误,其中一个好像是复制粘贴了一些代码造成的,
此
printf()
语句会导致未定义的行为printf("\nEnter the price per %s: ", &tokenSold);
因为你传递了正确的地址但指针类型错误所以指针运算将导致内部未定义的行为
printf()
printf("\nEnter the price per %s: ", tokenSold); /* remove the & --------------------^ here */
您向
addPres
传递了一个双指针,但您从未取消引用它以访问实际的指针,这就是您要修改的内容,这会导致未定义的行为和观察到的一个空列表的效果,因为一旦函数 returns 它没有改变原来的指针,你应该在这个函数中使用解引用运算符访问双指针,例如而不是if (tip == NULL)
必须
if (*tip == NULL)
同样适用于此函数内的每次访问。
我怎么这么快就发现了所有这些问题?
Because I compiled your programs with compiler warnings enabled and it started showing those problems.
您的代码中还会有其他问题吗?
Yes probably, but you need to fix these first.
你
fflush(stdin)
,一个很常见的错误,似乎来自一些教程或书籍或在线资源,标准明确指出fflush()
是用于输出流,并且输入流的行为未定义,以下摘自 C11 草案7.21.5.2 The fflush function
- If stream points to an output stream or an update stream in which the most recent
operation was not input, the
fflush
function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined.
- If stream points to an output stream or an update stream in which the most recent
operation was not input, the