fscanf skip my first character - c

Currently I'm doing my C programming homework. I'm facing a problem that I need to add some records to a text file using fprintf, then display out all the records within the file using fscanf. But here the display problem. It only skip the first character in the text, and display the rest.
Example in the textfile,
hello haha 400 500 60
hello2 haha2 500 600 70
We need to fscanf this file into display in command prompt. But in result show me...
ello haha 400 500 60
hello2 haha2 500 600 70
The rest of characters is okay, but for the first character, it skipped.
So this is my codes.
Fscanf's part
if ((ch = fgetc(fp)) != EOF){
while(fscanf(fp,"%s %s %d %d %d",code,name,&cost,&price,&stock) == 5)
{
printf("%-20s %-20s %-20d %-20d %-20d\n",code,name,cost,price,stock);
}
}else{
printf("Record not found in the stock database.\n");
puts("");
}
Fprintf's part
fprintf(fp,"%s %s %d %d %d\n",code,name,cost,price,stock);
So, how to read the first character ?

Your fgetc(fp) read the first h of the first hello, so now the file pointer is at e of hello. Further calls of your fscanf will read from e onwards. A simple soultion would be to add a printf("%c", ch) just above your while loop in your if condition. I.e,
if ((ch = fgetc(fp)) != EOF){
printf("%c", ch);
while(fscanf(fp,"%s %s %d %d %d",code,name,&cost,&price,&stock) == 5)
{
printf("%-20s %-20s %-20d %-20d %-20d\n",code,name,cost,price,stock);
}
}else{
printf("Record not found in the stock database.\n");
puts("");
}

The problem that you are having is that fgetc() is pulling your first character, as mentioned in the comment. In order to get the first character, you either need to store this character somewhere and append it to your output at the beginning, or else use a different method to check that the first character is not EOF.
Note that you could also cause definite problems if your first item was only one character long--Then your fscanf() would no longer have a 1st string to look at.

if ((ch = fgetc(fp)) != EOF){
ungetc(ch, fp);
while(fscanf(fp,"%s %s %d %d %d",code,name,&cost,&price,&stock) == 5)

Related

While loop still prints once after EOF in C

I have to look through a file and take out the information of a student. It all works fine so far, there are 21 lines in the file, the first 20 contain information of a student and the final line contains just a single name. For some reason my while loop continues, sees that there's no information after that last line and stops but it still prints out that last line of the file with other lines of information in the in the output as well.
count = 0;
while(fscanf(fp, "%d", &average)!= EOF )
{
if(fscanf(fp, "%d", &average)!= EOF ){
printf("\n/////////////////////////////////////////////////////////////////////////////");
fscanf(fp, "%s", name);
fscanf(fp, "%s", initial);
fscanf(fp, "%s", surname);
printf("\n\n\tName: %s \tInitial: %s \tSurname: %s\n", name, initial, surname);
fscanf(fp, "%d", &year);
fscanf(fp, "%s", coursename);
fscanf(fp, "%s", group);
fscanf(fp, "%d", &average);
printf("\n\tYear: %d \tCourse Name: %s \tGroup: %s \tAverage: %d\n", year, coursename, group, average );
printf("\n\tThis is entry number %d\n", count+1);
printf("\n/////////////////////////////////////////////////////////////////////////////");
count++;
}
if(fscanf(fp, "%d", &average) == EOF ){
printf("\n\nThank you for using the program\n\nAll of the student records are now displayed\n");
}
}
fclose(fp);
return 0;
}
If the second last line for instance was
Mike (M) Johnson 3 IT A 66
it would print that out perfectly fine but the final thing in the file the name "John" it would print out
John Johnson 3 IT A 66
I don't understand firstly why it wouldn't take Mike Johnson's initial and secondly when it shouldn't print that line to begin with? I've tried setting the if statements and while statement to take the name as the end of the file but I think when I use "%s" to find that at the begining it seems to skip everything to the next string in the file over by 1, so Mike's name would become (M), and so on.

Why fscanf is giving segmentation fault while reading the data into a text file?

I am trying to read data from a text file with some data in it.
My text file:
1 dior Asfiya 20 abcde 12345
2 abde Sabah 17 saar 5757657
My code:
typedef long long int ulong;
struct Customer
{
char name[25];
int acc_no;
int age;
char gender[2];
char address[60];
ulong phone;
char password[10];
};
struct Customer add,check;
int new_acc()
{
int c;
FILE *p;
FILE *q;
p = fopen("test.txt","a");
q = fopen("test.txt","r");
if(p == NULL)
{
puts("Could't open file\n");
return(-1);
}
if(q == NULL)
{
puts("Couldn't open file\n");
return(-1);
}
account_no:
printf("\nAdd record");
printf("\nEnter account number: ");
scanf("%d",&check.acc_no);
while(c = fscanf(q,"%d %s %s %d %s %s %llu%[^\n]",&add.acc_no,add.password,add.name,&add.age,add.gender,add.address,&add.phone) == 7)
{
if(check.acc_no==add.acc_no)
{
printf("\nAccount no. already in use!");
goto account_no;
}
}
if(c != EOF){
goto details;
}
details:
add.acc_no = check.acc_no;
printf("\nEnter password: ");
scanf("%s",add.password);
printf("\nFull Name: ");
scanf("%s",add.name);
printf("\nEnter your age: ");
scanf("%d",&add.age);
printf("\nEnter your gender: ");
scanf(" %c",&add.gender);
printf("\nEnter address: ");
scanf("%s",add.address);
printf("\nEnter phone number: ");
scanf("%llu",&add.phone);
fprintf(p,"%d %s %s %d %s %s %lld\n",add.acc_no,add.password,add.name,add.age,add.gender,add.address,add.phone);
fclose(p);
fclose(q);
}
While debugging the code it gives segmentation fault when the while loop starts. It worked perfectly fine before adding the first line of data into the file. I am not able to figure out why is this happening.
Remove goto.
Refactor this part of your code please.
About your arrays, which await to store a string - did you take in account the string NULL terminator, that also needs a cell of the array to be stored?
In any case, I see gender has a size of 2, but your input suggests that it needs more.
Your input has 7 tokens:
1 dior Asfiya 20 abcde 12345
that means that gender will overflow, invoking Undefined Behavior (UB), since you will attempt to store a 4-character length string into an array of size 2. That might explain the crash.
You would have seen it by your check for 7 values, but there is also another problem in your code, as you can read in the next section.
You probably meant:
1 dior Asfiya 20 abcde f 12345
Change this:
while(c = fscanf(q,"%d %s %s %d %s %s %llu%[^\n]",&add.acc_no,add.password,add.name,&add.age,add.gender,add.address,&add.phone) == 7)
to this:
while((c = fscanf(q,"%d %s %s %d %s %s %llu%[^\n]",&add.acc_no,add.password,add.name,&add.age,add.gender,add.address,&add.phone)) == 7)
since, because of operators priority, the comparison happens before the assignment, which is not what you want. You want first to assign to your variable, and then compare, so use parentheses to specify the desired priority.
You're not setting c correctly when you write:
while(c = fscanf(q,"%d %s %s %d %s %s %llu%[^\n]",&add.acc_no,add.password,add.name,&add.age,add.gender,add.address,&add.phone) == 7)
This is setting c to the result of the == comparison, because == has higher precedence than =.
Also, you don't need [^\n] at the end of the format string. %d at the beginning will skip over any whitespace, including the newline at the end of the previous line.
It should be:
while((c = fscanf(q,"%d %s %s %d %s %s %llu",&add.acc_no,add.password,add.name,&add.age,add.gender,add.address,&add.phone)) == 7)
I'm not sure what you intend with
if(c != EOF){
goto details;
}
details:
Since details: is immediately after the if statement, you go there whether or not the condition succeeds.
You should get out of the habit of using goto, it's generally considered poor programming style. Put the code that should run when the condition is true inside the if. You can use continue and break to restart and end a loop.

File processing in C; won't take input

I'm starting to learn file processing in C. The point of this specific program is to make a file called "clients.dat" where I store the account number, name, and balance of clients at a bank, lets say. I've worked and refined the code so that its a perfect replica of what the textbook provides as an example, yet for some reason mine loops endlessly after the first "scanf" and reprints question marks unto oblivion, without ever making it to the scanf statement inside the while loop. Would anyone have any suggestions as to why this is happening? My compiler is Netbeans and I'm running it on Linux-Ubuntu.
#include <stdio.h>
#include <stdlib.h>
/*
*
*/
int main() {
unsigned int actNumber;
char actName[30];
long double actBalance;
FILE *fPtr;
if((fPtr = fopen("clients.dat", "w")) == NULL) {
printf("File could not be found.\n");
}
else {
printf("Enter the Account Number, Name, and Balance.\n Hit the EoF to exit.\n");
printf("%s","?");
scanf("%d%29s%lf", &actNumber, actName, &actBalance);
while (!feof(stdin)) {
fprintf(fPtr, "%d, %29s, %.2lf\n", actNumber, actName, actBalance);
printf("%s", "?");
scanf("%d%29s%lf", &actNumber, actName, &actBalance);
}
fclose(fPtr);
}
return;
}
The end of file marker is set on stdin only when you press a special key combination on the console.
You can make your loop work correctly by using the return value of scanf(), like this
while (scanf("%d%29s%lf", &actNumber, actName, &actBalance) == 3)
{
fprintf(fPtr, "%d, %29s, %.2lf\n", actNumber, actName, actBalance);
printf("%s", "?");
}
After the first scanf() a '\n' character is left in the input stream, when you call scanf() again inside the loop, the character is consumed then ignored, and scanf() fails returning a value that is less than 3, the process is repeated over and over causing the infinite loop.
The following solution, however, is better. Using fgets() allows a better handiling of the '\n' character left unread in the stdin,
char line[100];
while (fgets(line, sizeof(line), stdin) != NULL)
{
if (sscanf(line, "%d%29s%lf", &actNumber, actName, &actBalance) != 3)
continue;
fprintf(fPtr, "%d;%29s;%.2lf\n", actNumber, actName, actBalance);
fprintf(stdout, "?");
}
note that I remove the white spaces in the printf() format, and replaced the , with ; because in some locales the , is the decimal separator, it's just instintictive not to use it, you can use it if you ensure that . is the decimal separator.

Cant read input line in C

Sorry for a stupid question, but this is really starting to annoy me.
I need to take a line of input from a console. Here's the relavent fragment of code:
int number_read=0;
char line[80];
printf("Enter register address: ");
number_read = scanf("%s\n", line);
printf("number of characters entered: %d; characters entered: %s.\n", number_read, line);
if (number_read > 0) {
<read some registers and display the results.>
}
It doesn't work. The "Enter register address" line is printed, and the cursor stops at the end of the line, and moves to the next line when I press enter, but then nothing else happens. I've tried replacing scanf() with fscanf(stdin,...), with fgets(stdin), gets, GNU's getline(), a short function that does the same thing, with diagnostics:
char *new_line, ch;
for(;;) {
ch = fgetc(stdin);
if(ch == EOF) break;
if((*line++ = ch) == '\n') break;
printf("Line so far: %s\n", line);
}
*line='\0';
I get the same response from all of them. I'm including all the requisite headers.
I'm on a Windows XP box, compiling with gcc 3.4.5 (mingw).
Can anyone see what I'm doing wrong?
In scanf you should use a %i to represent a int so, try with
scanf("%I", number_line);
The following code will works,
char buff_msg[1024];
while(1)
{
if(fgets(buff_msg,1024, stdin) != NULL){
printf("%s\n", buff_msg);
memset(buff_msg, 0, 1024); // you will need this line
}
}
You can
break the loop on your own condition
try read() it works in MinGW replace
this
number_read = scanf("%s\n", line);
with this also include #include<unistd.h>
number_read = read(STDIN_FILENO, (void *)line,sizeof line);
value scanf returns is not the number of strings in the number of elements to read(this case meybe 1).
Use the %n To get the number, such as desired.
scanf("%s%n", line, &number_read);
printf("number of characters entered: %d; characters entered: %s.\n", number_read, line);

Read int and char from the same file in C

I have a text file that looks like this:
i 3755
i 3633
i 4435
i 1434
how would I go about reading this as an input, I've tried using fscanf, but it keeps on giving me a random character after the 'i'
for example output would look like
i% 3755
i5 3633
etc.
Here is what I've been trying:
int data = 0;
char command;
if(fptr==NULL)
printf("File Cannot Be Read");
fscanf(fptr,"%c %d\n", &command, &data);
printf("%c " , command);
printf("%d\n" , data);
fscanf(fptr,"%s %d\n", &command, &data);
printf("%c " , command);
printf("%d\n" , data);
fscanf(fptr,"%s %d\n", &command, &data);
printf("%s " , command);
printf("%d\n" , data);
none of them seem to work. Thanks for your help in advance!
edit: Heres the working code for anybody that was having the same problem:
int data = 0;
char command;
fptr = fopen(argv[1], "r");
if(fptr==NULL)
printf("File Cannot Be Read");
while(fscanf(fptr,"%c %d \n", &command, &data) == 2)
{
if(command == 'i')
{
printf("insert found\n");
}
if(command == 'd')
{
printf("delete found\n");
}
}
}
fscanf(fptr,"%c %d", command, &data);
should be:
fscanf(fptr,"%c %d", &command, &data);
getchar(); // consume the newline character that fscanf left.
Assuming you defined:
char command;
int data;
For simplicity, I would recommend you to, in a loop, read a line using fgets() and then use strtok() to get different 'strings' and then cast according to your parsing methodology. But Mike is right as well, you can use fscanf(fptr, "%c %d\n", &command, &data) to read. When you're using a string, you can ignore the usage of "&" before the variable name. But when its a character or an integer or a float.. you will need to use the address of operator("&")
at this line :
fscanf(fptr,"%c %d", command, &data);
you should give it a pointer to command. like this :
fscanf(fptr,"%c %d", &command, &data);
the next line can't work because the reading cursor is already at the end of the file.
This is incorrect and will result in a buffer overrun:
fscanf(fptr,"%s %d", &command, &data);
as command has only enough space for a single char but fscanf() with format specifier "%s" will read until next whitespace and then write a terminating null character into command. Use a char[] to read and restrict the number of chars to be read.
Note that the NULL check just prints an error message, it does not actually prevent use of a NULL file pointer.
To ensure that each line is of the correct format use fgets() to read a line and then use sscanf() to read the fields. If fscanf() is used to read directly from the file then these two lines:
i
3755
are treated identically to the single line:
i 3755
as a new-line character is also whitespace.
Example:
if (fptr)
{
char line[1024];
while (fgets(line, 1024, fptr))
{
char command;
int data;
if (2 == sscanf(line, "%c %d", &command, &data))
{
/* Use 'command' and 'data'. */
}
}
}
in your fscanf function you have to expect the return to line by adding space at the end of format. Like this
fscanf(fptr,"%c %d ", &command, &data);
The space character replaces return to new line, tabulation and spaces
BTW I see that you use %s to read a char &command and this is incorrect
fscanf(fptr,"%s %d\n", &command, &data);
you have to use this instead
fscanf(fptr,"%c %d ", &command, &data);

Resources