How to design a if statement to achieve the following goal?Code:if (feof(inSalesPtr) != "\n") fprintf(inSalesPtr,"\n");
1)
insert a new line
2)
do nothing
How to design a if statement to achieve the following goal?Code:if (feof(inSalesPtr) != "\n") fprintf(inSalesPtr,"\n");
1)
insert a new line
2)
do nothing
Untested:
Code:FILE *inSalesPtr; //open the file for binary read/append if ((inSalesPtr = fopen("sales.txt", "a+b")) == NULL) exit(1); /* exit on error */ // set the file position to the very last character if (fseek(inSalesPtr, -1, SEEK_END)) exit(2); /* exit on error */ // read the last character int ch = fgetc(inSalesPtr); if (ch == EOF) exit(3); /* exit on error */ // check if the last character is a '\n' if (ch != '\n') { // if the last character is not a '\n' append a "\r\n" (Windows line break) fputs("\r\n", inSalesPtr); } // close the FILE fclose(inSalesPtr);
Last edited by qny; 11-03-2012 at 03:27 AM. Reason: typo
If you pulled in the data using fscanf(), ( or from a buffer, using sscanf() ), then you know you need to add the newline.
So when would you NOT need to enter the newline into the file output?
!feof is a problem - using the return number from fscanf() or sscanf(), like I showed you previously.
Why it doesn't work?Code:#include <stdio.h> #include <stdlib.h> #include <string.h> // number of salesman #define SIZE 100 // salesman_type structure definition typedef struct{ int ID; // salesman id char id_txt[6]; // salesman id for txt file char name[50]; // salesman name double hor_total; // total sales amount of a salesman }salesman_type; // end structure salesman_type salesman_type salesman[SIZE];// synonym for salesman_type // function prototype int nextId(int currentId, int isReset); int sale_menu(); int report_menu(); void AddSalesMan(int initialId); // function to generate id // currentId and isReset are parameters int nextId(int currentId, int isReset) { // initializes elements to 0 for the first time function is called static int lastId = 0; // if isReset is 0, assign currentId to lastId; if (isReset == 0) { lastId = currentId; } //if isReset is not 0, return and add 1 to lastId if (isReset != 0) return ++lastId; } // sales processing system menu function int sale_menu() { int menu; printf("Sales Processing System\n"); printf("-----------------------\n\n"); printf("1. Add Salesman Records\n"); printf("2. Reports Generation\n"); printf("3. Modify Salesman Records\n"); printf("4. Delete Salesman Records\n\n"); printf("0. Exit\n"); printf("Your choice: "); scanf("%d", &menu); return menu; printf("\n"); } // reports generation menu function int report_menu() { int report; printf("Reports Generation\n"); printf("------------------\n\n"); printf("1. View Quarterly Sales Report\n"); printf("2. View Individual Salesman Commission\n\n"); printf("0. Return to Main Menu\n"); printf("Your choice: "); scanf("%d", &report); return report; } // function to add salesman void AddSalesMan(int initialId) { // nextid.txt file pointer FILE *writeIdPtr; // sales.txt file pointer FILE *inSalesPtr; char ch; int a, b; // counter int loop = 1; // confirmation int creId = 1; // pass value to nextId function to generate ID int newId; // receive new generated ID double sale[SIZE][4]; // quarterly sales amount // fopen opens file; exit program if unable to create file if ( (writeIdPtr = fopen("nextid.txt","w") ) == NULL) { printf("Cannot open nextid.txt.\n"); // display error message system("pause"); // pause program before it exits exit(-1); // end program } //end if // fopen opens file; exit program if unable to create file if ( (inSalesPtr = fopen("sales.txt","a") ) == NULL) { printf("Cannot open sales.txt file.\n"); // display error message system("pause"); // pause program before it exits exit(-1); // end program } // end if else { // set the file position to the very last character fseek(inSalesPtr, -1, SEEK_END); ch = fgetc(inSalesPtr); if (ch != '\n') { fputs("\r\n",inSalesPtr); } // write salesname id, quarterly sales amount into file with fprintf for(a=initialId - 1; a<SIZE; a++) { // while loop is 1 while (loop == 1) { // assign new generated id to newId newId = nextId(initialId, creId); // write newId into file with fprintf fprintf(inSalesPtr,"S%04d|",newId); //printf("Name: "); //scanf(" %[^\n]", salesman[a].name); for (b=0; b<4; b++) { // prompt and read quarterly sales amount printf("Quarter %d: ",b+1); scanf(" %lf", &sale[a][b]); // write sales[a][b] into file with fprintf if(b<3) fprintf(inSalesPtr,"%.2f|",sale[a][b]); // end if else fprintf(inSalesPtr,"%.2f\n",sale[a][b]); // end else } // end for printf("\n"); printf("Continue?(Yes = 1): "); // prompt user to continue or not scanf("%d",&loop); } // end while } // end for // write newId into file with fprintf fprintf(writeIdPtr,"%d",newId); fclose(writeIdPtr); // flose close the file fclose(inSalesPtr); // flose close the file } // end else } // end function AddSalesman // function main begins program execution void main() { // nextid.txt file pointer FILE *readIdPtr; // variable declaration int a, b, c = 0, last; // counter int getMenu = 0, getReport = 0; // menu selector double ver_total = 0, max = 0; int id = 0, lastId, resetId = 0; // fopen opens the file; exits program if file cannot be opened if ( (readIdPtr = fopen("nextid.txt","r") ) == NULL) { printf("Cannot open nextid.txt file\n"); system("pause"); exit(-1); } // end if else { // read lastId from file fscanf(readIdPtr,"%d",&lastId); // Generate new id from previous salesman ID if the salesman is one or more // lastId and restId are arguments nextId(lastId, resetId); } // end else // fclose close the file fclose(readIdPtr); // call and assign sale_menu function to getMenu getMenu = sale_menu(); printf("\n"); // Execute command based on user input switch(getMenu) { // call AddSalesMan function case 1: AddSalesMan(lastId); break; // call and assign report_menu to getReport case 2: break; } // end switch system("pause"); // pause the program before it exits } // end main
WHAT isn't working right?
Describe the problem like you did in the first post of this thread - that was good.
It would be great to know if the advice given since then, has solved that first problem.
You opened the FILE for append mode, but then try to read from it ... this is a big no no: don't do that!Code:if ( (inSalesPtr = fopen("sales.txt","a") ) == NULL) { printf("Cannot open sales.txt file.\n"); // display error message system("pause"); // pause program before it exits exit(-1); // end program } // end if else { // set the file position to the very last character fseek(inSalesPtr, -1, SEEK_END); ch = fgetc(inSalesPtr);
Open the file for reading / appending in binary mode like I suggested
Note:Code:if ( (inSalesPtr = fopen("sales.txt", "a+b") ) == NULL)
the binary mode may be troublesome (or its absence may be troublesome).
Without binary mode, when a file contains "one\r\ntwo\r\n" (10 characters) it is converted to "one\ntwo\n" (8 characters). Using fseek is not guaranteed to go to the expected place.
With binary mode there is no conversion between what's on disk and what your program sees, so "one\r\ntow\r\n" is effectively read as "one\r\ntwo\r\n" and you have to deal with the '\r's yourself.
My suggestion ,assuming you have to deal with Windows line breaks of "\r\n", is to open the files without the binary flag for normal processing, and open them with the binary flag for precision work within the disk-file itself.
I'm beginning to think that ulti-killer either is a troll or has severe periodic amnesia (forgets everything from time to time).
You can't open a file in append mode, and then try to read from the file.
You can't fseek() to the end of the file, and then try to read from the file.
I don't know how to make it any plainer than that.
BeforeCode:#include <stdio.h>#include <stdlib.h> #include <string.h> // number of salesman #define SIZE 100 // salesman_type structure definition typedef struct{ int ID; // salesman id char id_txt[6]; // salesman id for txt file char name[50]; // salesman name double hor_total; // total sales amount of a salesman }salesman_type; // end structure salesman_type salesman_type salesman[SIZE];// synonym for salesman_type // function prototype int nextId(int currentId, int isReset); int sale_menu(); int report_menu(); void AddSalesMan(int initialId); // function to generate id // currentId and isReset are parameters int nextId(int currentId, int isReset) { // initializes elements to 0 for the first time function is called static int lastId = 0; // if isReset is 0, assign currentId to lastId; if (isReset == 0) { lastId = currentId; } //if isReset is not 0, return and add 1 to lastId if (isReset != 0) return ++lastId; } // sales processing system menu function int sale_menu() { int menu; printf("Sales Processing System\n"); printf("-----------------------\n\n"); printf("1. Add Salesman Records\n"); printf("2. Reports Generation\n"); printf("3. Modify Salesman Records\n"); printf("4. Delete Salesman Records\n\n"); printf("0. Exit\n"); printf("Your choice: "); scanf("%d", &menu); return menu; printf("\n"); } // reports generation menu function int report_menu() { int report; printf("Reports Generation\n"); printf("------------------\n\n"); printf("1. View Quarterly Sales Report\n"); printf("2. View Individual Salesman Commission\n\n"); printf("0. Return to Main Menu\n"); printf("Your choice: "); scanf("%d", &report); return report; } // function to add salesman void AddSalesMan(int initialId) { // nextid.txt file pointer FILE *writeIdPtr; // sales.txt file pointer FILE *inSalesPtr; char ch; int a, b; // counter int loop = 1; // confirmation int creId = 1; // pass value to nextId function to generate ID int newId; // receive new generated ID double sale[SIZE][4]; // quarterly sales amount // fopen opens file; exit program if unable to create file if ( (inSalesPtr = fopen("sales.txt","a+b") ) == NULL) { printf("Cannot open sales.txt file.\n"); // display error message system("pause"); // pause program before it exits exit(-1); // end program } // end if else { // set the file position to the very last character fseek(inSalesPtr, -1, SEEK_END); ch = fgetc(inSalesPtr); if (ch != '\n') { fputs("\r\n",inSalesPtr); } fclose(inSalesPtr); } // fopen opens file; exit program if unable to create file if ( (writeIdPtr = fopen("nextid.txt","w") ) == NULL) { printf("Cannot open nextid.txt.\n"); // display error message system("pause"); // pause program before it exits exit(-1); // end program } //end if // fopen opens file; exit program if unable to create file if ( (inSalesPtr = fopen("sales.txt","a") ) == NULL) { printf("Cannot open sales.txt file.\n"); // display error message system("pause"); // pause program before it exits exit(-1); // end program } // end if else { // write salesname id, quarterly sales amount into file with fprintf for(a=initialId - 1; a<SIZE; a++) { // while loop is 1 while (loop == 1) { // assign new generated id to newId newId = nextId(initialId, creId); // write newId into file with fprintf fprintf(inSalesPtr,"S%04d|",newId); //printf("Name: "); //scanf(" %[^\n]", salesman[a].name); for (b=0; b<4; b++) { // prompt and read quarterly sales amount printf("Quarter %d: ",b+1); scanf(" %lf", &sale[a][b]); // write sales[a][b] into file with fprintf if(b<3) fprintf(inSalesPtr,"%.2f|",sale[a][b]); // end if else fprintf(inSalesPtr,"%.2f\n",sale[a][b]); // end else } // end for printf("\n"); printf("Continue?(Yes = 1): "); // prompt user to continue or not scanf("%d",&loop); } // end while } // end for // write newId into file with fprintf fprintf(writeIdPtr,"%d",newId); fclose(writeIdPtr); // flose close the file fclose(inSalesPtr); // flose close the file } // end else } // end function AddSalesman // function main begins program execution void main() { // nextid.txt file pointer FILE *readIdPtr; // variable declaration int a, b, c = 0, last; // counter int getMenu = 0, getReport = 0; // menu selector double ver_total = 0, max = 0; int id = 0, lastId, resetId = 0; // fopen opens the file; exits program if file cannot be opened if ( (readIdPtr = fopen("nextid.txt","r") ) == NULL) { printf("Cannot open nextid.txt file\n"); system("pause"); exit(-1); } // end if else { // read lastId from file fscanf(readIdPtr,"%d",&lastId); // Generate new id from previous salesman ID if the salesman is one or more // lastId and restId are arguments nextId(lastId, resetId); } // end else // fclose close the file fclose(readIdPtr); // call and assign sale_menu function to getMenu getMenu = sale_menu(); printf("\n"); // Execute command based on user input switch(getMenu) { // call AddSalesMan function case 1: AddSalesMan(lastId); break; // call and assign report_menu to getReport case 2: break; } // end switch system("pause"); // pause the program before it exits } // end main
After
No. My goal is:
No matter how the user put line indicator in last line text or any blank line, the new input record can stick with the old record.
My code works for me:
Code:#include <stdio.h> #include <stdlib.h> int eofnormalize(const char *fname) { FILE *h; int ch; if ((h = fopen(fname, "a+b")) == NULL) return 1; if (fseek(h, -1, SEEK_END)) return 2; ch = fgetc(h); if (ch == EOF) return 3; if (ch != '\n') { fputs("\r\n", h); } if (fclose(h)) return 4; return 0; } int main(void) { FILE *h; if ((h = fopen("151926.dat", "wb")) == NULL) exit(1); fprintf(h, "1 no line break"); /* not a line */ if (fclose(h)) exit(2); if (eofnormalize("151926.dat")) exit(3); if ((h = fopen("151926.dat", "a")) == NULL) exit(4); fprintf(h, "2 ok\n"); fclose(h); if ((h = fopen("151926.dat", "a")) == NULL) exit(5); fprintf(h, "3 windows line break\r\n"); if (fclose(h)) exit(6); if (eofnormalize("151926.dat")) exit(7); if ((h = fopen("151926.dat", "a")) == NULL) exit(8); fprintf(h, "4 ok\n"); fclose(h); return 0; }If I remove the eofnormalize() callsCode:./a.out && echo $? && hd 151926.dat 0 00000000 31 20 6e 6f 20 6c 69 6e 65 20 62 72 65 61 6b 0d |1 no line break.| 00000010 0a 32 20 6f 6b 0a 33 20 77 69 6e 64 6f 77 73 20 |.2 ok.3 windows | 00000020 6c 69 6e 65 20 62 72 65 61 6b 0d 0a 34 20 6f 6b |line break..4 ok| 00000030 0a |.| 00000031
Code:./a.out && echo $? && hd 151926.dat 0 00000000 31 20 6e 6f 20 6c 69 6e 65 20 62 72 65 61 6b 32 |1 no line break2| 00000010 20 6f 6b 0a 33 20 77 69 6e 64 6f 77 73 20 6c 69 | ok.3 windows li| 00000020 6e 65 20 62 72 65 61 6b 0d 0a 34 20 6f 6b 0a |ne break..4 ok.| 0000002f
In eofnormalize(), a call to a file positioning function is needed between input and output.
I no longer can edit my post, but I'd change the function to:
Code:#include <stdio.h> int eofnormalize(const char *fname) { FILE *h; int ch; if ((h = fopen(fname, "a+b")) == NULL) return 1; if (fseek(h, -1, SEEK_END)) return 2; ch = fgetc(h); if (ch == EOF) return 3; if (ch != '\n') { fseek(h, 0, SEEK_CUR); fputs("\r\n", h); } if (fclose(h)) return 4; return 0; }