How to design a if statement to achieve the following goal?Code:if (feof(inSalesPtr) != "\n")
fprintf(inSalesPtr,"\n");
1)
Attachment 12146
insert a new line
2)
Attachment 12147
do nothing
Printable View
How to design a if statement to achieve the following goal?Code:if (feof(inSalesPtr) != "\n")
fprintf(inSalesPtr,"\n");
1)
Attachment 12146
insert a new line
2)
Attachment 12147
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);
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!Quote:
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
Attachment 12154
After
Attachment 12155
No. My goal is:
Attachment 12156
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;
}