当我尝试将记录添加到数据库时,我的代码存在问题。每次我输入任何超过几个字符的名字提示时,即使从旧记录中移动元素,程序也会出现故障。我知道seg故障是由于试图访问我们无法访问的内存,但对于我的生活,我无法弄清楚是什么导致它。这段代码的要点是创建一个信用卡类型的结构,它在头文件中定义,它有一个硬编码的4个记录集,并且能够打印当前数据库,添加记录,删除记录和其他选择从菜单中。现在我专注于添加和删除记录,因为它们是该计划中最困难的部分。为什么我在尝试添加记录时会不断出现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.
}
答案 0 :(得分:1)
这里确实存在很多错误 - 你应该尝试使用lint或其他静态分析工具来帮助你找到错误。
一个特殊的问题 - 当你输入fname时,你将scanf传递给一个单个字符的指针 - 你真的想要传递一个指向一个字符数组的指针(实际上,你不想使用scanf at所有,但我不会进入那个)。 Scanf正在快速地将输入字符复制到单个字符之后的内存位置,这当然会在某个时刻导致段错误。
您还需要学习使用某种调试器(gdb?),它可以帮助您在遇到段错误时查看核心转储,以便找到出错的地方。