我编写了以下代码段,并且无法理解为什么它不会到达最后一个printf行。我在第4行后立即得到一个段错误.kill_char仅用于杀死前一个scanf中添加的'enter'字符。非常感谢任何帮助,谢谢!
int remove = 0;
char kill_char = 'a';
printf("Enter the product number to be removed: ");
scanf("%d", &remove);
scanf("%c", &kill_char);
printf("Does not get here");
编辑: 完整代码如下,removeProduct函数中的错误
#include <stdio.h>
#include <stdlib.h>
struct product_node {
char *supply_type;
long number;
char *description;
float price;
int quantity_bought;
float retail_price;
int quantity_sold;
struct product_node *next;
};
struct product_node *head;//declaring head out here
//allows the list to be in scope for the functions
/*Function Prototypes*/
void addProduct();
void removeProduct();
void listProduct();
void listSupplierTypes();
void supplierTypeProfit();
void totalProfit();
void addProduct(){
char kill_char = 'a';//used to kill the enter characters
struct product_node *new_node;
new_node = malloc(sizeof(struct product_node));
printf("\nEnter a string for type: ");
scanf( "%s", &(*new_node).supply_type);
scanf("%c", &kill_char);
printf("Enter the product number: ");
scanf("%ld", &(*new_node).number);
scanf("%c", &kill_char);
printf("Enter the description: ");
scanf("%s", &(*new_node).description);
scanf("%c", &kill_char);
printf("Enter the wholesale price: ");
scanf("%f", &(*new_node).price);
scanf("%c", &kill_char);
printf("Enter the quantity bought: ");
scanf("%d", &(*new_node).quantity_bought);
scanf("%c", &kill_char);
printf("Enter the retail price: ");
scanf("%f", &(*new_node).retail_price);
scanf("%c", &kill_char);
printf("Enter the quantity sold: ");
scanf("%d", &(*new_node).quantity_sold);
scanf("%c", &kill_char);
struct product_node *walker;
walker = head;
int can_insert = 1;
while (!(walker == NULL))
{
if (((*walker).number == (*new_node).number) && ((*walker).supply_type == (*new_node).supply_type))
{
can_insert = 0;
}
walker = (*walker).next;
}
if (can_insert==1)
{
(*new_node).next = head;
head = new_node;
printf("Insertion Successful");
}
else
{
printf("\nERROR INSERTING:This product name and number is already in the list\n");
}
free(new_node);
}
void removeProduct(){
int remove = 0;
char kill_char = 'a';
printf("Enter the product number to be removed: ");
scanf("%d", &remove);
scanf("%c", &kill_char);
printf("Does not get here");
struct product_node *walker;
struct product_node *prev;
prev = head;
walker = (*head).next;
if ((*prev).number == remove)
{
head = walker;
}//points head to second node to remove first
while (!(walker = NULL))
{
if ((*walker).number == remove)
{
(*prev).next = (*walker).next;
}
}
}
void listProduct(){
printf("Still unsure what defines a supplier...");
}
void listSupplierTypes(){
printf("Same as above");
}
void supplierTypeProfit(){
printf("Again");
}
void totalProfit(){
float total = 0.0;
struct product_node *walker;
walker = head;
while(!(walker == NULL))
{
total += ((float)(*walker).quantity_sold * (*walker).retail_price) - ((float)(*walker).quantity_bought * (*walker).price);
walker = (*walker).next;
}
printf("Total Profit is: $%.2f\n", total);
}
int main()
{
head = NULL;
char *temp_type;
char *temp_description;
int temp_number, temp_quantity_bought, temp_quantity_sold;
float temp_price, temp_retail_price;
while(!feof(stdin))
{
scanf( "%s %ld %s %f %d %f %d\n", &temp_type, &temp_number, &temp_description, &temp_price, &temp_quantity_bought, &temp_retail_price, &temp_quantity_sold);
struct product_node *new_node;
new_node = malloc(sizeof(struct product_node));
(*new_node).next = head;
head = new_node;
(*head).supply_type = temp_type;
(*head).number = temp_number;
(*head).description = temp_description;
(*head).price = temp_price;
(*head).quantity_bought = temp_quantity_bought;
(*head).retail_price = temp_retail_price;
(*head).quantity_sold = temp_quantity_sold;
}
freopen("/dev/tty", "rw", stdin);
int done=0;
int selection=0;
while (!done)
{
printf("\nMENU OPTIONS:\n");
printf("1. Add a product number\n");//Okay
printf("2. Remove a product number\n");
printf("3. List the products for a supplier\n");
printf("4. List all unique supplier types\n");
printf("5. Show profit margin for a specific supplier type\n");
printf("6. Show total profit\n");//Okay
printf("7. Quit\n");//Okay
printf("Enter a selection (1-7): ");
scanf("%d", &selection);
char garbage = 'a';
scanf("%c", &garbage);
switch(selection){
case 1:
addProduct();
break;
case 2:
removeProduct();
break;
case 3:
listProduct();
break;
case 4:
listSupplierTypes();
break;
case 5:
supplierTypeProfit();
break;
case 6:
totalProfit();
break;
case 7:
done = 1;
break;
default:
printf("Invalid selection.\n");
break;
}
}
}
答案 0 :(得分:3)
remove
是标准函数的名称,在<stdio.h>
中声明。定义您自己的对象或具有相同名称的其他实体具有未定义的行为。该调用可能会尝试在int
函数的地址存储remove()
值。
尝试选择其他名称。
更新:我认为我错了。标准标题中定义的函数名称保留用作带有外部链接的标识符 ;如果相关标题是#include
d,它们还保留用作宏名称和文件范围的标识符。在您的情况下也不适用。不过,最好避免自己定义这些标识符。
此外,这可能与您所看到的症状无关,但
scanf("%d", &obj);
如果输入是一个语法上有效的整数,具有未定义的行为,其值超出int
的范围。
执行确实到达“不要到达此处”行。您没有看到它,因为在程序死亡之前不会打印缓冲的输出。改变这个:
printf("Does not get here");
到此:
printf("Does not get here\n");
fflush(stdout);
当我在gdb
下运行程序时,我看到了seg错误:
if ((*walker).number == remove)
我在编译期间也收到了几个警告:
c.c: In function ‘addProduct’:
c.c:32:5: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat]
c.c:38:5: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat]
c.c: In function ‘main’:
c.c:134:9: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat]
c.c:134:9: warning: format ‘%ld’ expects argument of type ‘long int *’, but argument 3 has type ‘int *’ [-Wformat]
c.c:134:9: warning: format ‘%s’ expects argument of type ‘char *’, but argument 4 has type ‘char **’ [-Wformat]
很容易导致内存损坏。修复这些并看看会发生什么。
更新2:
我不知道你的代码可能还有哪些程序,但是这个:
while (!(walker = NULL))
{
if ((*walker).number == remove)
{
(*prev).next = (*walker).next;
}
}
几乎肯定是错的。您正在使用作业=
运算符,您可能希望进行相等比较==
。在修好之后,代码将更加清晰如下:
while (walker != NULL)
{
if (walker->number == remove)
{
prev->next = walker->next;
}
}
当我快速查看gdb告诉我段错误在if ((*walker).number == remove)
上时,这就是我跳出来的东西。
尝试自己使用调试器,一次修复一个问题,并注意任何编译器警告。
答案 1 :(得分:0)
你的printf没有出现,因为它没有从缓冲区中刷新,只需在字符串的末尾使用“\ n”,你就会看到它:
printf("Does not get here\n");
所以,错误不是scanf
,而是在这一行:
walker = (*head).next;
正如我所看到的,程序可能会在未分配head
的情况下到达那里,因此您可以在函数开头检查它:
void removeProduct(){
int remove = 0;
char kill_char = 'a';
if (head == NULL) {
printf("No product to remove!\n");
return;
}
我不确定是否还有其他错误,但这是我注意到的错误。
BTW,您可以通过在kill_char
上的格式字符串的开头和结尾插入空格来避免使用scanf
:
scanf(" %d ", &remove);
它将跳过所有白色字符(如标签,空格和断路器)。而且,如果你真的只想跳过一个,只有一个角色,你可以使用*
忽略匹配:
scanf("%d%*c", &remove);