【问题标题】:read/write functions in cc中的读/写函数
【发布时间】:2014-04-08 01:05:54
【问题描述】:

典型的初学者电话簿程序,试图增加文件的读写能力。它没有编译,因为

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);
}

【问题讨论】:

  • 哇。去。 ...好吧,goto 仅在函数内部起作用,而不是跨函数...摆脱它并使用返回值
  • 是的,我的教授特别说我们必须使用 goto。如果我知道,见鬼。
  • 摆脱那个 p...哦不,最好不要。但是如果你必须在那些地方使用“goto”,那么你就不能使用不同的功能(但在 main 中做所有事情)。如果发生错误,使用返回值然后转到 main 怎么样?
  • 我修复了 ErrorHandler。其他的还不知道。

标签: c file error-handling compiler-errors


【解决方案1】:

你应该把你的电话簿转换成 char *:

fprintf(pWrite, (char*)phonebook,sizeof (struct phonebook));

goto 不能在不同的函数之间跳转。
您需要在每个函数中有一个“ErrorHandler”标记。

也许一个更好的解决方案是 Makro。

【讨论】:

  • 他为什么要选角?宏将如何提供帮助?他一开始就不应该打印这样的东西......
  • @deviantfan:至少(尝试)打印cFirstname
  • 投射错误。您将无法编写一个恰好包含带有fprintf 的零字节的结构,因为它只写入字符串。此外,它会忽略sizeof 参数。
【解决方案2】:

第一季度。来自 C 标准的第 6.8.6.1 节:

goto 语句中的标识符应命名位于封闭函数某处的标签。

goto 语句不应从具有可变修改类型的标识符范围之外跳转到该标识符范围内。

goto 语句会导致无条件跳转到以封闭函数中命名标签为前缀的语句。

您的教授的意思是,您需要在每个函数中将goto 放在底部的一个部分中,该部分处理与该函数相关的清除(关闭文件等),然后执行returngoto(和坏的)的良好使用示例在这里:Examples of good gotos in C or C++

第二季度。这意味着printf 中的格式说明符与传递的参数类型不匹配。在这种情况下,你正在做:

fprintf(pRead, phonebook, sizeof (struct phonebook));

fprintfchar * 作为字符串指定格式。您永远不应该将结构直接传递给此(想象一下,如果您使用 fprintf 并且电话簿条目有 % 登录会发生什么)。

在这种情况下,您希望将固定大小的对象写入文件,而不是以NULL 结尾的字符串。因此,在任何情况下,您都应该使用 fwrite 而不是 fprintf,例如

fwrite(phonebook, sizeof (struct phonebook), 1, pRead);

您还应该考虑错误检查以及pRead 是否是您正在写信的FILE * 的好名字。

第三季度。请参阅第二季度。

【讨论】:

  • 感谢您提供如此多的细节,这解决了所有问题,除了当我选择任一读/写函数时,我的错误处理程序返回“无效参数”
  • 这意味着错误之前的系统调用的错误(即errnum的值)是EINVAL(其文本表示为'无效参数'。查找哪个库调用导致此问题,打开手册页,您就会知道原因。如果有用,您可以随时投票/接受答案。
猜你喜欢
  • 1970-01-01
  • 2020-03-01
  • 2017-06-06
  • 2021-03-19
  • 2013-07-03
  • 2020-05-15
  • 2018-09-23
  • 2010-09-19
相关资源
最近更新 更多