2016-10-26 34 views
-1

我是新來的C,和我一直在寫一個簡單的腳本象下面這樣:Ç得到段錯誤

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

typedef enum {FALSE, TRUE} bool; 

// item_t: information for a single item to be purchased 
typedef struct _item_t { 
    char name[50]; 
    int price; 
    int quantity; 
} item_t; 

// cart_t: information for the shopping cart 
typedef struct _cart_t { 
    item_t *items[10]; 
    int size; 
} cart_t; 

// Returns index of item with name `item_name` in the `items` array inside of `cart`. Returns -1 if not found. 
int find_item(cart_t *cart, const char* item_name) { 
    int i; 
    for(i=0;i<sizeof(*cart);++i){ 
     if(strcmp(cart->items[i]->name,item_name) == 0){ 
      return i; 
     } 
    } 

    if(i == sizeof(*cart) -1) 
     return -1; 
    return 0; 
} 

// Adds item to cart's items array, if the cart is not full. Returns `FALSE` if the cart is full, and returns `TRUE` otherwise. 
bool add_new_item(cart_t *cart, item_t *item) { 
    if(10 == cart->size) 
     return FALSE; 
    else{ 
     int i = cart->size; 
     cart->items[i] = item; 
     cart->size +=1; 
     return TRUE; 
    } 
} 

// Increases quantity by one of item with name `item_name` inside of `cart`, if such an item exists. 
void add_existing_item(cart_t *cart, const char* item_name) { 
    int i = find_item(cart,item_name); 
    if(i == -1) 
     return; 
    else{ 
     cart->items[i]->quantity += 1; 
    } 
} 

// Removes item with name from cart's items array. Returns a pointer to the removed item, and shifts the items to the right of the deleted item in the `items` array 
// left to fill in the gap. 
// If the item is not found, return NULL. 
item_t* remove_item(cart_t *cart, char *remove_me) { 
     item_t *p; 
     int j = 0; 
     int i = find_item(cart,remove_me); 
     if(i == -1) 
      return NULL; 
     else{ 

      if(i == cart->size-1){ 
       p = cart->items[i]; 
       cart->items[i] = NULL; 
      }else{ 
       p = cart->items[i]; 
       for(j=i;j<cart->size-1;++j){ 
        cart->items[j] = cart->items[j+1]; 
       } 
       cart->items[cart->size-1] = NULL; 
       cart->size -= 1; 
      } 
      return p; 
     } 
    } 

// Determines and returns the total cost of items in cart. 
int total_cost(cart_t *cart) { 
    int total; 
    int i; 
    for(i=0;i<sizeof(*cart);++i){ 
     total += cart->items[i]->quantity * cart->items[i]->price; 
    } 
    return total; 
} 

//print item's info and cost. 
void print_item_cost(item_t *item) { 
    printf("%s %d @ $%d = $%d\n", item->name, item->quantity, 
      item->price, (item->price * item->quantity)); 
} 

//print the shopping cart info 
void print_total(cart_t *cart) { 
    int i = 0; 
    int cost = 0; 

    printf("Number of Items: %d\n\n", num_items(cart)); 

    if (cart->size > 0) { 
     for (i = 0; i < cart->size; ++i) { 
      print_item_cost(cart->items[i]); 
     } 
    } 

    else { 
     printf("SHOPPING CART IS EMPTY\n"); 
    } 

    cost = total_cost(cart); 

    printf("\nTotal: $%d\n", cost); 
} 

//this function clears items in the cart 
void clear_cart(cart_t *cart) { 
    int i = 0; 
    for (i = 0; i < cart->size; i++) { 
     free(cart->items[i]); 
    } 
    cart->size = 0; 
} 

//a menu of options to manipulate the shopping cart 
void print_menu(cart_t *cart) { 
    char choice = ' '; 
    char name[50] = ""; 
    int price = 0; 
    int quantity = 0; 
    int i = 0; 
    char c = ' '; 
    item_t *item; 

    while(choice != 'q') { 

     printf("MENU\n"); 
     printf("a - Add item to cart\n"); 
     printf("r - Remove item from cart\n"); 
     printf("c - Change item quantity\n"); 
     printf("o - Output shopping cart\n"); 
     printf("q - Quit\n\n"); 

     while (choice != 'a' && 
       choice != 'r' && 
       choice != 'c' && 
       choice != 'o' && 
       choice != 'q') { 
      printf("Choose an option: "); 
      scanf(" %c", &choice); 
      printf("\n"); 
     } 

     switch (choice) { 
      case 'a': 
       while ((c = getchar()) != EOF && c != '\n'); 

       printf("ADD ITEM TO CART\n"); 
       printf("Enter the item name: "); 
       fgets(name, 50, stdin); 
       printf("\n"); 

       i = find_item(cart, name); 
       if (i != -1) { 
        printf("Item found. Updating quantity of item. \n"); 
        add_existing_item(cart, name); 

        choice = ' '; 
        printf("\n"); 
        break; 
       } 

       if (cart->size >= 10) { 
        printf("Cart full. Cannot add new item. \n"); 

        choice = ' '; 
        printf("\n"); 
        break; 
       } 

       printf("Enter the item price: "); 
       scanf("%d", &price); 
       printf("\n"); 

       printf("Enter the item quantity: "); 
       scanf("%d", &quantity); 
       printf("\n"); 


       item = (item_t*)malloc(sizeof(item_t)); 
       strcpy(item->name, name); 
       item->price = price; 
       item->quantity = quantity; 
       add_new_item(cart, item); 

       choice = ' '; 
       printf("\n"); 

       break; 

      case 'r': 
       while ((c = getchar()) != EOF && c != '\n'); 

       printf("REMOVE ITEM FROM CART\n"); 
       printf("Enter name of item to remove: "); 
       fgets(name, 50, stdin); 
       printf("\n"); 

       item = remove_item(cart, name); 
       if (item == NULL) { 
        printf("Item not found. \n"); 
       } 
       else { 
        printf("Item removed. \n"); 
        free(item); 
       } 

       choice = '\0'; 
       printf("\n"); 
       break; 

      case 'c': 

       while ((c = getchar()) != EOF && c != '\n'); 

       printf("CHANGE ITEM QUANTITY\n"); 
       printf("Enter the item name: "); 
       fgets(name, 50, stdin); 
       printf("\n"); 

       i = find_item(cart, name); 

       if (i == -1) { 
        printf("Item not found. \n"); 
        choice = ' '; 
        printf("\n"); 
        break; 
       } 

       printf("Enter the item price: "); 
       scanf("%d", &price); 
       printf("\n"); 


       printf("Enter the new quantity: "); 
       scanf("%d", &quantity); 
       printf("\n"); 

       update_item_in_cart(cart, name, price, quantity); 

       choice = '\0'; 
       printf("\n"); 

       break; 

      case 'o': 
       while ((c = getchar()) != EOF && c != '\n'); 
       printf("OUTPUT SHOPPING CART\n"); 
       print_total(cart); 
       choice = ' '; 
       printf("\n"); 
       break; 

     } 
    } 
    clear_cart(cart); 
} 

int main(){ 
    // malloc 
    cart_t *cart; 
    cart = (cart_t*)malloc(sizeof(cart_t)); 
    cart->size = 0; 

    print_menu(cart); 

    //free 
    free(cart); 
    return 0; 
} 

它可能看起來很長,但這個想法是簡單的,它在一個購物車模擬項目,它會接收命令添加項目/刪除項目/更改數量/顯示當前購物車信息。但是,在調試開始時,當我在命令窗口中執行以下操作時:

$ ./try 
MENU 
a - Add item to cart 
r - Remove item from cart 
c - Change item quantity 
o - Output shopping cart 
q - Quit 

Choose an option: a 

ADD ITEM TO CART 
Enter the item name: tira 

Segmentation fault (core dumped) 

我正在收到段錯誤。我想知道這裏的bug可能是什麼?我對C真的很陌生,不確定指針在我的代碼中的正確性。

PS: 感謝您的回覆,是的,它幫助我解決了add_new_item函數中的錯誤。然而,當我調試remove_item,它再次以分段故障終止,在命令行看起來象下面這樣:

$ ./try 
MENU 
a - Add item to cart 
r - Remove item from cart 
c - Change item quantity 
o - Output shopping cart 
q - Quit 

Choose an option: a 

ADD ITEM TO CART 
Enter the item name: shoes 

Enter the item price: 1 

Enter the item quantity: 2 


MENU 
a - Add item to cart 
r - Remove item from cart 
c - Change item quantity 
o - Output shopping cart 
q - Quit 

Choose an option: r 

REMOVE ITEM FROM CART 
Enter name of item to remove: shoes 

Item removed. 

MENU 
a - Add item to cart 
r - Remove item from cart 
c - Change item quantity 
o - Output shopping cart 
q - Quit 

Choose an option: o 

OUTPUT SHOPPING CART 
Segmentation fault (core dumped) 
+0

在你正在使用的兩個函數中,返回未初始化的'int total'的值(參見編譯器警告)。 –

+0

你也使用循環'for(i = 0; i

回答

3

一個問題,至少是在find_item功能。 sizeof(*cart)與購物車中物品的實際數量無關,sizeof返回數據結構中的字節數。在這種情況下,至少有44個字節(假設4字節的int和4字節的指針)。你應該該功能更改爲類似這樣:

// Returns index of item with name `item_name` in the `items` array inside of `cart`. Returns -1 if not found. 
int find_item(cart_t *cart, const char* item_name) { 
    int i; 
    for(i=0;i<cart->size;++i){ 
     if(strcmp(cart->items[i]->name,item_name) == 0){ 
      return i; 
     } 
    } 

    return -1; // if we get here, then no items were found, so return -1. 
       // I don't understand your logic in returning 0, since 0 is a valid item index 
} 

正如注意到@Fang,與sizeof(*cart)混淆了你的購物車(cart->size)項目的數量在整個代碼中的常見錯誤。這將需要改變你試圖迭代你的物品的任何地方。

+1

類似地,在輸出函數中使用cart Fang

2

在你的代碼,導致段錯誤是在find_item功能的問題,您使用的sizeof關鍵字,您應該使用您的購物車的size屬性。

sizeof爲您提供了購物車結構的大小(永不會更改),而您將購物車中的物品數量存儲在其size屬性中。

這意味着你的功能應該是:

// Returns index of item with name `item_name` in the `items` array inside of `cart`. Returns -1 if not found. 
int find_item(cart_t *cart, const char* item_name) { 
    int i; 
    for(i=0;i<cart->size;++i){ 
     if(strcmp(cart->items[i]->name,item_name) == 0){ 
      return i; 
     } 
    } 

    if(i == cart->size) 
     return -1; 
    return 0; 
}