i want to make 2 lines calculator program but after first printf,scanf it skipped the second statement
#include <stdio.h>
int main ()
{
int a,b,c,d,abcd;
int e,f,g,h,efgh;
printf("1. ");
scanf("(%d+%d)x(%d-%d)",&a,&b,&c,&d);
printf("2. ");
scanf("(%d+%d)x(%d-%d)",&e,&f,&g,&h);
abcd=(a+b)*(c-d);
efgh=(e+f)*(g-h);
printf("%d %d %d",abcd,efgh);
return 0;
}
and i want to make the program like this:
input
1. (1+2)x(3-4)
2. (5+6)x(7-8)
output
-3 -11
I would strongly suggest you read a line of input using fgets, then use sscanf to parse out the info you need. You will also want to check the return value of sscanf to ensure all four values were read. In this case I have made successful input required to break out of an infinite loop (for (;;) { ... }).
Please note also that all variables do not need to de declared at the start of a function. Instead they can be declared and initialized at their point of use. In this scenario, I have declared abcd and efgh later in main.
#include <stdio.h>
#define LINE_LEN 256
int main ()
{
int a, b, c, d;
int e, f, g, h;
char line[LINE_LEN] = {0};
for (;;) {
printf("1. ");
fgets(line, LINE_LEN, stdin);
if (sscanf(line, "(%d+%d)x(%d-%d)", &a, &b, &c, &d) == 4)
break;
fprintf(stderr, "Bad input. Try again.");
}
for (;;) {
printf("1. ");
fgets(line, LINE_LEN, stdin);
if (sscanf(line, "(%d+%d)x(%d-%d)", &e, &f, &g, &h) == 4)
break;
fprintf(stderr, "Bad input. Try again.");
}
int abcd = (a + b) * (c - d);
int efgh = (e + f) * (g - h);
printf("%d\n", abcd);
printf("%d\n", efgh);
return 0;
}
By some suggestions here I copied the function to read from the stdin in C and adapted your example. This is a safe way to handle stdin from a C application.
Also I tried your code and I believe that what was wrong is that some newline gets "trapped" in the stdin, hence the second scanf returns before you can write anything. That's why this solution.
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
int main ()
{
int a,b,c,d,abcd;
int e,f,g,h,efgh;
int rc;
char buff[20];
rc = getLine ("1. ", buff, sizeof(buff));
if (rc == NO_INPUT) {
// Extra NL since my system doesn't output that on EOF.
printf ("\nNo input\n");
return 1;
}
if (rc == TOO_LONG) {
printf ("Input too long [%s]\n", buff);
return 1;
}
sscanf(buff, "(%d+%d)x(%d-%d)",&a,&b,&c,&d);
rc = getLine ("2. ", buff, sizeof(buff));
if (rc == NO_INPUT) {
// Extra NL since my system doesn't output that on EOF.
printf ("\nNo input\n");
return 1;
}
if (rc == TOO_LONG) {
printf ("Input too long [%s]\n", buff);
return 1;
}
sscanf(buff, "(%d+%d)x(%d-%d)",&e,&f,&g,&h);
printf("Check \n");
printf("%d %d %d %d\n" ,a,b,c,d);
printf("%d %d %d %d\n" ,e,f,g,h);
abcd=(a+b)*(c-d);
efgh=(e+f)*(g-h);
printf("Results: %d %d \n",abcd,efgh);
return 0;
}
scanf is wrong..
scanf("%typeOfFirstVariable %typeOfSecondVariable...", &firstVariable, &secondVariable...);
int a,b,c,d,abcd;
int e,f,g,h,efgh;
printf("1. ");
scanf("%d %d %d %d)",&a,&b,&c,&d);
...
return 0;
Related
I need to input 1 to 3 numbers with values between 3 to 69 only. So when I input something different from a number the program should fprintf on stderr "The input isn't number". But I cannot find a way how to code that. And I should use if function.
#include <stdio.h>
int main()
{
int i=0;
while (scanf("%d", &i) == 1)
{
if (i<3 || i>69)
{
fprintf(stderr,"Error: Input is too big or too small!");
return 101;
}
if (ISNT A NUMBER)
{
fprintf(stderr,"Error: Input isnt a number!");
return 100;
}
}
return 0;
}
There are many ways to do this correctly:
Using scanf:
#include <stdio.h>
#include <stdlib.h>
int get_num() {
int i;
printf("Enter a number between 3 and 69: ");
fflush(stdout);
if (scanf("%d", &i) != 1) {
fprintf(stderr, "incorrect number of arguments, we need exactly one number (between 3 and 69)\n");
return -1;
}
if( i < 3 || i > 69 ) {
fprintf(stderr, "oops the number must be between [3, 69]\n");
return -2;
}
return i;
}
void eat_trash() {
int c;
while((c = getchar())!= '\n' && c !=EOF);
}
int main() {
int value;
while ((value = get_num()) <= 0 ) {
eat_trash();
}
printf("Got: %d\n", value);
}
A little extra but has interesting but (maybe slightly silly) things:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int stdin_copy;
int get_num() {
int i, rv = 0;
static int err_count = 0;
char *input = NULL;
size_t len = 0;
printf("Enter a number between 3 and 69: ");
fflush(stdout);
// gets a line (allocates memory we have to free)
rv = getline(&input, &len, stdin);
if ( rv > 3 ) {
err_count++; // see if we have a lot of garbage incoming
free(input);
if (err_count < 3 ) {
fprintf(stderr, "a number between 3 and 9 only needs two characters, try again. (%d tries left)\n", 3 - err_count);
return -3;
}
// just stop dealing with this silly user.
fprintf(stderr, "really? okay bye!\n");
exit(127);
}
rv = sscanf(input, "%d", &i);
free(input);
if (rv != 1) {
fprintf(stderr, "incorrect number of arguments, we need exactly one number (between 3 and 69)\n");
return -1;
}
if( i < 3 || i > 69 ) {
fprintf(stderr, "oops the number must be between [3, 69]\n");
return -2;
}
return i;
}
void eat_trash() {
fclose(stdin);
stdin = fdopen(stdin_copy, "r");
stdin_copy = dup(fileno(stdin));
}
int main() {
int value;
stdin_copy = dup(0);
while ((value = get_num()) <= 0 ) {
eat_trash();
}
printf("Got: %d\n", value);
}
The thing to note is the way trash is being consumed. The trouble with this is what happens if user pushes an input without \n and then we are stuck in the way getline functions (also it can use up memory and that needing to free the input is annoying). So,
is there a way how to check if input I have scanfed is a number? With IF function in C
The best is to read the user input line with fgets(), (or getline() if you have it) and then parse for an integer with strtol().
The troubles with scanf("%d", ... include
Leaving non-numeric input in stdin.
Not reading the entire line.
Reading multiple lines when first ones are all white-space.
Not detecting trailing nun-numeric input.
Undefined behavior on int overflow.
Instead read a line and form a string. Then parse the string:
char *endptr;
long num = strtol(input_line_as_a_string, &endptr, 10);
if (input_line_as_a_string == endptr) {
printf("No conversion happened. Input is non-numeric\n");
} else if (num < 3 || num > 69) {
printf("Input %ld is out of range\n", num);
} else {
while (isspace(*endptr)) endptr; // skip trailing white-space
if (*endptr != '\0') {
printf("Input has trailing input\n");
} else {
printf("Success %ld\n", num);
}
}
#include <stdio.h>
int main()
{
FILE *f1;
int ch, i, n = 0;
char q[500], opt[4][100];
int corAns;
f1 = fopen("C://Users//Lenovo//Desktop//fileInC1.txt", "a+");
if (f1 == NULL)
{
printf("Error Opening File.");
return 0;
}
else
{
while (n != 2)
{
n++;
printf("\nQuestion: ");
fgets(q, 500, stdin);
for (i = 0; i < 4; i++)
{
printf("\nOption %d: ", i + 1);
fgets(opt[i], 100, stdin);
}
printf("\nCorrect answer: ");
scanf("%d", corAns);
//program terminating here after only one iteration
fprintf(f1, "{\nQ: \"%s\", \n\topt: [\"%s\", \"%s\", \"%s\", \"%s\"], \n\tCA: %d }", q, opt[0], opt[1], opt[2], opt[3], corAns);
printf("\nData Written Successfully.");
}
}
fclose(f1);
return 0;
}
I have been trying to create a Javascript generator as you can see in the code.
The main problem i am getting is inside the while loop.
The while loop is terminating after only one iteration and the program not writting the data in the created file. The file already exists.
I am not getting where is the problem occuring.
You need to cleanse your input of new-lines. You also had a redundant Else statement, and Scanf requires the address of a variable, not it's value.
This should work for you. You can check out this question here: Fgets skipping inputs, which I shamelessly copied.
#include <stdio.h>
#include <string.h>
int main()
{
FILE *f1;
int ch, i, n = 0;
char q[500], opt[4][100];
int corAns;
int c;
char *p;
f1 = fopen("fileInC1.txt", "a+");
if (f1 == NULL)
{
printf("Error Opening File.");
return 0;
}
while (n != 2)
{
n++;
printf("\nQuestion: ");
fgets(q, 500, stdin);
if ((p=strchr(q, '\n')) != NULL) *p = '\0';
for (i = 0; i < 4; i++)
{
printf("\nOption %d: ", i + 1);
fgets(opt[i], 100, stdin);
if ((p=strchr(opt[i], '\n')) != NULL) *p = '\0';
}
printf("\nCorrect answer: ");
scanf("%d", &corAns);
//program terminating here after only one iteration
fprintf(f1, "{\nQ: \"%s\", \n\topt: [\"%s\", \"%s\", \"%s\", \"%s\"], \n\tCA: %d }", q, opt[0], opt[1], opt[2], opt[3], corAns);
printf("\nData Written Successfully.");
while ( (c = getchar()) != '\n' && c != EOF );
}
fclose(f1);
return 0;
}
I need to check whether the input is number. My code looks something like this:
int input;
while ( scanf(" %s %d", string, &input) != EOF) {
if ( isNotANumber(input) ) {
printf("Not a number"); }
doSomethingElse(input, string);
}
EDIT: I need to be accepting input and calling the function doSomethingElse(input) until the user enters EOF.
isNotANumber is a mock function, I don't have that function, I'm asking how could I write it.
EDIT 2: Variable string needs to be a string, variable input needs to be an integer.
EDIT 3: I tried separating my code into this:
while (scanf(" %s", string) != EOF) {
if (scanf("%d",&input) != 1) {
printf("not a number");
}
doSomething();
}
But it stil doesn't work for input like "4a".
For example, you can change it as follows.
#include <stdio.h>
#define doSomethingElse(input) do{ printf("your input is %d\n", input); }while(0)
int main(void){
int input;
int status;
while ((status = scanf("%d", &input)) != EOF) {
if ( status == 0 ) {
printf("Not a number\n");
while(getchar() != '\n'); //clear input
}
else {
doSomethingElse(input);
}
}
}
However, this can not check input like 123.456. (accept 123)
So, It is recommended to input with fgets and check with strtol.
As already pointed out, like scanf(" %s %d", string, &input) can not check the input after the number.
So, For convenience, check backward input.
char string[32], ch;
int input;
int status;
while ((status = scanf("%31s %d%c", string, &input, &ch )) != EOF) {
if ( status == 3 && ch == '\n') {
doSomethingElse(input);
}
else {
printf("Not a number\n");
while(getchar() != '\n'); //clear input
}
}
Example using fgets and strtol
(mystrtoi has reorganized the answer of chux. thanks)
#include <stdio.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#define doSomethingElse(input) do{ printf("your input is %d\n", input); }while(0)
int mystrtoi(const char *str, int *err) {
char *endptr;
*err = errno = 0;
long l = strtol(str, &endptr, 0);
if (errno == ERANGE || *endptr != '\0' || str == endptr) {
*err = 1;
}
// Only needed if sizeof(int) < sizeof(long)
if (l < INT_MIN || l > INT_MAX) {
*err = 1;
}
return (int) l;
}
int main(void){
char line[128];
char string1[32], string2[128];
int num, err;
while (fgets(line, sizeof line, stdin)){
// if(2 != sscanf(line, "%31s %31s", string1, string2)){// or use strtok to split
if(2 != sscanf(line, "%31s %127[^\n]", string1, string2)){
printf("invalid input\n");
continue;
}
num = mystrtoi(string2, &err);
if(err) {
printf("Not a number\n");
}
else {
doSomethingElse(num);
}
}
}
while ( scanf("%d", input) != EOF)
Your scanf code has two problems:
scanf returns the number of successfully read item, not EOF. Here you want to check if scanf has successfully read one integer input
scanf expects the address of the variable
You should re-write that line as:
while ( scanf("%d", &input) == 1 )
//why the code starts printing retry infinitely if i wrongly
enter a string in place of int i in terminal
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char const *argv[])
{
int i,j=0;
while(1)
{
scanf("%d",&i);
if(i==10)
{
printf("you got the max! YOU WON\n");
break;
}
else
{
printf("%s\n","retry" );
}
}
return 0;
}
Try consuming (flushing) on bad input:
else {
while ((j = fgetc(stdin)) != '\n' && j != EOF);
printf("%s\n", "retry");
}
An alternative using fgets (is preferable because it consumes the whole line) and strtol:
#include <stdio.h> /* fgets, printf */
#include <stdlib.h> /* strtol */
#include <string.h> /* strchr */
int main(void) /* No args */
{
char buf[128], *p;
int i;
while (fgets(buf, sizeof(buf), stdin)) {
if ((p = strchr(buf, '\n')) != NULL) {
*p = '\0'; /* remove newline */
}
i = (int)strtol(buf, &p, 10); /* Base 10 */
if (*p != '\0' || i != 10) {
printf("retry\n");
} else {
printf("you got the max! YOU WON\n");
break;
}
}
return 0;
}
Read fails because of you inputted wrong type and i will have garbage value.
Add initialization to i:
int i=0, j=0;
scanf returns number of succesful reads. Add return value check to scanf:
int r = scanf("%d",&i); // Will return 1 if 1 argument was successully read
if(r == 1 && i == 10)
{
//do something
}
Edit:
As others have pointed out, it seems that scanf doesn't consume incoming bytes if input is wrong. Thus you might want to replace it wit fgets and sscanf:
int r;
char temp[32];
fgets(temp, 32, stdin); // Read input to temporary buffer
r = sscanf(temp, "%d", &i); // Try to convert value on buffer
if(r == 1 && i == 10)
{
//do something
}
I'm using this piece of code to read users input and check if it is a number or not.But sincerly it just works for numbers and letters. I want it to work with every char. For example "!?%". I have already tried to change the "isalnum" by "isascii" but that does not work.
#include <stdio.h>
#include <ctype.h>
int main ()
{
int a;
int b = 1;
char c ;
do
{
printf("Please type in a number: ");
if (scanf("%d", &a) == 0)
{
printf("Your input is not correct\n");
do
{
c = getchar();
}
while (isalnum(c));
ungetc(c, stdin);
}
else
{
printf("Thank you! ");
b--;
}
}
while(b != 0);
getchar();
getchar();
return 0;
}
Unless you have specific requirements, you should use fgets and sscanf
while (1) {
char buf[1000];
printf("Please input a number: ");
fflush(stdout);
if (!fgets(buf, sizeof buf, stdin)) assert(0 && "error in fgets. shouldn't have hapenned ..."):
/* if enter pending, remove all pending input characters */
if (buf[strlen(buf) - 1] != '\n') {
char tmpbuf[1000];
do {
if (!fgets(tmpbuf, sizeof tmpbuf, stdin)) assert(0 && "error in fgets. shouldn't have hapenned ...");
} while (buf[strlen(tmpbuf) - 1] != '\n');
}
if (sscanf(buf, "%d", &a) == 1) break; /* for sufficiently limited definition of "numbers" */
printf("That was not a number. Try again\n");
}
A correct way in strictly C89 with clearing input buffer, checking overflow looks like:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int readLong(long *l)
{
char *e,in[20];
fgets( in,20,stdin );
if(!strchr(in,'\n')) while( getchar()!='\n' );
else *strchr(in,'\n')=0;
errno=0;
*l=strtol(in,&e,10);
return *in&&!*e&&!errno;
}
int main()
{
long l;
if( readLong(&l) )
printf("long-input was OK, long = %ld",l);
else
puts("error on long-input");
return 0;
}