Loop Gone wrong [duplicate] - c

This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 2 years ago.
I'm pretty new in C.
My problem is the code keep looping at that line ( you can check the code) while what i wanted is for it to loop the whole for statement, not a single line.
English is not my first language so i'm truly sorry
#include <stdio.h>
int hw;
int uts;
int uas;
float hasil_uts;
float hasil_uas;
float hasil_hw;
char opsi;
int main (void) {
int n1; //Homework
int c1;
for (c1=0;opsi != 'n';c1++) {
printf ("Input : ");
scanf ("%d",&hw);
n1 += 1;
hasil_hw += hw;
printf ("\nInput another marks? (y/n)"); // it loops here when it run
scanf ("%c",&opsi);
}
return 0;
}

you have to add one space in scanf like this scanf (" %c",&opsi); ,otherwise you will take \n as your character in scanf.
also note that you are using uninitialized variable n1 and hasil_hw. you have to add n1=0 and hasil_hw=0 to your code.
also as mentioned in comments you should check scanf returned value.
look
int hw;
int uts;
int uas;
float hasil_uts;
float hasil_uas;
float hasil_hw=0;
char opsi;
int main(void) {
int n1=0; //Homework
int c1;
for (c1 = 0; opsi != 'n'; c1++) {
printf("Input : ");
if ( scanf("%d", &hw) != 1)
{
fputs ("error: invalid value.\n", stderr);
return 1;
}
n1 += 1;
hasil_hw += hw;
printf("\nInput another marks? (y/n)"); // it loops here when it run
if (scanf(" %c", &opsi) != 1)//add space before %c
{
fputs ("error: invalid value.\n", stderr);
return 1;
}
}
return 0;
}

Related

How to make code say 'invalid input' when a user enters a character or a string (Validate)

I'm new to c and i just wanted to know how to make my code say ' invalid input' if they decide to enter a character or gibberish.
My code is just a simple Celsius to Kelvin (i know very simple) and i just adds 273 to any inputted number. i tried to use isdidgit but it was unsuccessful.
My code;
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int temp = 273;
int cel;
int cel2;
int choice;
switch (choice)
{
case 1:
printf("enter ce to conv to kel: ");
scanf("%ld", &cel);
cel2 = cel + temp;
printf("%d in Celsuis is: %d Kelvin \n", cel, cel2)
I accept all feedback / improvements,
thanks
~Neamus
Presently, your code has no way to recover from an invalid input. That is, if a user enters "a" when prompted, scanf() will never return because it will be waiting for a base-10 integer value.
What you will need to do is read the input as a C-string and process that:
char input[80];
do {
printf("enter ce to conv to kel: ");
scanf("%79[^\n]\n", input); // read until newline; toss newline
} while (input_is_bad(input)); // your function to validate input
cel = atoi(input); // atoi parses C-string, returning an int
cel2 = cel + temp;
printf("%d in Celsuis is: %d Kelvin \n", cel, cel2);
Inside your own input_is_bad() function, you can print a message stating that the input is not valid.
You can achieve this by using fgets and strtol. See the following code:
#include<stdio.h>
#include <stdlib.h>
int main()
{
int temp = 273;
int cel;
int cel2;
int choice;
int flag;
char *p, str[100];
printf("enter ce to conv to kel: ");
while (fgets(str, sizeof(str), stdin)) {
cel = strtol(str, &p, 10); //number of base 10
if (p == str || *p != '\n') {
printf("Please enter an integer: ");
}
else break; //if input is integer then break the loop
}
//do your calculations here
return 0;
}

Calculate GPA of a student without arrays [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
whats wrong in my code? it doesn't give the values properly and when i insert q it doesn't execute properly....
#include<stdio.h>
void main()
{
double a=0, x, ctot;
double y, stot;
char b, c='q';
double score=x*y;
while(a<200){
printf("Enter no of Credits of the subject = ");
scanf("%lf\n",&x);
printf("Enter the score for the subject = ");
scanf("%lf\n",&y);
scanf("%c\n",&b);
if(b=='q'){
break;
}else{
ctot+=x;
stot+=score;
a++;
}
}
printf("GPA of the student = %f\n", stot/ctot);
}
An attempt to access a variable with indeterminate value (meaning uninitialized) invokes Undefined Behavior and the valid operation of your code ceases at that point. It can appear to work properly or SegFault or anything in between.
To avoid uninitialized values, always initialize them -- especially when you are just beginning to program. (it will save you from yourself...), e.g.
int a = 0; /* always initialize all variables - good practice */
double ctot = 0.0,
stot = 0.0,
score = 0.0,
x = 0.0,
y = 0.0;
char c = 0;
The proper declarations for main are int main (void) and int main (int argc, char **argv) (which you will see written with the equivalent char *argv[]). note: main is a function of type int and it returns a value. See: C11 Standard ยง5.1.2.2.1 Program startup p1 (draft n1570). See also: See What should main() return in C and C++?
While there are some ancient compilers, and some micro-controllers that allow void main(), it is a non-standard invocation, and any worthwhile compiler will warn. (you are compiling with compiler-warning enabled right?, e.g. -Wall -Wextra for gcc/clang or /W3 for VS (cl.exe))
You must check the return of scanf every time and validate the return is equal to the number of conversions you have requested -- otherwise a matching or input failure has occurred (or the user canceled by generating a manual EOF). This is the only way you can insure you are processing valid data and not further invoking Undefined Behavior (or throwing yourself into an endless input loop). You must always empty stdin after each input. Your '\n' gimick in the format string will not work. A simple way to empty stdin is to define a helper-function to call after each input to remove any extraneous or additional characters that remain unread, e.g.
/* simple function to empty remaining chars in stdin */
void empty_stdin (void) /* if no parameter - spcecify 'void' explicitly */
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
...
printf ("Enter no of Credits of the subject = ");
if (scanf ("%lf", &x) != 1) { /* validate EVERY input */
fprintf (stderr, "error: invalid input for 'x'.\n");
return 1;
}
empty_stdin(); /* empty stdin, your \n gimick doesn't work */
Putting it altogether, you could do something similar to the following:
#include <stdio.h>
/* simple function to empty remaining chars in stdin */
void empty_stdin (void) /* if no parameter - spcecify 'void' explicitly */
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
int main (void) {
int a = 0; /* always initialize all variables - good practice */
double ctot = 0.0,
stot = 0.0,
score = 0.0,
x = 0.0,
y = 0.0;
char c = 0;
for (; a < 200; a++) { /* loop however you like */
printf ("Enter no of Credits of the subject = ");
if (scanf ("%lf", &x) != 1) { /* validate EVERY input */
fprintf (stderr, "error: invalid input for 'x'.\n");
return 1;
}
empty_stdin(); /* empty stdin, your \n gimick doesn't work */
printf ("Enter the score for the subject = ");
if (scanf ("%lf", &y) != 1) {
fprintf (stderr, "error: invalid input for 'y'.\n");
return 1;
}
empty_stdin();
score = x * y; /* compute values each iteration */
ctot += x;
stot += score;
/* prompt for additional credits? */
printf ("add additional credits? (y/n): ");
if (scanf (" %c", &c) != 1) {
fprintf (stderr, "error: user canceled input.\n");
return 1;
}
empty_stdin();
if (c == 'n' || c == 'N') /* you can use 'q', but (y/n) is fine */
break;
}
printf ("\nGPA of the student = %f\n", stot/ctot);
return 0;
}
(can you figure out why if (scanf (" %c", &c) != 1) can only mean that the user canceled input?)
Example Use/Output
note: there are extraneous characters intentionally input below to provide example of how the simple additions to your code handle them safely. (try the input below with your original code and see what happens)
$ ./bin/credits_grades
Enter no of Credits of the subject = 3
Enter the score for the subject = 90
add additional credits? (y/n): y
Enter no of Credits of the subject = 4 (seemed like 40)
Enter the score for the subject = 80 (thank god!)
add additional credits? (y/n): y
Enter no of Credits of the subject = 3
Enter the score for the subject = 85
add additional credits? (y/n): n
GPA of the student = 84.500000
Look things over and let me know if you have further questions.
Initializing ctot and stot and re-positioning score=x*y your code will work . Try this edited code this works fine :-
#include <stdio.h>
void main()
{
double a = 0, x, ctot;
double y, stot;
char b, c = 'q';
double score;
ctot = 0; // initialize ctot and stot #ERROR1
stot = 0;
while (a < 200)
{
printf("\n Enter no of Credits of the subject = ");
scanf("%lf", &x);
printf("\n Enter the score for the subject = ");
scanf("%lf", &y);
getchar(); // to manage the addtional \n from scanf()
score = x * y; // computing score #ERROR2
scanf("%c", &b);
if (b == 'q')
{
break;
}
else
{
ctot += x;
stot += score;
a++;
}
}
printf("\n GPA of the student = %f", stot / ctot);
}
based on comments of #mch and #David C. Rankin
should modify the slot+=score to slot+=x*y
#include<stdio.h>
void main()
{
double a=0, x, ctot;
double y, stot;
char b, c='q';
double score=x*y;
while(a<200){
printf("Enter no of Credits of the subject = ");
scanf("%lf\n",&x);
printf("Enter the score for the subject = ");
scanf("%lf\n",&y);
scanf("%c\n",&b);
if(b=='q'){
break;
}else{
ctot+=x;
stot+=x*y;
a++;
}
}
printf("GPA of the student = %f\n", stot/ctot);
}

Scanf is being ignored [duplicate]

This question already has answers here:
Simple C scanf does not work? [duplicate]
(5 answers)
Closed 7 years ago.
#include <stdio.h>
#define length 20
main()
{
float x;
int y;
float array1[length], array2[length], array3[length];
float ray[length];
int size1 = insert(array1, length);
printf("enter number: ");
scanf("%d", &y);
int size2 = insert(array2, length);
int size3 = insert(array3, length);
}
int insert(float a[], int size)
{
int n = 0;
while(n<size && scanf("%f\n", &a[n]) == 1)
{
printf("you entered: ");
printf("%2.1f\n", a[n]);
n++;
}
return n;
}
When I run the program, it executes the first insert okay, but the next time function is called, scanf() seems to be ignored completely. I tried putting it right after where insert is done, but that's ignored as well.
Use %*c in scanf to consume the newlines along with space around %d in the scanf in main(). I tested the below code on MingW and it seem to work. The '\n' in your scanf is being consumed making it scanf() return while the '\n' at the press of enter key still remains in IO buffer to be consumed by scanf() again; hence the weird behaviour.
#include <stdio.h>
#include <stdlib.h>
#define length 20
int insert(float *a, int size)
{
int n = 0;
while(n<size && scanf("%f%*c", &a[n]))
{
printf("you entered: ");
printf("%2.1f\n", a[n]);
n++;
}
return n;
}
int main(int argc, char* argv[])
{
float x;
int y;
float array1[length], array2[length], array3[length];
float ray[length];
int size1 = insert(array1, length);
printf("enter number: ");
scanf("%d", &y);
int size2 = insert(array2, length);
int size3 = insert(array3, length);
return 0;
}
In the scanf format string, change "%f\n" to "%f". The \n in a scanf format string does not mean "wait for newline".
You do not need to worry about waiting for newline, because the only format specifiers you use are %f and %d, which both discard any leading whitespace.

Checking input type without quitting the program and restarting it

I have a requirement to get two integers and add and print the added value. I wrote a working program. Another requirement is to check whether the input value is other than integer and if it is other than integer, without closing the program, it should again ask for the inputs.
C Code
#include <stdio.h>
void main()
{
int a,b,c;
printf("This is a Addition program");
printf("\n Enter value of a:");
scanf("%d",&a);
printf("\n Enter value of b:");
scanf("%d",&b);
c=a+b;
printf("\n The added value is %d",c);
}
Here's some code that will completely fulfil your requirement. Yesterday David C Rankin posted an answer to the same basic question in Stack Overflow.
This code is basically what David provided:
#include <stdio.h>
static int getInt(const char *prompt)
{
int value;
char c;
while(printf("%s",prompt) && scanf("%d", &value) !=1)
{
do { c = getchar(); } while ( c != '\n' && c != EOF ); // flush input
printf ("Invalid Entry, Try Again...\n");
}
return value;
}
int sum(int a , int b) { return ( a + b ); }
int main(){
int a , b;
a = getInt("Please enter a number");
b = getInt("Please enter a number");
printf("Sum is :%d" , sum(a,b));
}
The function getInt check the input and yells for the wrong input.
This program will do what you want
#include<stdio.h>
int main() //use int not void
{
int a,b,c;
printf("This is a Addition program");
printf("\n Enter value of a:");
while(scanf("%d",&a)==0)
{
printf("\n Invalid input.Try again:");
getchar(); // clear the previous input
}
printf("\n Enter value of b:");
while(scanf("%d",&b)==0)
{
printf("\n Invalid input.Try again:");
getchar(); // clear the previous input
}
c=a+b;
printf("\n The added value is %d",c);
return 0; // because main returns int
}
scanf returns the number of successfully read items, so it will return 1 in your case if a valid value was entered. If not, an invalid integer value was entered and scanf will return 0.
Use fgets()/sscanf()/strto...() rather than scanf().
scanf() parses and performs input in the same function and does not well handle unexpected input. Use fgets() for user input and then scan/parse.
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
int getint(const char *prompt) {
char buf[sizeof(int) * CHAR_BIT];
while (1) {
fputs(prompt, stdout);
fflush(stdout);
if (fgets(buf, sizeof buf, stdin) == NULL) {
// sample handling of unexpected input issue.
// Value to return of EOF or IO error
return INT_MIN;
}
/// strtol() is another option
int i, n;
// " %n" notes offset of non-white-space after the numebr.
if (1 == sscanf(buf, "%d %n", &i, &n) && buf[n] == '\0') {
return i;
}
}
}
int main(void) {
int a, b, c;
printf("This is a Addition program");
a = getint("\n Enter value of a:");
b = getint("\n Enter value of b:");
c = a + b;
printf("\n The added value is %d", c);
return 0;
}

Factorial issue with user input

I am learning c language and i am confused about the code below. its a recursion but how come when i run this code, it won't run until i provided 2 different inputs but system only execute the first?
Thanks in advance.
#include <stdio.h>
long factor (float user_input)
{
if(user_input <=1)
return 1;
else
return (user_input * factor (user_input - 1));
}
int main ()
{
int user_input;
long factorial_calculation;
printf("what factorial number would you like to calculate?\n");
scanf("%d\n", &user_calculation);
factorial_calculation = factor (user_input);
printf("ld\n", factorial_calculation);
return 0;
}
Your user_input is int but you are passing variable as a float and running your factorial function on it. Factorials are undefined for non-integer nos, so you are better off using int.
In:
printf("ld\n", factorial_calculation);
ld is an invalid format specifer.
In
scanf("%d\n", &user_calculation);
I think you meant
scanf("%d", &user_input);
The following code works:
#include <stdio.h>
int factor (int user_input)
{
if(user_input <=1)
return 1;
else
return (user_input * factor (user_input - 1));
}
int main ()
{
int user_input;
long factorial_calculation;
printf("what factorial number would you like to calculate?\n");
scanf("%d", &user_input);
printf("%d\n",user_input);
factorial_calculation = factor (user_input);
printf("%d\n", factorial_calculation);
return 0;
}
scanf() is notoriously difficult to synchronize with user input. Instead, use fgets() and inspect the string for a number (or numbers if more than one is expected per line).
long factorial_calculation;
char buf [1000];
for (;;)
{
printf("What factorial number would you like to calculate?\n");
if (!fgets (buf, sizeof buf, stdin)) /* probably EOF, hangup, etc.: just exit */
return 0;
if (1 != sscanf(buf, "%ld", &user_calculation))
{
printf ("No number entered, please try again\n");
continue;
}
factorial_calculation = factor (user_input);
}

Resources