[英]read/write functions in c
典型的初学者电话簿程序,尝试添加对文件的读写功能。 它没有编译是因为
1)无论我将其放置在哪里,它都不会识别标签ErrorHandler
2)在两个函数中:从不兼容的指针类型传递fprintf
参数2 [默认启用]
3)在.c文件随附的文件中,在两个函数中均进行了打印:预期的const char * __restrict__
但参数的类型为struct pb *
整个代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct phonebook {
char cFirstName[20];
char cLastName[20];
char PhoNo[20];
} pb;
//function prototypes
void AddContact (pb * );
void DeleteContact (pb * );
void ShowContacts (pb * );
void FindContact (pb * );
void RandContact (pb * );
void FindContact (pb * );
void DeleteAll (pb *);
void Read (pb *);
void Write (pb *);
char FileName[100];
FILE *pRead;
FILE *pWrite;
int counter = 0;
main ()
{
pb *phonebook;
phonebook = (pb*) malloc(sizeof(pb)*1);
int iChoice = 0;
while (iChoice <= 8) {
printf("\n-Choose an option- \n");
printf("\n\t(1)\tAdd Contact");
printf("\n\t(2)\tDelete Contact");
printf("\n\t(3)\tShow All Contacts");
printf("\n\t(4)\tSearch for a Contact");
printf("\n\t(5)\tRandom Contact");
printf("\n\t(6)\tDelete All Contacts");
printf("\n\n\t(7)\tWrite contacts to file");
printf("\n\t(8)\tRead contacts from file");
printf("\n\n\t(9)\tExit\n\n\t");
scanf("%d", &iChoice);
if (iChoice == 1) {
AddContact(phonebook);
}
if (iChoice == 2) {
DeleteContact (phonebook);
}
if (iChoice == 3) {
ShowContacts(phonebook);
}
if (iChoice == 4) {
FindContact(phonebook);
}
if (iChoice == 5) {
RandContact(phonebook);
}
if (iChoice == 6) {
DeleteAll(phonebook);
}
if (iChoice == 7) {
Write(phonebook);
}
if (iChoice == 8) {
Read(phonebook);
}
if (iChoice == 9) {
free(phonebook);
return 0;
}
} //end while
} //end main
//function definitions
//add contact
void AddContact (pb * phonebook)
{
counter++; //counter incremented for each entry
realloc(phonebook, sizeof(pb)); //realloc with every new contact
printf("\nFirst Name: ");
scanf("%s", phonebook[counter-1].cFirstName);
printf("Last Name: ");
scanf("%s", phonebook[counter-1].cLastName);
printf("Phone Number: ");
scanf("%s", phonebook[counter-1].PhoNo);
printf("\n\tContact added\n");
}
//delete contact
void DeleteContact (pb * phonebook)
{
int x = 0;
char scrapcFirstName[20]; //strings for deleting original strings
char scrapcLastName[20];
char nullStr[20] = {"\0"};
printf("\nFirst name: ");
scanf("%s", scrapcFirstName);
printf("Last name: ");
scanf("%s", scrapcLastName);
//compare strings
for (x = 0; x < counter; x++) {
if (strcmp(scrapcFirstName, phonebook[x].cFirstName) == 0) {
for (x = 0; x < counter; x++) {
if (strcmp(scrapcLastName, phonebook[x].cLastName) == 0) {
strcpy(phonebook[x].cFirstName, nullStr);
strcpy(phonebook[x].cLastName, nullStr);
strcpy(phonebook[x].PhoNo, nullStr);
}//end if
else {
printf("Invalid Input");
}
}//end for
}//end if
}// end for
counter--; // Contact deleted, update counter
printf("Contact Deleted\n");
}
//show phonebook
void ShowContacts (pb * phonebook)
{
int x = 0;
printf("\nPhonebook:\n\n ");
for( x = 0; x < counter; x++) {
printf("\n(%d)\n", x+1);
printf("Name: %s %s\n", phonebook[x].cFirstName, phonebook[x].cLastName);
printf("Number: %s\n", phonebook[x].PhoNo);
} //end for
}
//Find a specific contact
void FindContact (pb * phonebook)
{
int x = 0;
char TempFirstName[20];
char TempLastName[20];
printf("\nWho are you looking for?");
printf("\n\nFirst Name: ");
scanf("%s", TempFirstName);
printf("Last Name: ");
scanf("%s", TempLastName);
for (x = 0; x < counter; x++) {
if (strcmp(TempFirstName, phonebook[x].cFirstName) == 0) {
if (strcmp(TempLastName, phonebook[x].cLastName) == 0) {
printf("\n%s %s \n%s\n", phonebook[x].cFirstName,
phonebook[x].cLastName,
phonebook[x].PhoNo);
}
}
}
}
//show a random contact
void RandContact (pb * phonebook)
{
int iRand = 0;
srand(time(NULL));
iRand = rand() % counter;
int x = iRand;
printf("\n%s %s\n", phonebook[x].cFirstName, phonebook[x].cLastName);
printf("%s\n", phonebook[x].PhoNo);
}
//delete all
void DeleteAll (pb * phonebook)
{
int x = 0;
char nullStr[20] = {'\0'};
for ( x = 0; x < counter; x++) {
strcpy(phonebook[x].cFirstName, nullStr);
strcpy(phonebook[x].cLastName, nullStr);
strcpy(phonebook[x].PhoNo, nullStr);
--counter;
}
printf("Contacts have been wiped.\n");
}
void Read(pb * phonebook)
{
FILE *pRead;
char name[256];
printf("File to read:");
gets(name);
pWrite=fopen(name,"a");
if(pWrite != NULL) {
printf("Contact List");
while(!feof(pRead)) {
fprintf(pRead, phonebook,sizeof (struct phonebook));
if (!feof(pRead)) {
fprintf(pRead, phonebook,sizeof (struct phonebook));
}
}
}
else {
goto ErrorHandler;
}
exit(EXIT_SUCCESS);
ErrorHandler:
perror("The folling error occured:");
exit(EXIT_FAILURE);
}
void Write(pb * phonebook)
{
FILE *pWrite;
char name[256];
printf("File to write:");
gets(name);
pWrite=fopen(name,"a");
if(pWrite != NULL) {
fprintf(pWrite, phonebook,sizeof (struct phonebook));
fclose(pWrite);
}
else {
goto ErrorHandler;
}
exit(EXIT_SUCCESS);
ErrorHandler:
perror("The folling error occured:");
exit(EXIT_FAILURE);
}
Q1。 根据C标准的6.8.6.1节:
goto
语句中的标识符应命名位于封闭函数中某处的标签。
goto
语句不应从具有可变修改类型的标识符范围外跳到该标识符范围内。
goto
语句会导致无条件跳转到封闭函数中以命名标签为前缀的语句。
教授要讲的是,您需要将每个函数内的goto
放到底部的一个部分,该部分处理相对于该函数的清理(关闭文件等),然后执行return
。 良好使用goto
(和不好使用)的示例如下 : C或C ++中良好的goto
示例
Q2。 这意味着printf
中的格式说明符与传递的参数类型不匹配。 在这种情况下,您正在执行以下操作:
fprintf(pRead, phonebook, sizeof (struct phonebook));
fprintf
将char *
作为指定格式的字符串。 您永远都不要直接传递结构(想象一下,如果您使用fprintf
且电话簿条目具有%
登录符号,将会发生什么情况)。
在这种情况下,您要向文件写入固定大小的对象,而不是以NULL
结尾的字符串。 因此,无论如何您都应该使用fwrite
而不是fprintf
,例如
fwrite(phonebook, sizeof (struct phonebook), 1, pRead);
您还应该考虑错误检查,以及pRead
是否是您正在写入的FILE *
的好名字。
Q3。 请参阅第2季。
您应该将电话簿转换为char *:
fprintf(pWrite, (char*)phonebook,sizeof (struct phonebook));
goto不能在不同功能之间跳转。
您需要在每个函数中都有一个“ ErrorHandler”标记。
也许更好的解决方案是万客隆。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.