2014-10-03 103 views
0

當我嘗試向數據庫添加記錄時,我的代碼出現問題。每次輸入任何超過幾個字符的名字提示時,即使在移動舊記錄中的元素之後,該程序也會將故障排除。我知道seg故障是由於試圖訪問我們無法訪問的內存,但對於我的生活,我無法弄清楚是什麼導致了它。這個代碼的重點是創建一個信用卡類型的結構,它在頭文件中定義,它具有一組硬編碼的4條記錄,能夠打印當前數據庫,添加記錄,刪除記錄和其他選項從菜單中。現在我專注於添加和刪除記錄,因爲它們是該程序中最困難的部分。爲什麼在嘗試添加記錄時不斷收到seg故障錯誤?Seg障礙在我的

頭文件:

#ifndef myStruct 
#define myStruct 

struct creditCard 
{ 
char firstName[100]; 
char lastName[100]; 
char cardNumber[17]; //TA advised to use string since 16 digits will overflow in plain integer 
char expMonth[10]; 
}; 

//function headers below 
int printCreditCard(struct creditCard *); 

int sizeOfDb(struct creditCard *); 

int countRecords(struct creditCard *); 

int deleteRecord(struct creditCard *); 

int addRecord(struct creditCard *); 

#endif 

下面是實際的程序:

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

int accesses = 0; //number of times database was manipulated 
int count = 0; //used to count how many records there are; we always start at 4 
//int size = 0; //used to tell us how big the database is 
struct creditCard *ptr; //chunk of memory for each record/structure 
struct creditCard *headPtr; //chunk of memory for the first records/structure 

int main(void) 
{ 
    ptr = (struct creditCard *) malloc(4 * sizeof(struct creditCard)); 
    headPtr = ptr; 

    memcpy(ptr->firstName,"Bob",100); 
    memcpy(ptr->lastName,"Marley",100); 
    memcpy(ptr->cardNumber,"0000000000000000",17); 
    memcpy(ptr->expMonth,"September", 10); 
    ptr++; 
    count = count++; 

    memcpy(ptr->firstName, "John", 100); 
    memcpy(ptr->lastName, "Adams", 100); 
    memcpy(ptr->cardNumber,"1111111111111111",17); 
    memcpy(ptr->expMonth, "October", 10); 
    ptr++; 
    count = count++; 

    memcpy(ptr->firstName, "Bill", 100); 
    memcpy(ptr->lastName, "Gates", 100); 
    memcpy(ptr->cardNumber,"2222222222222222",17); 
    memcpy(ptr->expMonth, "January", 10); 
    ptr++; 
    count = count++; 

    memcpy(ptr->firstName, "Steve", 100); 
    memcpy(ptr->lastName, "Jobs", 100); 
    memcpy(ptr->cardNumber,"3333333333333333",17); 
    memcpy(ptr->expMonth, "May", 10); 
    count = count++; 

while (1) 
{ 
//headPtr = ptr; //put the newest database into headPtr so it points to the first record in that database 
//ptr = headPtr; //start the database back at the first record 
//countRecords(ptr); //update the count of the current database 

    int sel; 
    printf("MAIN MENU\n"); 
    printf("=====\n"); 
    printf("1. Select 1 to print all records.\n"); 
    printf("2. Select 2 to print number of records .\n"); 
    printf("3. Select 3 to print size of database.\n"); 
    printf("4. Select 4 to add record.\n"); 
    printf("5. Select 5 to delete record.\n"); 
    printf("6. Select 6 to print number of accesses to database.\n"); 
    printf("7. Select 7 to Exit.\n"); 
    printf("Enter Your Selection: \n"); 

    scanf("%d", &sel); //get user input; 

    if (sel == 1) 
    { 
      printCreditCard(ptr); 
      accesses++; 
    } 
    else if (sel == 2) 
    { 
      fprintf(stderr,"Number of records in the database is %d records\n", count); //pulls value of count from global updated variable 
      accesses++; 

    } 
    else if (sel == 3) 
    { 
      sizeOfDb(ptr); 
      accesses++; 
    } 
    else if (sel == 4) 
    { 
      ptr = headPtr; 
      addRecord(ptr); 
      accesses++; 
    } 
    else if (sel == 5) 
    { 
      deleteRecord(ptr); 
      accesses++; 
    } 
    else if (sel == 6) 
    { 
      fprintf(stderr,"Number of accesses to the database is %d\n", accesses); 
      accesses++; 
    } 
    else if (sel == 7) 
    { 
      printf("Now Exiting.\n"); 
      return 0; 
    } 
    else 
    { 
      printf("Invalid input, please select a valid option.\n"); 
      break; //go back to the main menu 
    } 
} 
} 
//functions defined below 
int sizeOfDb(struct creditCard *card2) 
{ 
    int size = 0; 
    int j; 
    for (j = 1; j <= count; j++) 
    { 
      size += sizeof(card2->firstName); //get the size of each element 
      size += sizeof(card2->lastName); 
      size += sizeof(card2->cardNumber); 
      size += sizeof(card2->expMonth); 
      card2++; 
    } 
    //loop through each record and get sizeof() of each record 
    fprintf(stderr, "Total Size of the Database is %d bytes.\n", size); 
    return size; 
} 

int addRecord(struct creditCard *card3) 
{ 
    count = count++; 
    fprintf(stderr, "count is %d \n", count); 
    int p; 
    struct creditCard *tempStruct; 
    //struct creditCard *dummy; 
    char fName, lName, month, number; 
    //tempStruct = (struct creditCard *) malloc (count * sizeof(struct creditCard)); //allocate memory to a dummy record 
    tempStruct = (struct creditCard *) malloc ((count+1) * sizeof(struct creditCard)); //allocate memory to a dummy record 
    //dummy = (struct creditCard *) malloc (sizeof(struct creditCard)); 
    //dummy = (struct creditCard *) malloc (2 * sizeof(struct creditCard)); 
    card3 = headPtr; //start at the beginning of the old database 
    for (p = 1; p < count; p++)  //copies the old database in the new database up to the record before the newly allocated record 
    { 
      memcpy(tempStruct->firstName, card3->firstName, 100); 
      memcpy(tempStruct->lastName, card3->lastName, 100); 
      memcpy(tempStruct->cardNumber, card3->cardNumber, 17); 
      memcpy(tempStruct->expMonth, card3->expMonth, 10); 
      fprintf(stderr, "first name is %s\n", tempStruct->firstName); 
      if (p == count-1) 
      { 
        tempStruct++; 
      } 
      else 
      { 
        tempStruct++; 
        card3++; 
      } 
    } 
    printf("Please enter your first name.\n"); 
    scanf("%s", &fName); 
    fprintf(stderr, "fname is %s\n", &fName); 
    memcpy(tempStruct->firstName, &fName, 100);//put first name in struct 
    //memcpy(dummy->firstName, &fName,100);//put first name in struct 
    fprintf(stderr, "struct name is %s\n", tempStruct->firstName); 
    //fprintf(stderr, "dummy name is %s\n", dummy->firstName); 
    printf("Please enter your last name.\n"); 
    scanf("%s", &lName); 
    memcpy(tempStruct->firstName, &fName, 100);//put first name in struct 
    //memcpy(dummy->lastName,&lName,100);//put last name in struct 
    printf("Please enter your 16 digit credit card number with no spaces.\n"); 
    scanf("%s", &number); 
    memcpy(tempStruct->firstName, &fName, 100);//put first name in struct 
    //memcpy(dummy->cardNumber,&number,17);//put creditcard number in struct 
    printf("Please enter the month in which your credit card expires.\n"); 
    scanf("%s", &month); 
    memcpy(tempStruct->firstName, &fName, 100);//put first name in struct 
    //memcpy(dummy->expMonth,&month, 10); //put month of expiration in struct 

    //code below copies stuff from the dummy record to the new database called tempStruct 
    //memcpy(tempStruct->firstName, dummy->firstName, 100); 
//memcpy(tempStruct->lastName, dummy->lastName, 100); 
//memcpy(tempStruct->cardNumber, dummy->cardNumber, 17); 
//memcpy(tempStruct->expMonth, dummy->expMonth, 10); 

    card3 = tempStruct; //put the new database in place of the old database 
    //free(dummy); //clear memory for the dummy record because we don't need it anymore 
    return 0; 
} 

    int deleteRecord(struct creditCard *card4) //goes to the last record in the database and clears the memory for it, essentially deleting it 
    { 
    count = count--; 
    int l; 
    struct creditCard *newDb; //will hold the new database with one less record at the end 
    newDb = (struct creditCard *) malloc(count * sizeof(struct creditCard)); 

    for (l = 0; l < 4; l++) 
    { 
      memcpy(newDb->firstName,card4->firstName,100); 
      memcpy(newDb->lastName,card4->lastName,100); 
      memcpy(newDb->cardNumber,card4->cardNumber,17); 
      memcpy(newDb->expMonth,card4->expMonth,10); 
      card4++; 
    } 
    //now we need to put the data into the new record 
    card4 = newDb; //put the new database into ptr to hold as the new database 
    return 0; 
    } 

int printCreditCard(struct creditCard *card) 
{ 
    card = headPtr; //start at the beginning of the database 
    int i; 
    if (count == 0) 
    { 
    printf("The database is empty\n"); 
    return 0; 
    } 
    else 
    { 
    for (i = 1; i <= count; i++) 
    { 
      printf("Credit Card Record %d\n", i); 
      fprintf(stderr, "First Name = \%s\n", card-> firstName); 
      fprintf(stderr, "Last Name = \%s\n", card-> lastName); 
      fprintf(stderr, "Card Number = \%s\n", card-> cardNumber); 
      fprintf(stderr, "Expiration Date = \%s\n\n", card-> expMonth); 
      card++; //go to the next record to print 
    } 
    } 
    return 1; //we have now printed all records, go to main menu. 
} 
+2

'count = count ++;'絕對不是你想要的。 '++ count;'或'count + = 1;'或'count = count + 1;'。 – 2014-10-03 03:22:00

+1

@PaulGriffiths:對於那些想知道爲什麼,一個解釋是在這裏:http://stackoverflow.com/questions/3575350/sequence-points-in-c – 2014-10-03 03:23:43

+0

你可以嘗試添加更多'printf()'或使用一個調試器首先識別段故障位置。 – SSC 2014-10-03 03:26:39

回答

1

實在是很多錯誤這裏 - 你應該嘗試使用棉絨或其他靜態分析工具來幫助你發現錯誤。

一個特別的問題 - 當你輸入fname時,你傳遞了一個指向單個字符的指針 - 你真的要傳遞一個指向字符數組的指針(實際上,你不想使用scanf在所有,但我不會進入)。在單個字符之後,Scanf會將輸入字符快速複製到內存位置,這當然會在某個點引起段錯誤。

您還需要學習使用某種調試器(gdb?),它可以幫助您在發生段錯誤時查看核心轉儲,以便查找出錯的地方。

+0

我應該使用fgets而不是scanf嗎? – ThomasM 2014-10-03 04:53:37

+0

是的,fgets更安全 - – antlersoft 2014-10-03 15:02:38