Segmentation fault in sscanf while reading FILE - c

When I compile my program I get no error, but when I start it I get a "Segmentation fault". The FILE I try to read is build like this:
322;Peter;m
233;Chad;m
211;Lisa;w
I have the strong feeling my sscanf function is the issue.
Please help me.
#define MAXCHAR 30
#define MAXZEILE 40
void speicher(char Z[MAXCHAR]){
FILE *QUELL;
int a;
char n[MAXCHAR];
char g;
char string[MAXZEILE];
QUELL=fopen(Z,"r");
fgets(string, MAXZEILE, QUELL);
sscanf(string, "%d;%s;%c", &a, n, &g);
printf("%d, %s, %c", a, n, g);
fclose(QUELL);
}

My bad:
the MAXCHAR for the FILE input was to low.
The FILE had more than 30 chars.

In your sscanf %s does not know when to stop:
sscanf(string, "%d;%s;%c", &a, n, &g);
Without properly tokenizing on ;, %s will keep grabbing input until the next whitespace (which in your case will be the end of the line). It should be changed to
sscanf(string, "%d;%[^;];%c", &a, n, &g);
The %[^;] specifies to grab characters that are not a ; thus achieving the desired result.
For more robustness, you may want to look into using strtok to first separate it ; and then process each individual segment.

I assume that to your purposes the lines written below are enough
ReturnVal = sscanf(strinp1, "%d %c %100[^;] %c %c", &a, &Separator1,
n,&Separator2, &g);
Read an integer
Read then the character ';'
Read at most 100 characters, stop reading encountering the character ';'
Read then again the character ;
Read the next character. (man or woman???).

Related

Scanf for not the same amount of data in C

I am trying write a code for program in C, but i found a problem i am not able to solve. I get a set of input, but the input is not always the same. How do i use scanf to read not always the same amount of data?
Input 1):
+ 12345 Lala
Input 2):
- 12345
If i use something like this:
scanf("%s %d %s", a[i], &b[i], c[i]);
the terminal requests more data for me (which i understand). So how do i use scanf to sometimes read all three (string, integer, string) and sometimes just two (string, integer)?
Start by reading the whole line
char line[100];
scanf(" %[^\n]", line);
or
fgets(line, 100, stdin);
Then use sscanf to read the values from the line.
int itemsRead = sscanf(line, "%s %d %s", a[i], &b[i], c[i]);
The return value of sscanf will tell you how many values you successfully read from the line.
You can try fgets:
char *fgets(char *s, int size, FILE *stream);

c - in a series of input using scanf, last value is not being printed ( using printf )

Here is my code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int i, j;
float k, l;
char a, b;
scanf("%d%d%f%f%c%c", &i, &j, &k, &l, &a, &b);
printf("%d %d %f %f %c %c", i, j, k, l, a, b);
return 0;
}
The program takes in all the six inputs but prints only first 5 variables.
Can anyone please point out the problem in my concept/program ?
As predicted, the problem is with %c
scanf("%d%d%f%f%c%c", &i, &j, &k, &l, &a, &b);
As it stands, given your input like below, then your last character d would not be read - instead a space right after c is interpreted as your character input:
1 2 3.0 4.0 c d
So your scanf should be changed to:
scanf("%d%d%f%f %c %c", &i, &j, &k, &l, &a, &b); // <-- Notice there is a space before each %c to read over space characters
Note: C is indeed strange in this aspect, I guess everyone has to encounter this issue a few times before remembering this kind of weird issue - that you should always be careful with %c of scanf, and you need to add space before it to read character input properly.
To get a single character from the user in C, people use either scanf() with the format specifier %c or getchar(). Both functions read a character from the standard input stream (the difference between them is that getchar() reads just one character, whereas scanf() can read a variety of formats).
But both have the same pitfall: when the user enters a character and then afterwards presses the enter key. Thus there are actually two characters in the input stream: the character entered and the newline character.
If you don't remove the newline character from the input stream, it could interfere with input functions later in the program. It seems that the input is ignored.
Simple solution would be scanf(" %c", &ch);

why does fscanf read garbage values

I have a simple file as below:
1
3
a 7
and when I run the code below, I get some unexpected result. I initially try to read the first two integers and then read the character a and number 7. There is no white space after the number 1 or 3.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main(int argc, char **argv)
{
FILE *f;
f = fopen(argv[1],"r");
int num1, num2, num3;
char t;
fscanf(f, "%d",&num1);
fscanf(f, "%d",&num2);
fscanf(f, "%c %d", &t, &num3);
printf("%c %d\n", t, num3);
}
EDIT:
Input is the file with the content:
1
3
a 7
and the output is a new line and some garbage. Expected output should be a 7
EDIT 2: it reads correctly 1 and 3. Then trying to read a single character a if fails
Loooks at what happens when you run this:
fscanf(f, "%d",&num1);
skips whitespace (of which there is none), then reads an integer (1)
fscanf(f, "%d",&num2);
skips whitespace (the newline at the end of the first line) then reads an integer (3)
fscanf(f, "%c %d", &t, &num3);
reads the next caharcter from the input (a newline), then skips whitespace (none) and tries to read an integer. The next input character is 'a', so this fails, and the fscanf call returns 1 without writing anything into num3.
So the problem you are having is that due to the fact that %c does NOT skip whitespace, you are reading the whitespace (newline) instead of the character you expect. The most obvious solution is to add a space () to the format to skip whitespace:
fscanf(f, " %c%d", &t, &num3);
Note that I've also removed the space before %d, as it is redundant (%d always skips whitespace).
In addition, it is always a good idea to check the return value of fscanf to make sure it is reading the number of input items you expect.

fscanf reading newline character

I have been slowly tracking down my error for my program. I have narrowed it down to this.
I have a user input
fscanf(stdin, "%c %c %d", &car, &dir, &amount);
the first time I access it it works fine, correctly reading in the values. The second time in the loop it reads a \n into car instead of the char I give it. it then reads what should have been in car into dir. amount reads correctly. As car is passed to other functions for counting I eventually end up with a segfault.
Is it reading in the \n from the previous line or something?
The "%c" conversion specifier does not do the usual whitespace trimming.
Try adding a space before the first conversion specifier
if (fscanf(stdin, " %c %c %d", &var, &dir, &amount) != 3) { /* error */ }
Or, maybe better, read a full line and parse it within your program
char buf[1000];
fgets(buf, sizeof buf, stdin);
parse(buf);

How do i ignore characters after a certain spot on each line in C?

I am trying to input txt files into my C program that look something like this
123 x 182 //this is a comment in the file
1234 c 1923 //this is another comment in the file
12 p 3 //this is another comment in the file
I need to store the int, the single character and the other int on each line and then I want to ignore everything else on the line. Here is what I tried....
while (fscanf(file, "%d %c %d", &one,&two,&three) !=EOF)
{
printf("%d %c %d\n", one,two,three);
}
Right now I'm just printing out the values to test the process. So, if I test this with a file that does not have any comments or extra stuff after the first 3 things I need, it works perfectly. But if there is extra stuff, I get stuck in an infinite loop where the first line is repeatedly printed.
There may be a better way in C, but you could add a loop inside of your current loop to read in the remaining characters until you hit a newline.
while (fscanf(file, "%d %c %d", &one,&two,&three) !=EOF)
{
printf("%d %c %d\n", one,two,three);
while(fgetc(file) != '\n'){};
}
This should break out of the nested while loop as soon as the character it gets is a newline, and the next fscanf will begin on the next line.
If you're libc supports POSIX 2008 (like at least glibc on linux does), you can use getline and sscanf:
int len;
char *line;
while (getline(&line, &len, file) != -1) {
sscanf(line, "%d %c %d", &one, &two, &three);
printf("%d %c %d\n", one,two,three);
...
}

Resources