我只是想获取用户输入,将其存储在结构中,将其写入二进制文件,然后再次读取。这是一个联系簿类型计划的开始。 当我尝试检索单个结构的数据时,它不会读入我的readStruct,并且我在代码中的标记注释中出现了seg错误。
另外,请注意动态字符串和用户输入的混乱使用。我只是在玩耍并从中学习。
感谢。
下面是代码:
int main(void) {
struct contactStruct {
int phoneNumber;
char * firstName;
char * lastName;
char * companyName;
};
struct contactStruct contact;
struct contactStruct read;
//Variable Declaration
int j = 1;
char tempInput[100] = "-";
char * menuInput;
char * searchInput;
bool menuLoop = false;
FILE * filePointer;
filePointer = fopen("contactList.db", "r+");
if (filePointer == NULL) {
filePointer = fopen("contactList.db", "w+");
}
printf("Welcome to the Contact Book Program\n");
printf("This program will let you store and access all of your contacts!\n");
do {
menuLoop = false;
printf("Would you like to: 'ADD', 'EDIT', 'VIEW', or 'REMOVE' a contact? - ");
fgets(tempInput, sizeof(tempInput), stdin);
for (int i = 0; i < strlen(tempInput); i++) {
tempInput[i] = tolower(tempInput[i]);
}
menuInput = malloc(sizeof(char) * strlen(tempInput) + 1);
strcpy(menuInput, tempInput);
if (strcmp(menuInput, "add\n") == 0) {
printf("Phone Number: ");
fgets(tempInput, sizeof(tempInput), stdin);
contact.phoneNumber = atoi(tempInput);
printf("First Name: ");
fgets(tempInput, sizeof(tempInput), stdin);
contact.firstName = malloc(sizeof(char) * strlen(tempInput) + 1);
strcpy(contact.firstName, tempInput);
printf("Last Name: ");
fgets(tempInput, sizeof(tempInput), stdin);
contact.lastName = malloc(sizeof(char) * strlen(tempInput) + 1);
strcpy(contact.lastName, tempInput);
printf("Company Name: ");
fgets(tempInput, sizeof(tempInput), stdin);
contact.companyName = malloc(sizeof(char) * strlen(tempInput) + 1);
strcpy(contact.companyName, tempInput);
fwrite( & contact, sizeof(struct contactStruct), 1, filePointer);
} else if (strcmp(menuInput, "view\n") == 0) {
printf("Who are you searching for? (First Name): ");
scanf("%s", tempInput);
searchInput = malloc(sizeof(char) * strlen(tempInput) + 1);
strcpy(searchInput, tempInput); // Get name being searched for
fread( & read, sizeof(struct contactStruct), 1, filePointer);
printf("DEBUG - File Pos: %ld Size of Struct: %lu\n", ftell(filePointer), sizeof(struct contactStruct));
printf("Input: %s Searching: %s\n", searchInput, read.firstName); //Seg Fault Happens Here
if (strcmp(searchInput, read.firstName) == 0) {
printf("Here is the contact information given:\n\n");
printf("%d %s %s %s \n", read.phoneNumber, read.firstName, read.lastName, read.companyName);
} else {
printf("Did not find\n");
}
} else {
printf("Invalid Option, Try Again.\n");
menuLoop = true;
}
}
while (menuLoop == true);
free(menuInput);
free(searchInput);
fclose(filePointer);
return 0;
}
答案 0 :(得分:0)
问题在于您的结构:
struct contactStruct
{
int phoneNumber;
char * firstName; // <-- you have pointers, not data
char * lastName;
char * companyName;
};
将contactStruct保存到文件时,使用fwrite( & contact, sizeof(struct contactStruct), 1, filePointer);
保存指向文件的指针值,而不是它们指向的字符串的内容。这意味着实际数据永远不会被保存,当您读取文件时,您的指针无处可寻。
如果你想要做的只是在你的文件中有固定长度的记录 - 我建议你这样做,现在,你应该改变你的结构来保存数据。长度。您必须根据需要决定字符串的长度。
#define CS_PHONE_LEN 11 // remember that your strings will need a zero termination.
#define CS_FIRSTNAME_LEN 24 // I've chosen arbitrary lengths for the demonstration.
#define CS_LASTNAME_LEN 24
#define CS_COMPANY_LEN 24
struct contactStruct
{
char phoneNumber[CS_PHONE_LEN]; // phone numbers are usually stored as text.
char firstName[CS_FIRSTNAME_LEN];
char lastName[CS_LASTNAME_LEN];
char companyName[CS_COMPANY_LEN];
};
您必须注意程序中不要存储超过结构中定义的字符串的字符串,否则数据将会损坏。您可能希望使用strncpy_s()
在数据成员中存储字符串,这里是函数http://en.cppreference.com/w/c/string/byte/strncpy的文档。
strncpy_s(cs.phoneNumber, CS_PHONE_LEN, userEntryString, CS_PHONE_LEN - 1);
如果您使用较旧的strncpy,请注意,如果源字符串太长,它将不会终止您的目标字符串。
strncpy(cs.phoneNumber, userEntryString, CS_PHONE_LEN - 1);
cs.phoneNumber[CS_PHONE_LEN - 1] = 0; // make sure it's null-terminated.
一种更安全,另类的写作方式(上面是更经常使用的'经典'符号。
strncpy_s(cs.phoneNumber, sizeof(cs.phoneNumber), userEntryString, sizeof(cs.phoneNumber) - 1);
// or...
strncpy(cs.phoneNumber, userEntryString, sizeof(cs.phoneNumber) - 1);
cs.phoneNumber[sizeof(cs.phoneNumber) - 1] = 0; // make sure it's null-terminated.
这样,您的写入与常量的名称无关,而长度总是正确的。