I want to read int from a file
The first line is composed of 1 int and the second of 2
ie
1
2 3
if i do
fscanf(FILE, "%d \n %d %d", &a, &b, &c);
I obtain correctly the 3 numbers
but if i put all the numbers on the same line in the file
ie 1 2 3
I obtain the same result (and that's not what i want)
I want to know : How to force the user to go to a new line in his file ?
Edit :
As it seems unclear to some (i'm sorry for that) i want that the file
1
2 3
Produce the result :
a = 1
b = 2
c = 3
And the file
1 2 3
produce either an error or
a = 1
b = 0
c = 0
You need to read each line into a char buffer using fgets and parse each line with its own sscanf. You can use an extra %s on the end of the format string (and an extra pointer argument to a dummy variable of type char *) to detect whether the line contains extra stuff after the fields you're looking for.
fscanf(FILE, "%d", ...); first scans and discard white space before scanning for int characters. In scanning white-space, both ' ' and '\n' are treated the same, so using '%d' loses the end-of-line.
fscanf(FILE, "\n", ...); and fscanf(FILE, " ", ...); do the same thing: scan and discard any white space. Using "\n" does not scan only for '\n'.
Code could use fscanf(FILE, "%d%*1[\n]%d %d", &a, &b, &c) == 3, to find a '\n' after a, but additional '\n' could be lurking in other places.
The only way using scanf() family to detect a '\n' involves using '%c' or '%[]' or '%n'. It is easier to use fgets() and then parse with sscanf() or strtol().
int Read1and2int(FILE *stream, int *a, int *b, int *c) {
char buf[100];
int n;
if (fgets(buf, sizeof buf, stream) == NULL) return EOF;
int count = sscanf(buf,"%d %n", a, &n);
// Non-numeric or extra data
if (count != 1 || buf[n]) return 0;
if (fgets(buf, sizeof buf, stream) == NULL) return 1;
count = sscanf(buf,"%d%d %n", b, c, &n);
// Non-numeric or extra data
if (count != 2 || buf[n]) return 1;
return 3;
}
Related
I'm working on one of my C assignments. I have a little problem with taking unknown numbers of input. This is my code:
while ((a = getchar()) != EOF){
ungetc(a,stdin);
scanf(" %c %d %d %d",&a,&b,&c,&d);
arr1[3*i] = b;
arr1[3*i+1] = c;
arr1[3*i+2] = d;
i++;
(I have done all the declaretions befor this)
What i'm trying to do this here is I take inputs and stroe them in three arrays. My input is:
X 10 18 3
r -3 2 1
Y 0 -2 -1
After i write these in terminal, i have to push the buttons ctrl+d twice. And then when i try to check arr1, its like {10, 18, 3, -3 ,2 ,1 ,0 ,-2 ,-1 ,0 ,-2 ,-1} The last input is duplicated and i don't know the reason..
!!! The main thing is that I don't that how many inputs i will take. !!!
Thank you for your help.
After each scanf, the file pointer is left on the trailing newline of input. After the last line of input is scanned and values are assigned to b, c, and d, the getchar in the while loop reads the final newline. Then scanf reads no values so b, c, and d are unchanged. The values that were left from the previous loop are assigned to the array, i is incremented, and then getchar returns EOF and the loop breaks. Always check the value returned by scanf. In other words, this problem evaporates if you use the usual idiom
while(scanf(" %c%d%d%d",&a,&b,&c,&d) == 4) { ...
Also, in this case, the error would have been noticed more readily if you weren't copying the data unnecessarily to the temporary variables b, c, and d, but just did:
while( scanf(" %c%d%d%d", &a, arr + 3*i, arr + 3*i +1, arr + 3*i + 2) == 4
which would be written a lot more cleanly as:
int *base = arr;
while( scanf(" %c%d%d%d", &a, base, base + 1, base + 2) == 4 ) {
base += 3; ...
Note that in all of these, a must really be declared as a char, but to assign a from getchar requires that a be an int, and that should be a clue that trying to use getchar/ungetc is a mistake.
To summarize, on all but the first line of input, getchar is reading '\n', ungetc pushes that newline back to the buffer, and then scanf skips over it because of the leading whitespace in the format string.
regarding:
while ((a = getchar()) != EOF){
ungetc(a,stdin);
scanf(" %c %d %d %d",&a,&b,&c,&d);
arr1[3*i] = b;
arr1[3*i+1] = c;
arr1[3*i+2] = d;
i++;
Suggest using the returned value from scanf(), similar to:
int i = 0;
while ( scanf(" %c %d %d %d",&a,&b,&c,&d) == 4 )
{
arr1[3*i] = b;
arr1[3*i+1] = c;
arr1[3*i+2] = d;
i++;
}
I have just started learning file handling in C, and wondered if I could perform mathematical calculations by reading input from a file, here is the code for just reading the characters and displaying on the console :
int main(void)
{
FILE *p;
char a, b, c, ch;
p = fopen("numbers.txt", "a+");
while((ch = getc(p)) != EOF)
{
fscanf(p, "%c %c %c\n", &a, &b, &c);
printf("%c %c %c\n", a, b, c);
}
fclose(p);
return 0;
}
numbers.txt contains (with a space before each character) :
2 + 3
5 + 6
6 + 7
output obtained is :
2 + 3
+ 6
+ 7
I am unable to understand why first line output is as expected but second and third line have missing character, even though new line is given after each expression in numbers.txt.
An additional character is being scanned at the beginning of each iteration of your while loop
while((ch = getc(p)) != EOF)
Try making the fscanf() statement as the condition for your while loop and check for its return value. According to cplusplus.com:
On success, the function returns the number of items of the argument
list successfully filled. This count can match the expected number of
items or be less (even zero) due to a matching failure, a reading
error, or the reach of the end-of-file.
If a reading error happens or the end-of-file is reached while
reading, the proper indicator is set (feof or ferror). And, if either
happens before any data could be successfully read, EOF is returned.
So try changing your while condition to anyone of the following:
while (fscanf(p, " %c %c %c", &a, &b, &c) != EOF)
or
while (fscanf(p, " %c %c %c", &a, &b, &c) == 3)
Using whitespace in the scanf format specifier, like you do with \n, matches any amount of whitespace. The \n and the leading space on the next line are consumed, causing getc to remove the first digit instead of the leading space.
I’d skip getc entirely, as #BLUEPIXY suggested:
while (fscanf(p, " %c %c %c", &a, &b, &c) == 3) {
printf("%c %c %c\n", a, b, c);
}
I'm currently trying writing a program using C (very new to C - only been learning it for 2 weeks), and I wanted to get a string of input from the user by stdin, in which the string has a char, followed by 2 floats (each has space in between). Example would be: "y 2.1 1.1".
My question is how can I obtain and store the 3 inputs, while making sure the first is a char, and the following two inputs are floats?
Stick with sscanf(), but don't forget to check its return value (look here). What really happens for input "y 1u 1" is that sscanf will read and store the char, which is valid, then it will read and store the int 1, which is valid, and then stop, because "u" does not match the format string.
Below is example code (using scanf() rather then fgets() and sscanf()).
char in1;
int in2,in3;
int retval;
/*
char array[100] = {'\0'};
fgets(array, 100, stdin);
retval = sscanf(array, "%c %d %d", &in1, &in2, &in3);
*/
retval = scanf("%c %d %d", &in1, &in2, &in3);
printf("Scanned %d items\n", retval);
printf("Here they come: ");
if(retval > 0) {
printf("%c ", in1);
}
if(retval > 1) {
printf("%d ", in2);
}
if(retval > 2) {
printf("%d", in3);
}
putchar('\n');
How can I obtain and store the 3 inputs, while making sure the first is a char, and the following two inputs are ints?
problem with this code is that there are extra spaces at the very end, and I don't know how to get rid of it.
A simple way to use sscanf() and check if there is extra anything after the scanned variable is to use "%n" to record the location of the scan at that point.
char in1;
int in2, in3;
int n = 0;
sscanf(array,"%c %d %d%n", &in1, &in2, &in3, &n);
if (n > 0 && (array[n] == '\n' || array[n] == '\0')) {
Success(in1, in2, in3);
}
It is always important to check the results of sscanf(). One way is to check its return value which should be 3 here. Unfortunately that does not tell us if anything exist after in3. By setting n == 0 and then testing n > 0, code knows that scanning proceeded all the way successfully to "%n". Code can also test what character the scanning stopped at.
So I am trying to figure out how to use fscanf to read multiple lines from an in file. The in file looks like this:
8
1 8
1 7
1 9
1 8
3 2
3 8
0 0
1 5
2 4
0 0
The first number I want to obtain is going to be the size of an array I will be creating so I will just set it to n(in this example that number being the 8 at the beginning).
The following digits will be as follows: the left most number will tell me what index in my array I will queue the right most number in a list I have created.
The zeros just indicate where I will be terminating.
The way I was attempting to do it thus far is:
fscanf(in, "%d", &n)
//have obtained n
arr[n];
while( fgets(line, MAX_LEN, in) != NULL){
fscanf(in, "%d %d", &x, &y);
//from here I place them in their corresponding arrays
}
Code:
int main()
{
int i, j, k;
scanf ("%d\n", &i);
printf ("%d\n", i);
while (i){
--i;
scanf ("%d %d\n", &j, &k);
printf ("%d %d\n", j, k);
}
}
Execution:
./a.out <input.txt
This is using file redirection. Also check about freopen. If u use this, you no need to worry about fscanf syntax. If you suppose to fscanf only, then there are lots of example in Google. Please refer it.
1) Using fgets() right after fscanf(in, "%d", &n) leaves the first line's '\n' in stdin and only read a short line. Suggest avoid mixing fgets() with fscanf().
2) After using fgets() to read the line (good idea), use sscanf() (or strtol()) to read the numbers, not fscanf()
if (fgets(line, MAX_LEN, in) == NULL) Hanlde_EOF();
if (sscanf(line, "%d", &n) != 1) Handle_BadInput();
arr[n];
while(fgets(line, MAX_LEN, in) != NULL){
if (sscanf(in, "%d %d", &x, &y) != 2) Handle_BadData();
...
}
I am really new programming in C. How can I do the same in C, maybe in a more simple way than the one I do in Java?
Each line of the input has two integers: X and Y separated by a space.
12 1
12 3
23 4
9 3
InputStreamReader in = new InputStreamReader(System.in);
BufferedReader buf = new BufferedReader(in);
int n;
int k;
double sol;
String line = "";
line = buf.readLine();
while( line != null && !line.equals("")){
String data [] = line.split(" ");
n = Integer.parseInt(data[0]);
k = Integer.parseInt(data[1]);
calculus (n,k);
line = buf.readLine();
}
Use fgets() to read a line of text and sscanf() to parse it:
#include <stdio.h>
int main(void)
{
int n, k;
char line[64]; // adjust size as necessary
while(fgets(line, sizeof line, stdin) && sscanf(line, "%d %d", &n, &k) == 2)
printf("n=%d, k=%d\n", n, k); // dummy code
return 0;
}
Using scanf() alone to read directly from stdin might be possible with scansets, but it's not as easy as it looks because whitespace characters (including newlines) are skipped.
No compiler, so please fix as needed. Also the variable decalrations are C++ style
#include <stdio.h>
...
while (!feof(stdin)) {
int n = 0, k = 0;
if (scanf("%d %d\n", &n, &k) != 2) continue;
// do something with n and k
}
C++ solution (with streams) may be simpler still
fscanf(filehandle, "%d %d\n", n, k);
The file variable is called FILE
To open a file use fopen()
Reading and writing are done with fgets() and fputs()
This is all in stdio.h.
Example:
#include <stdio.h>
int main(){
FILE *input = fopen("file.txt", "r");
char text[100]; // Where we'll put our text we read
fgets(text, 100, input); // Get up to 100 chars, stops at the first newline
puts(text); // In your example, this should print out "12 1"
fgets(text, 100, input); // Get the next up to 100 chars
puts(text); // Prints "12 3"
return 0;
}
Let me know if there's anything wrong with the code, I don't have a C compiler with me.