What is wrong with the scanf() to get in the string on the second time, I can't input my string on the second time.
I am not sure with the error that occurs, I can't get this program function well
#include <stdio.h>
#include <stdlib.h>
int main()
{
//variables decleration
char staff_name1[31];
char staff_name2[31];
float sales1, sales2;
//input
printf("Enter staff name\t> ");
scanf("%[^\n]s", staff_name1);
printf("Enter sales amount\t> ");
scanf("%f", &sales1);
printf("\nEnter staff name \t> ");//ERROR,CAN'T INPUT MY STRING
fflush(stdin);
scanf("%[^\n]s", staff_name2);
printf("\nEnter sales amount\t> ");
scanf("%f", &sales2);
printf("\n");
//output
printf("Staff Name\t\t\t\tSales Amount\n");
printf("===================\t\t=============\n");
printf("%-20s \t%12.2f\n", staff_name1, sales1);
printf("%-20s \t%12.2f\n", staff_name2, sales2);
}
my output of this code is as below:
warning: this program uses gets(), which is unsafe.
Enter staff name > kh s
Enter sales amount > 134.14
Enter staff name >
Enter sales amount > 141243.14
Staff Name Sales Amount
=================== =============
kh s 134.14
141243.14
I can't input the second staff name. Can anyone please help me solve this??
fflush(stdin);
is undefined behaviour in standard C. To flush the newline character, you could simply use getchar() instead.
printf("\nEnter staff name \t> ");
getchar();
scanf("%[^\n]s", staff_name2);
I would also use fgets() instead of scanf to read a line and trim the newline if necessary, which offers better control over invalid inputs being entered by user and against buffer overflows.
You have three problems.
I see that you use %[^\n]s. It is wrong. The s isn't part of the %[ specifier. So use %[^\n] instead of %[^\n]s
After you enter the value for sales1, you press Enter. This character stays in the stdin(standard input stream). And when the next character for %[^\n] is \n, it will fail. Fix this problem by adding a space before %[^\n].
Using fflush on stdin invokes Undefined Behavior as per the C11 standard, although the behavior is well defined in some implementations. It is better to remove it so that your code will be more portable.
Additional notes:
You can limit the amount of characters to be scanned so that you can avoid buffer overflows.
You can check the return value of scanf to make sure it is successful. All the scanf in your program will return 1 on success.
Fixed Program:
#include <stdio.h>
#include <stdlib.h> //Unused header
int main()
{
char staff_name1[31];
char staff_name2[31];
float sales1, sales2;
printf("Enter staff name\t> ");
if(scanf(" %30[^\n]", staff_name1) != 1)
{
printf("Could not scan staff_name1");
return -1; //Exit main with a return value of -1
}
printf("Enter sales amount\t> ");
if(scanf("%f", &sales1) != 1)
{
printf("Could not scan sales1");
return -1; //Exit main with a return value of -1
}
printf("\nEnter staff name \t> ");
//fflush(stdin); UB!
if(scanf(" %30[^\n]", staff_name2) != 1)
{
printf("Could not scan staff_name2");
return -1; //Exit main with a return value of -1
}
printf("\nEnter sales amount\t> ");
if(scanf("%f", &sales2) != 1)
{
printf("Could not scan sales2");
return -1; //Exit main with a return value of -1
}
printf("\n");
//output
printf("Staff Name\t\t\t\tSales Amount\n");
printf("===================\t\t=============\n");
printf("%-20s \t%12.2f\n", staff_name1, sales1);
printf("%-20s \t%12.2f\n", staff_name2, sales2);
}
Related
i am pretty new to c, i m trying to make the user input a number, but if they input a letter or word it shows a warning and asks for input again, my code works fine if the user puts in a number but it goes into an infinite loop if the user inputs something invalid, here is my code
#include <stdio.h>
int main(void) {
float salary;
int status = 0;
while (status == 0)
{
printf(" Please input your yearly salary to calculate taxes: \n");
status = scanf(" %f", &salary);
if (status == 0)
printf("invalid input!\n");
}
printf("%.2f\n", salary);
return 0;
}
i thought that i was something to do with the buffer left over from the first scanf , but adding a space " %f" didnt work, i tried using fflush(stdin) after then scanf also didnt work. i m not sure what else i can try.
thanks in advance for any help.
You need to clear the buffer or it will keep evaluating it and cause the endless loop. Add one line after your invalid input: scanf("%*[^\n]")
#include <stdio.h>
int main(void) {
float salary;
int status = 0;
while (status == 0)
{
printf(" Please input your yearly salary to calculate taxes: \n");
status = scanf(" %f", &salary);
if (status == 0)
printf("invalid input!\n");
scanf("%*[^\n]");
}
printf("%.2f\n", salary);
return 0;
}
This will work. You can see a better explanation here: Scanf and loops
The problem is that scanf won't advance the file stream. You ask it to read a floating point value and it isn't able to, so it doesn't consume the input.
For example, let's say your input is "foo", which isn't a number. Your scanf call isn't able to successfully read anything and returns 0. Then, in the next iteration, "foo" is still waiting to be read from stdin.
Try changing your if condition to something like
if (status == 0) {
char foo[256];
fgets(foo, sizeof(foo), stdin);
printf("Invalid input! Expected a nmuber, got: %s", foo);
}
Notice how the entire input is read from stdin by the gets call.
I'm trying to write a simple binary calculator to get reaquainted with C. for some reason the first input verification works fine, and even though the second verification for the numbers is written in almost the same way, if the user enters faulty input, the while loop just loops infinitely without ever waiting for new user input. Here is the code, and thanks for the help.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char operator[20];
char valid_operator[4] = "+-*/";
printf("Enter operator: ");
scanf("%s", operator);
printf("You entered: %s\n", operator);
while(strchr(valid_operator, (int)operator[0]) == NULL) {
printf("%s is not a valid operator. Enter +, -, /, or *: ", operator);
scanf("%s", operator);
}
The code works up until here. This next part is thrown into an infinite loop if the user enters faulty input the first time. The re-prompting never happens.
int input1;
int input2;
printf("Enter the two inputs (separated by whitespace): ");
int num_ints = 1;
num_ints = scanf("%d %d", &input1, &input2);
printf("Input 1: %d. Input 2: %d.\n", input1, input2);
while(num_ints < 2){
printf("Invalid input. Enter two integers separated by whitespace: ");
num_ints = 0;
num_ints = scanf("%d %d", &input1, &input2);
printf("Input 1: %d. Input 2: %d.\n", input1, input2);
}
return 0;
The reason it loops infinitely without ever waiting for new user input is that when scanf fails to read a char in the requested format (%d in your case) it won't advance the file pointer and at the next iteration of the loop it will try to read the same incorrect char again.
This is consistent with POSIX: http://pubs.opengroup.org/onlinepubs/009695399/functions/fscanf.html
if the comparison shows that they are not equivalent, the directive shall fail, and the differing and subsequent bytes shall remain unread.
Also, return value from the man scanf:
...return the number of input items successfully matched and assigned, which can be fewer than provided for, or even zero in the event of an early matching failure.
So, you better combine fgets and sscanf.
do {
char buf[BUFSZ];
printf("Enter the two inputs (separated by whitespace): ");
if(fgets(buf, BUFSZ, stdin) == NULL)
{
/* Error exit. */
break;
}
num_ints = sscanf(buf, "%d %d", &input1, &input2);
} while(num_ints != 2);
You need to clear stdin. If you input a non-integer in your example "1 t", "t" is not consumed (left in the stream). Add this to your loop:
while(num_ints < 2){
while (fgetc(stdin) != '\n'); // clear input
. . .
See C program loops infinitely after scanf gets unexpected data for a good description of the issue.
I can't seem to figure out what's wrong with this code:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#define MAX 100
#define TRUE 1
#define FALSE 0
char sect_cat;
char customer_name[MAX];
char customer_number[MAX]; /* error handling is easier */
int prev_unit = 0;
int current_unit = 0;
int consumed = 0;
int set = FALSE;
float init_bill;
float tax;
float total_bill;
void get_userinfo()
{
printf("Enter sector category: ");
scanf("%c", §_cat);
printf("Enter customer name: ");
fflush(stdin);
scanf("%sn", &customer_name);
set = FALSE;
while (set == FALSE)
{
printf("Enter customer number: ");
fflush(stdin);
scanf("%s", customer_number);
int i;
int error;
for (i=0, error=0; i<strlen(customer_number); i++)
{
if (isdigit(customer_number[i]))
{
}
else
{
error = 1;
}
}
if (error == 0)
{
set = TRUE;
}
else
printf("ERROR: Only numbers are allowed\n");
}
printf("Enter previous unit: ");
fflush(stdin);
scanf("%d", &prev_unit);
set = FALSE;
while (set == FALSE)
{
printf("Enter current unit: ");
fflush(stdin);
scanf("%d", ¤t_unit);
if (prev_unit > current_unit)
{
printf("ERROR: Current unit must be larger than previous unit\n");
}
else
set = TRUE;
}
consumed = current_unit - prev_unit;
}
int main()
{
/* Introduce program to users */
printf("\nThis program computes your electric bill based on these sector categories\n\n");
printf("\tResidential(R)\n");
printf("\tIndustrial(I)\n");
printf("\tCommercial(C)\n\n");
printf("Press any key to continue...");
fflush(stdin);
getchar();
#################### edit
Applying templatetypedef's solution, the program now waits for user input for the customer_name. However entering a string with a space leads to an error, and the program assumes that the word after the space is input for the next prompt.
Enter sector category: r
Enter customer name: George of the Jungle
Enter customer number: ERROR: Only numbers are allowed
Enter customer number: ERROR: Only numbers are allowed
Enter customer number:
The fflush function does not flush data out of an input stream; it is instead used to push data buffered in an output stream to the destination. This is documented here. As seen in this earlier SO question, trying to use fflush(stdin) leads to undefined behavior, so it's best to avoid it.
If you want to eat the newline from the return character entered when the user finished typing in their character, instead consider the following:
scanf("%c%*c", §_cat);
This will eat the newline rather than leaving it in stdin.
Hope this helps!
I think that you meant to write fflush(stdout) instead of fflush(stdin).
fflush should work with an output stream, see docs here
I'm trying to use two scanf's to read a string and then an integer. The program waits for me to enter the string, i press enter and then doesn't wait for me to insert the integer. The code i'm using:
printf("Insert the name of the author to search: ");
scanf("%300s", author);
printf("Insert the year: ");
scanf("%d", &year);
Any suggestions?
The conversion specifier "%s" breaks on whitespace.
If you enter, for instance, "John Smith", the variable author will have "John" and the rest of the input will be used for year.
Always validate the return value of (most) library functions.
printf("Insert the name of the author to search: ");
if (scanf("%300s", author) != 1) /* error */;
printf("Insert the year: ");
if (scanf("%d", &year) != 1) /* error */;
The best way to get user input is to use fgets(), then, if needed, parse the input and assign to variables.
char tmp[1000];
printf("Insert the name of the author to search: ");
if (!fgets(tmp, sizeof tmp, stdin)) /* error */;
strcpy(author, tmp);
printf("Insert the year: ");
if (!fgets(tmp, sizeof tmp, stdin)) /* error */;
if (sscanf(tmp, "%d", &year) != 1) /* error */;
you are trying to read input into author array where input length can be upto 300 characters,So i hope that you have declared your array size aschar author[301] , 300+1 (one extra for accomadating '\0').
You can use function like this scanf(" %300[^\n],author") this means keep reading characters from keyboard(or you can say keyboard buffer) until '\n' is found, and '\n' is generated when you hit Enter key,Hence we are forcing scanf() to read characters until we hit enter.
We can use fgets() but one of the problem of it is that it will even read '\n' into array,which will always print the output of next printf() operation on one extra new line.This can cause problem when you want your output to be in tabular form.
int main()
{
char author[301]="\0";//initialize char array to '\0' NULL's
int year;
printf("Insert the name of the author to search: ");
if( scanf(" %300[^\n]", author)!=1 )
{
printf("End of Input or Error Occurred reading Name.\n");
return 1;// return (NON-ZERO) means unsuccessful termination
}
printf("Insert the year: ");
if( scanf("%d", &year)!=1 )
{
printf("End of Input or Error Occurred reading Year.\n");
return 1;// return (NON-ZERO) means unsuccessful termination
}
return 0;
}
I can't seem to figure out what's wrong with this code:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#define MAX 100
#define TRUE 1
#define FALSE 0
char sect_cat;
char customer_name[MAX];
char customer_number[MAX]; /* error handling is easier */
int prev_unit = 0;
int current_unit = 0;
int consumed = 0;
int set = FALSE;
float init_bill;
float tax;
float total_bill;
void get_userinfo()
{
printf("Enter sector category: ");
scanf("%c", §_cat);
printf("Enter customer name: ");
fflush(stdin);
scanf("%sn", &customer_name);
set = FALSE;
while (set == FALSE)
{
printf("Enter customer number: ");
fflush(stdin);
scanf("%s", customer_number);
int i;
int error;
for (i=0, error=0; i<strlen(customer_number); i++)
{
if (isdigit(customer_number[i]))
{
}
else
{
error = 1;
}
}
if (error == 0)
{
set = TRUE;
}
else
printf("ERROR: Only numbers are allowed\n");
}
printf("Enter previous unit: ");
fflush(stdin);
scanf("%d", &prev_unit);
set = FALSE;
while (set == FALSE)
{
printf("Enter current unit: ");
fflush(stdin);
scanf("%d", ¤t_unit);
if (prev_unit > current_unit)
{
printf("ERROR: Current unit must be larger than previous unit\n");
}
else
set = TRUE;
}
consumed = current_unit - prev_unit;
}
int main()
{
/* Introduce program to users */
printf("\nThis program computes your electric bill based on these sector categories\n\n");
printf("\tResidential(R)\n");
printf("\tIndustrial(I)\n");
printf("\tCommercial(C)\n\n");
printf("Press any key to continue...");
fflush(stdin);
getchar();
#################### edit
Applying templatetypedef's solution, the program now waits for user input for the customer_name. However entering a string with a space leads to an error, and the program assumes that the word after the space is input for the next prompt.
Enter sector category: r
Enter customer name: George of the Jungle
Enter customer number: ERROR: Only numbers are allowed
Enter customer number: ERROR: Only numbers are allowed
Enter customer number:
The fflush function does not flush data out of an input stream; it is instead used to push data buffered in an output stream to the destination. This is documented here. As seen in this earlier SO question, trying to use fflush(stdin) leads to undefined behavior, so it's best to avoid it.
If you want to eat the newline from the return character entered when the user finished typing in their character, instead consider the following:
scanf("%c%*c", §_cat);
This will eat the newline rather than leaving it in stdin.
Hope this helps!
I think that you meant to write fflush(stdout) instead of fflush(stdin).
fflush should work with an output stream, see docs here