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++;
}
Related
I have a text file with n lines of m length (it doesn't matter in the long term ). In every line, there is a sequence like this:
1 + 2 + 5 - 3 =
I'm using fscanf function to catch all numbers and operators and calculate it and when '=' operator found it prints into a different file. I'm using a loop . My question is how does C recognizes a number and operator? I know the operator is a type of %c and the number is of type %d, but how my program does work properly and why it doesn't take them for example 5 as a character :
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *InFile;
FILE *OutFile;
int number=0;
int result=0;
char operator;
int foundEqualsOp=0;
InFile = fopen("dane.txt","r");
OutFile = fopen("wynik.txt","w");
while(fscanf(InFile,"%d",&result)!=EOF)
{
number = 0;
foundEqualsOp = 0;
while(!foundEqualsOP){
fscanf(InFile,"%c",&operator);
if(operator == '='){
foundEqualsOp = 1;
fprintf(OutFile,"%d\n",result);
}
else if(operator == '-'){
fscanf(InFile,"%d",&number);
result = result-number;
}
else if (operator == '+'){
fscanf(InFile,"%d",&number);
result = result + number;
}
}
}
fclose(InFile);
fclose(OutFile);
return 0;
}
Let's assume your input file contains the following as in your example:
1 + 2 + 5 - 3 =
The outer scanf reads with %d. This picks up 1 as the integer value 1 and puts it in result.
Now the inner scanf runs with %c. It reads the space after 1 so none of the if blocks are entered and the inner loop runs again. The inner scanf again reads with %c and reads the + character. This causes the if (operator == '+') block to be entered where a call to scanf uses %d. This format specifier skips over the space after the + and reads 2 as the integer value 2 and adds it to result.
The above happens again reading the space after 2, the + that follows, and the space and 5 that follows. And again for the following space, -, space, and 3.
After that, the scanf in the inner loop reads the space after 3 and does nothing, then on the next iteration it reads the = after which it prints the result and sets the flag to exit the inner loop.,
I am doing homework to school. Task is to make program in C that can do some simple things with matrixes like *, -, +.
My program is reading matrixes and save them to int array. When the matrix input ended, I scanf to char to know what operation iam going to do with the matrixes. Operation are stores in char array. (on input can be up to 100 matrixes so 99 operations in between). If user writes * everything is okay, BUT when user writes '-' or '+' it stores '/n'. I was googling and debuging but still dont know why this happens. Any suggustions are welcome.
User input looks like this: First line is size of matrix.
2 3
76 98 -31
30 30 32
-
2 3
89 25 38
1 -32 -38
int* readMatrix(int width, int height, char arrayOperation[], int numberOfMatrix, int*err)
{
int sizeOfMatrix = ((height*width) + 3), i = 0;
char operation = 'n';
int *arrayMatrix = malloc(sizeOfMatrix* sizeof(int));
arrayMatrix[0] = width;
arrayMatrix[1] = height;
for (i = 2; i <= sizeOfMatrix; i++)
{
if (i == sizeOfMatrix)
{
if (scanf_s("%c", &operation) != EOF)
{
if (operation == '*' || operation == '-' || operation == '+')
{
arrayOperation[numberOfMatrix] = operation;
}
else
{
*err = 100;
}
}
else
{
arrayOperation[numberOfMatrix] = 'n';
break;
}
}
else if (scanf_s("%d", &(arrayMatrix[i])) == 1)
{
*err = 0;
}
}
return arrayMatrix;
}
In case of * the var operation==*,but in -,+ operation==/n. I call this function in loop, output array is stored in array of int**.
scanf("%c" reads the very next character without skipping any whitespace, so it will store whatever is after the last thing read -- usually a newline. If you want to skip whitespace, add a space to the format:
scanf(" %c", &operation)
this will skip any whitespace and store the next non-whitespace character.
You don't need this with %d as all of the conversion patterns except %c and %[ skip whitespace.
I was discusing this particular problem with my lecturer.
I understand this: when scanf reading the number it jumps over whitespace and /n.
So reading "32/n - " results in reading everything. When reading "32/n * " it stops at "*" because its not sign of any number. So its behave little stupid.
This can solve using fgets() function and read it by char.
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.
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;
}
Hi i am quite new into programming and i need some small help on converting char array to string and i am not sure where has gone wrong. i need to get user input in %c and i input for the first input - aabcc and then clicks on enter
the second input - fsdff then enter again
3rd input - rewrr then enter again
4th input - zzxcc and enter again the
last input - asdfg.
But the outputs gives me array 1 = aabcc , 2nd array = fsdf (one of gone missing) 3rd array = f '\n' ... followed by 3rd 4th and 5th array displayed incorrectly. Thanks all in advanced.
int main()
{
int i, j;
char ch[5][6];
char c[5][5];
for (i = 0; i < 5; i++)
for (j = 0; j<5; j++)
scanf("%c", &c[i][j]); // get user input
memcpy(ch[0], c[0], 5);
ch[0][5] = '\0';
memcpy(ch[1], c[1], 5);
ch[1][5] = '\0';
memcpy(ch[2], c[2], 5);
ch[2][5] = '\0';
memcpy(ch[3], c[3], 5);
ch[3][5] = '\0';
memcpy(ch[4], c[4], 5);
ch[4][5] = '\0';
printf("array 1 = %s, array 2 = %s , array 3 = %s , array 4 = %s , array 5 = %s ", ch[0], ch[1], ch[2], ch[3], ch[4]);
}
Change below scanf
scanf("%c", &c[i][j]);
to
scanf(" %c", &c[i][j]);
^
|
space here
Reason behind it is, you are entering input as aabcc<Enter>, there are 6 characters in the input buffer. scanf("%c") reads the a, a, b, c and then c, interpreting them as the aabcc, but the newline character is still in the input buffer. Thats why you see newline as well when you try printing them.
Your scanf buffer (c[][]) is too small to hold all the characters from a single entry. As another writer pointed out, you have not added space for the '\n' character in your static allocation.
The size of your scanf character array (c[][]) should be = max no. of words x (max no. of chars in a word + 1)
The plus one is for the newline character.
#define MAXWORDSIZE 5
#define MAXWORDS 10
char c[MAXWORDS][MAXWORDSIZE + 1]; // Newline character
char ch[MAXWORDS][MAXWORDSIZE + 1 + 1]; // Newline and NUL character