scanf with variable arguments (C lang) - c

My Input is as below.
3 8 9 3
4 2 4 0 3
5 1 5 9 3 1
0
1 5
As you can see, the first number of each line means the number of how many inputs left in the line.
How can I get all input via scanf?
Or please let me know something new.

As mentioned in the comments, the problem with scanf() is (among other things) the way it handles the newline character. However, the sscanf() function (reading from a string) doesn't have this issue! So, depending on exactly what you're trying to achieve, maybe something like the following code will help:
#include <stdio.h>
int main()
{
int a[5], n = 0, given;
char buffer[200];
while (n >= 0) {
printf("\nEnter n and a list of numbers: ");
fgets(buffer, 200, stdin);
printf("Input was: %s", buffer);
n = -1;
given = sscanf(buffer, "%d %d %d %d %d %d", &n, &a[0], &a[1], &a[2], &a[3], &a[4]);
if ((given < 1) || (given != n + 1)) printf("Invalid input!\n");
}
return 0;
}
I'm not saying it's an ideal solution, or even that you could use it, but it may give you some clues as to where to go next.
Let me know how you find it.

Related

How do you take input separated by space in a single line in C?

I was attempting the CodeChef contest today where I came across this problem. I managed to do the code, but there's one error that I don’t know how to take all inputs in a single line separated by space. I checked thousands of answers on Stack Overflow, but I still didn’t get it. How can I fix this problem?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int t, n, a, b, c, x, y, z;
//printf("No. of test cases\n");
scanf("%d", &t);
for(int i=0; i<t; i++)
{
//printf("Enter three inputs\n");
scanf("%d\t%d\t%d", &a, &b, &c);
}
x = a + b;
y = b + c;
z = a + c;
if(x>y && x>z)
{
printf("%d", x);
}
else if(y>a && y>z)
{
printf("%d", y);
}
else
{
printf("%d", z);
}
}
It is the same and is not a big deal.
Just enter your first input and instead of pressing Enter, you press Space. Then enter your second input, press Space again, enter the third input, and then press Enter. It will definitely work.
I will show you two programs and then may be you see a way to read the values in a controlled way.
scanf() is controlled by the mask, the thing like "%d\t%d\t%d" in your code. And scanf() has the notion of white space, treating spaces and tabs and newlines as same thing. These sometimes makes a mess when reading keyboard input, because scanf() refuses to end and keeps reading trying to satisfy the supplied input mask. [See the first example program].
Fact is that these functions were written to consume tabular data, like CSV files --- Hence the name: scan formatted input. But stdin with a keyboard with 105 keys are not formatted input: The user can key anything in.
Always test the return of scanf()
scanf() returns a negative value for error, or the number of items read. In your case, it can return 0, 1, 2 or 3: there are three fields to be read in "%d\t%d\t%d"
Example 1
#include <stdio.h>
int main(void)
{
int A, B, C;
int res;
do
{
printf("\n==> Enter up to 3 integer numbers, separated by spaces: ");
res = scanf("%d %d %d", &A, &B, &C);
switch (res)
{
case 0:
printf("\nscanf() read no numbers\n");
break;
case 1:
printf("scanf() read a single value, A = %d\n", A);
break;
case 2:
printf(
"scanf() read two values, A = %d, B = %d\n", A, B);
break;
case 3: // Fall-through
default:
printf(
"scanf() read all 3 values, A = %d, B = %d, C = "
"%d\n",
A, B, C);
break;
}; // switch()
} while ( res != 0);
return 0;
}
This code uses scanf() on stdin as usual.
Some results from example 1
==> Enter up to 3 integer numbers, separated by spaces: 1 2 3
scanf() read all 3 values, A = 1, B = 2, C = 3
All good when the numbers come as expected...
==> Enter up to 3 integer numbers, separated by spaces: 1 2
3
But now scanf() reads 1 and 2, but the user entered a few newlines, that scanf() skips like white space and will forever until read a letter or the final digit
And note this one:
==> Enter up to 3 integer numbers, separated by spaces: 1 end
scanf() read a single value, A = 1
==> Enter up to 3 integer numbers, separated by spaces:
scanf() read no numbers
The user entered 1 end. As soon as the e is read scanf() returns 1 and A is set to 1, of course. But then the next call has the end letters and the newline to read, so the next call of scanf() reads these letters, returns 0 and the program ends.
This is the kind of outcome that surprise many beginners and even a few professionals sometimes.
And these is hard to control.
For these reason many times is better to read the whole line by other means, and use sscanf() to consume the data, as in example 2. The idea is that all data in the line is consumed, and sscanf() parses the data from memory.
I believe that the example is ok to understand.
Example 2
#include <stdio.h>
int main(void)
{
int A, B, C;
int res;
printf("Enter up to 3 integer numbers, separated by spaces or ENTER to exit: ");
char line[100] = {0};
char* p = line;
// read whole line, up to the possible '\n'
p = fgets( line,100,stdin);
if ( p[0] == '\n') return 0; // input empty
do
{
res = sscanf(line, "%d %d %d", &A, &B, &C);
switch (res)
{
case 0:
printf("scanf() read no numbers\n");
break;
case 1:
printf("scanf() read a single value, A = %d\n", A);
break;
case 2:
printf(
"scanf() read two values, A = %d, B = %d\n", A, B);
break;
case 3: // fall thru
default:
printf(
"scanf() read all 3 values, A = %d, B = %d, C = "
"%d\n",
A, B, C);
break;
}; // switch()
printf("Enter up to 3 integer numbers, separated by spaces or ENTER to exit: ");
p = fgets( line,100,stdin); // next line
if ( p[0] == '\n') return 0; // input empty
} while ( res != 0 );
return 0;
}
Output for example 2
Enter up to 3 integer numbers, separated by spaces or ENTER to exit: 1
scanf() read a single value, A = 1
Enter up to 3 integer numbers, separated by spaces or ENTER to exit: 1 2
scanf() read two values, A = 1, B = 2
Enter up to 3 integer numbers, separated by spaces or ENTER to exit: 1 2 3
scanf() read all 3 values, A = 1, B = 2, C = 3
Enter up to 3 integer numbers, separated by spaces or ENTER to exit: 1 2 end
scanf() read two values, A = 1, B = 2
Enter up to 3 integer numbers, separated by spaces or ENTER to exit: end
scanf() read no numbers
Enter up to 3 integer numbers, separated by spaces or ENTER to exit:
And things are a bit easier to control.

Trying to make scanf not go to a new line in a for loop (C Programming)

Sorry if my English is poor. What I'm trying to do is get the scanf to be entered on the same line. For example Enter value: 1 6 8 9 4 1 2 8 5 and it to be separated by a space. Then the numbers to be stored in an array. This is my code:
#include <stdio.h>
int main(void)
{
int a[10], smallest, i;
printf("Random\n");
for (i = 0; i < 9; i++)
scanf("%d", &a[i]);
smallest = a[0];
for (i = 0; i < 9; i++)
{
if (a[i] < smallest)
{
smallest = a[i];
}
}
printf("\nSmallest Element : %d\n", smallest);
}
Thanks for any help!
Edit: I'm trying to make the user enter 9 numbers which are stored in the array using scanf but when entering the numbers the scanf goes to a new line for example:
> 5
> 6 and so on what I want is for them to enter the number numbers on the same line with a space in between like this Enter value: 1 6 8 9 4 1 2 8 5
Scanf will await for a complete line. I suggest you take your input as a string then use strtok to extract the values and then assign.
Edit: You could use the scanf like that:
scanf( "%d %d ...", &a[0], &a[1]...); //as many values you're to assign
However, I prefer the method I proposed initially. Keep in mind scanf is derived from "scan formatted". You'll also have to handle the result from the scanf, it returns the number of values successfully filled.
you can scanf all numbers in one statement: scanf("%d %d %d %d %d %d %d %d %d %d", &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6], &a[7], &a[8], &a[9]);
This will let you scan 10 numbers with spaces between them, without the need to hit enter every time
note that I scanned 10 ints, because your array can store 10 ints, while your loop only scans 9... (to fix it, change i < 9 to i < 10 as Sourav Ghosh suggested)

How to read an unknown quantity of integers from console?

I have entries like these:
0 5 260
1 0 -598
1 5 1508
2 1 -1170
I don't know previously how many (console) inputs I'll get, so I have to read until there are no entries left.
I started with a code like this:
int a, b, c;
while(scanf("%d %d %d", &a, &b, &c)!=EOF){
// do stuff here
}
But it never stops asking for new input.
Then, I saw people in other threads suggesting this:
int a, b, c;
while(scanf("%d %d %d", &a, &b, &c)==1){
// do stuff here
}
In this case, it doesn't even enter the while.
Does anyone know what I'm doing wrong?
An approach: Continue asking for input until the input is closed (EOF) or some problem is encountered. (Invalid line of input)
The below uses fgets() to read a line.
Then, " %n" to detect where scanning stopped. If scanning does not reach %n, n will still have the value of 0. Otherwise it gets the offset in buffer where scanning stopped, hopefully it was at the null character '\0'.
char buffer[100];
while (fgets(buffer, sizeof buffer, stdin)) {
int n = 0;
sscanf(buffer, "%d%d%d %n", &a, &b, &c, &n);
if (n == 0) {
fprintf(stderr, "3 int were not entered\n");
break;
}
if (buffer[n] != 0) {
fprintf(stderr, "Extra input detected.\n");
break;
}
// do stuff here with a,b,c
}
There are many approaches to solve this issue.
while(scanf("%d %d %d", &a, &b, &c)==1)
means that "if scanf() successfully read just one value, proceed in the loop."
Therefore, if you enter something like 0 junk, the scanf() read just 1 data and will enter the loop once.
Try using
while(scanf("%d %d %d", &a, &b, &c)==3)
to have it enter the loop when scanf() successfully read three values, which is what expected.

How to read from .txt in C

I have to read from a .txt like this (1. - txt line)
1 2
1 2 3
1 3 4
but I have to read like: "1" first line, attribute to x[0], "2" first line attribute to x[1]. I know how to do that but the problem is that I have to skip to the line 2 and do the same, but it doesn't work.
So It'd be like
x[2]=1. x[2]=2, x[3]=3, x[4]=1, x[5]=3, x[6]=4
Is there a way for me to do it???
Thanks!
Let me try to be more especific
1 2 1
2 3 1
3 4
Imagine this is a txt file where 3. 2. and 1. are first, second and third line. I have to read each number on each line and assign to a vet[MAX];
I can do it, but only with the first line. I don't know how to skip to the second one
My code
#include <stdlib.h>
int main (void)
{
char buf[1024];
int numeros[8];
FILE *fp = fopen("teste.txt", "r");
if(fp == NULL)
return EXIT_FAILURE;
while(fgets(buf, sizeof(buf), fp)) {
if(buf[0] == '\n')
continue;
sscanf(buf, "%d %d %d %d %d %d %d", &numeros[0], &numeros[1], &numeros[2], &numeros[3],&numeros[4], &numeros[5], &numeros[6]);
}
fclose(fp);
printf(" \n %d \n %d \n %d \n %d \n %d \n %d \n %d", numeros[0], numeros[1], numeros[2], numeros[3],numeros[4], numeros[5], numeros[6]);
}
the output
3
4
1
131072
2685712
302692880
4798692
Process returned 53 (0x35) execution time : 0.016 s
Press any key to continue.
And I wanted
1 2 2 1 2 3 1 3 4
Assuming your double use of x[2] is a typo, and assuming the line numbers are not really in the file, all you need is to loop doing:
fscanf(file, "%d", &x[i++]);
until it fails. So remember the check the return value, if it isn't 1 it failed to find a number to convert and store, and you should stop.
Of course, this assumes that x has space enough, and that i is initialized to 0.
Use the result of sscanf().
You will likely get 2 or 3 each loop. This means 2 or 3 int were successfully scanned. This number can then be used to determine saving the int in numeros[].
int i=0;
while(fgets(buf, sizeof(buf), fp)) {
int t[7];
int result = sscanf(buf, "%d %d %d %d %d %d %d", &t[0], &t[1], &t[2], &t[3], &t[4], &t[5], &t[6]);
if (result <= 0) break; // EOF, IO error, bad data
for (int r=0; r<result; r++) {
if (i >= sizeof(numeros)/sizeof(numeros[0[)) break; // too many
numeros[i++] = t[r];
}
}

Validate Input to a C Program

i have a c program in which i am accepting 2 numbers as input.
How do i validate if input entered is numbers only and not characters.
void main()
{
int a,b;
printf("Enter two numbers :");
scanf("%d%d",&a,&b);
printf("Number 1 is : %d \n Number 2 is : %d",a,b);
}
[Edit] Added Sample Code
Besides the other interesting suggestions (especially the one with scanf), you might also want to use the isdigit function:
The isdigit() function shall test
whether c is a character of class
digit in the program's current locale
note that this function examines only ONE char, not an entire bunch of them.
It is always good practice to resort to already-built functions; there are intricacies you might not be aware of even in the simplest task, and this will make you a good programmer overall.
Of course, in due time you might want to look at how that function works to get a good grasp of the underlying logic.
scanf returns the number of items that it has successfully scanned. If you asked for two integers with %d%d, and scanf returns 2, then it successfully scanned both numbers. Any number less than two indicates that scanf was unable to scan two numbers.
int main()
{
int a,b;
int result;
printf("Enter two numbers :");
result = scanf("%d%d",&a,&b);
if (result == 2)
{
printf("Number 1 is : %d \n Number 2 is : %d",a,b);
}
else if (result == 1)
{
// scanf only managed to scan something into "a", but not "b"
printf("Number 1 is : %d \n Number 2 is invalid.\n", a);
}
else if (result == 0)
{
// scanf could not scan any number at all, both "a" and "b" are invalid.
printf("scanf was not able to scan the input for numbers.");
}
}
One other value that scanf may return is EOF. It may return this if there is an error reading from the stream.
Also note that main returns int, but you have it declared with void return.
Read user line of text input as a string. This greatly simplifies error handling.
int a = 0, b = 0;
char buf[100];
for (;;) {
printf("Enter two integers :");
if (fgets(buf, sizeof buf, stdin) == NULL) {
printf("Input closed\n");
break;
}
Then test the string for 2 ints with no following junk. Use sscanf() (simple) , strtol() (more robust), etc.
int n; // %n records where scanning stopped
if (sscanf(buf, "%d%d %n", &a, &b, &n) == 2 && buf[n] == '\0') {
printf("Number 1 is : %d \n Number 2 is : %d", a, b);
break;
}
printf("<%s> is not 2 integers. Try again\n", buf);
}
More advanced code uses strtol() to validate and also detect excessively long lines of input.

Resources