0

typical beginner's phonebook program, attempting to add read and write to file capabilities. It's not compiling because

1) it wont recognize the label ErrorHandler, no matter where I place it

2) in both functions: passing argument 2 of fprintf from incompatible pointer type [enabled by default]

3) in file included with .c file, printed in both functions: expected const char * __restrict__ but argument is of type struct pb *

code for the whole thing:

#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);
}
pat
  • 12,587
  • 1
  • 23
  • 52

2 Answers2

0

Q1. From section 6.8.6.1 of the C standard:

The identifier in a goto statement shall name a label located somewhere in the enclosing function.

A goto statement shall not jump from outside the scope of an identifier having a variably modified type to inside the scope of that identifier.

A goto statement causes an unconditional jump to the statement prefixed by the named label in the enclosing function.

What your professor is getting at is that you need to put a goto within each function to a section at the bottom that handles clear up relative to that function (closing files etc.) and then does a return. Examples of good use of goto (and bad ones) are here: Examples of good gotos in C or C++

Q2. This means the format specifier in printf does not match the type of the argument passed. In this case you are doing:

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

fprintf take a char * as the string specifying the format. You should never pass structures straight to this (imagine what would happen if you use fprintf and the phone book entry had a % sign in).

In this case you want to write a fixed size object to the file, not a NULL terminated string. You should thus be using fwrite not fprintf in any case, e.g.

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

You should also consider error checking and whether pRead is a good name for a FILE * that you are writing to.

Q3. See Q2.

Community
  • 1
  • 1
abligh
  • 24,573
  • 4
  • 47
  • 84
  • thanks for so much detail, this fixes everything it seems except that when i select either of the read/write functions my error handler returns "invalid argument" – I Can't Advise You Counselor Mar 05 '14 at 19:35
  • That would imply the error (i.e. the value of `errnum`) from the system call immediately prior to the error is `EINVAL` (the textual representation of which is 'Invalid argument'. Find which library call is causing this, bring up the man page, and you will know why. You can always upvote / accept the answer if it is useful. – abligh Mar 05 '14 at 19:38
-1

You should cast your phonebook to char *:

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

goto cannot jump between different functions.
You need to have an "ErrorHandler"-mark in each function.

Maybe a better solution would be a Makro.

Dirk
  • 21
  • 1
  • 1
  • 2
  • Why should he cast? And how would a macro help? He shouldn´t printf such a thing in the first place... – deviantfan Mar 05 '14 at 19:19
  • @deviantfan: It'll at least (try) to print `cFirstname`. – alk Mar 05 '14 at 19:26
  • The casting is wrong. You will not be able to write a stucture that happens to contain a zero byte with `fprintf` as it only writes strings. Also, it will ignore the `sizeof` parameter. – abligh Mar 05 '14 at 19:39