Why do I get, variable is not initialized error? - c

#include <stdio.h>
#include <conio.h>
void Calculator();
void main()
{
Calculator();
getch();
}
void Calculator()
{
int n,j;
char f1;
double t;
printf("please enter two numbers");
scanf("%d%d",&n,&j);
printf("please enter the syboml you want ( * / + or -)");
scanf("%c",&f1);
if( f1 == '+')
t = n + j;
if (f1 == '-')
t = n-j;
if (f1 == '*')
t = n*j;
if (f1 == '/')
t = n/j;
printf("%f" ,t);
}

In your final printf, you are using t that has never been initialized, and might hold a garbage value if no-one of those if conditions is met.
Consider initializing t (a simple = 0 does the job) or add an else clause somewhere
Edit:
While I was at it, I also made some changes to make sure the second scanf ignores the trailing /n without using fflush.
Edit 2:
As suggested by HAL9000, assuming that an initialization to 0 would be enough is wrong. I modified the second part of the program to make use of a switch-case and eventually reject an invalid operator.
The final code looks like this
#include <conio.h>
#include <stdio.h>
void Calculator();
int main() {
Calculator();
getch();
return 0;
}
void Calculator() {
int n, j;
char f1;
double t;
printf("please enter two numbers: ");
scanf("%d%d", &n, &j);
printf("please enter the symbol you want ( * / + or -): ");
scanf(" %c", &f1);
switch (f1) {
case '+':
t = n + j;
break;
case '-':
t = n - j;
break;
case '*':
t = n * j;
break;
case '/':
t = (float)n / j;
break;
default:
printf("Invalid symbol, please use ( * / + or -)\n");
return;
}
printf("%f\n", t);
}

In some compilers, you might be getting this t is not initialized error as your code will never ask please enter the symbol you want ( * / + or -) because scanf("%c",&f1); will take input as trailing newline char, so t never gets initialized. I ran your code in GCC compiler on mac but got output as 0.0000 as t will never be initialized in your case.
You can just eat up the trailing char for that you can use getchar(); or you can also put a space in the format string, e.g. scanf(" %c",&f1); to consume the newline character.
void Calculator()
{
int n,j;
char f1;
double t;
printf("please enter two numbers");
scanf("%d%d",&n,&j);
printf("please enter the syboml you want ( * / + or -)");
scanf(" %c",&f1);
if( f1 == '+')
t = n + j;
if (f1 == '-')
t = n-j;
if (f1 == '*')
t = n*j;
if (f1 == '/')
t = n/j;
printf("%f" ,t);
}

Not every program path leads to the assignment of the t variable. So it can be used in the printf not initialized.
switch(f1)
{
case '+':
t = n + j;
break;
case '-':
break;
t = n-j;
case '*':
t = n*j;
break;
case '/':
t = n/j;
break;
default:
t = 0;
break;
}
Now t will always will be assigned with the value.
Some additional remarks:
Always check the return value of the scanf
Your main definition is invalid. If main does not take any parameters is has to be int main(void)

Related

When inputting large numbers it returns the final result as NaN

I am creating a SUPER basic calculator in C for a project.
/*
Declare and initialize variables and/or constants using appropriate data types -- X
Read in input from the user and output data & information to the user in a meaningful manner -- X
Use the mathematical operators – addition, subtraction, multiplication, division, and modulus (remainder)
– in expressions and calculations -- X
Use decision making structures such as if, if/else, and switch to affect program flow -- X
Use control structures such a while, do-while, and for loops to implement repetition in code -- X
*/
//All libraries
#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>
float num1 = 0;
float num2 = 0;
float finalResult = 0;
char operator = '+';
bool opReal = false;
int main() {
//Ask for first number
printf("Enter an number: ");
scanf("%f", &num1);
printf("\n");
//Ask for second number
printf("Enter another number: ");
scanf("%f", &num2);
printf("\n");
//Ask for operator
do {
printf("Enter either + - * or /: ");
scanf(" %c", &operator);
//Check for what operator is
if (operator == '-') {
operator = '-';
opReal = true;
} else if (operator == '+') {
operator = '+';
opReal = true;
} else if (operator == '*') {
operator = '*';
opReal = true;
} else if (operator == '/') {
operator = '/';
opReal = true;
} else {
operator = '+';
opReal = false;
}
} while (!opReal);
printf("num1: %f\n", num1);
printf("num2: %f\n", num2);
printf("operator: %c\n", operator);
//Do calculations
if (operator == '-') {
finalResult = num1 - num2;
} else if (operator == '+') {
finalResult = num1 + num2;
} else if (operator == '*') {
finalResult = num1 * num2;
} else if (operator == '/') {
finalResult = num1 / num2;
}
printf("Final Result: %f\n", finalResult);
}
I've tried looking up different solutions and applying different ways to operate on num1 and 2, but in the end they don't work.
It should take num1 and num2 and apply operator to it.
However when a large number is applied then num1 = inf and num2 = inf.
That in turn makes finalResult Nan
Whats happening?
Please help.
Well depending on how large those large numbers are, you might just be able to replace "float" with "double" and have it work.
Other than that you could add the following check to your code:
if(isinf(num1) || isinf(num2) || isnan(num1) || isnan(num2)) {
printf("Error, number out of bounds!");
return -1;
}
Though this requires the use of #include <math.h> though, if you are constrained to just the libraries specified in this file (as might be implied by the comment) then this might just be an unsolvable problem.
I don't see anything particular wrong with your code so maybe you just need to switch from float to double or even long double? Don't use global variable unless you have to. Guard against divide by zero. No point of checking if an operator is x then assign x to the operator. Check that scanf() was successful otherwise you may be operating on uninitialized data.
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
int main() {
double num1;
printf("Enter a number: ");
if(scanf("%lf", &num1) != 1) {
printf("scanf failed\n");
return 1;
}
double num2;
printf("Enter another number: ");
if(scanf("%lf", &num2) != 1) {
printf("scanf failed\n");
return 1;
}
char operator;
do {
printf("Enter either + - * or /: ");
if(scanf(" %c", &operator) != 1) {
printf("scanf failed\n");
return 1;
}
} while (!strchr("-+*/", operator));
double finalResult = 0;
if (operator == '-') {
finalResult = num1 - num2;
} else if (operator == '+') {
finalResult = num1 + num2;
} else if (operator == '*') {
finalResult = num1 * num2;
} else if (operator == '/') {
finalResult = num2 != 0 ? num1 / num2 : 0; // or ERR?
}
printf("Final Result: %lf\n", finalResult);
}
I would use an array of numbers, dedup the input with a loop and probably a switch instead of all those if-else-if:
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#define NUM_LEN 2
int main() {
const char *prompts[NUM_LEN] = { "an", "another" };
double num[NUM_LEN];
for(size_t i = 0; i < NUM_LEN; i++) {
printf("Enter %s number: ", prompts[i]);
if(scanf("%lf", &num[i]) != 1) {
printf("scanf failed\n");
return 1;
}
}
char operator;
do {
printf("Enter either + - * or /: ");
if(scanf(" %c", &operator) != 1) {
printf("scanf failed\n");
return 1;
}
} while (!strchr("-+*/", operator));
switch(operator) {
case '-':
num[0] -= num[1];
break;
case '+':
num[0] += num[1];
break;
case '*':
num[0] *= num[1];
break;
case '/':
num[0] = num[1] != 0 ? num[0] / num[1] : 0; // or ERR?
break;
default:
printf("Invalid operator\n");
break;
}
printf("Final Result: %lf\n", num[0]);
}
The next step would be to build a map from operator to a function, i.e:
struct operators {
char operator;
int (*evaluate)(double *num);
} operators[] = {
{'+', add},
{'-', subtract},
{'*', multiply},
{'/', divide}
};
Now you extract the valid operators used in strchr() from this map, and you can use lfind() to lookup the evaluate function for a given operator.

passing argument 1 and 2 of ‘strcmp’ makes pointer from integer without a cast [-Wint-conversion]

Hello so I've been working a little prgramme which is sort of a calculator (I'm a beginner) and well as you can see in the tittle at then end of the code, the two if strcmp doesn't work. And vscode is telling me (for the strcmp) Exception has occurred. Segmentation fault. But gcc is telling me what is in the tittle.
#include <stdio.h>
#include <string.h>
int main()
{
float num1;
float num2;
float anwser;
int rnum = 1;
int hi = 0;
char operator;
char ifyorn;
char y = 'y';
char n = 'n';
while (hi == 0)
{
printf("Enter operator +, -, /, x: ");
scanf(" %c", &operator);
printf("Enter num %d :", rnum++);
scanf("%f", &num1);
printf("Enter num %d :", rnum++);
scanf("%f", &num2);
switch (operator)
{
case '+':
anwser = num1 + num2;
printf("Do you want to continue y/n \n");
scanf(" %c", &ifyorn);
break;
case '-':
anwser = num1 - num2;
printf("Do you want to continue y/n \n");
scanf(" %c", &ifyorn);
break;
case 'x':
anwser = num1 * num2;
printf("Do you want to continue y/n \n");
scanf(" %c", &ifyorn);
break;
case '/':
anwser = num1 / num2;
printf("Do you want to continue y/n \n");
scanf(" %c", &ifyorn);
break;
default:
printf("This is not a valid character please try again :(");
break;
}
if(strcmp (ifyorn, n) == 0)
{
printf("%f", anwser);
hi == 1;
}
if(strcmp (ifyorn, y) == 0)
{
hi == 0;
}
}
}
The variables ifyorn, y and n are declared having the type char.
char ifyorn;
char y = 'y';
char n = 'n';
The function strcmp expects arguments of the pointer type char * that point to strings.
So these if statements
if(strcmp (ifyorn, n) == 0)
and
if(strcmp (ifyorn, y) == 0)
are incorrect. Instead you should write
if ( ifyorn == n )
and
if ( ifyorn == y )
Also instead of assignments you are using the comparison operator in these statements
hi == 1;
and
hi == 0;
You need to write
hi = 1;
and
hi = 0;
Increasing the variable rnum looks senseless
printf("Enter num %d :", rnum++);
scanf("%f", &num1);
printf("Enter num %d :", rnum++);
scanf("%f", &num2);
Why not just to write
printf("Enter num %d :", 1 );
scanf("%f", &num1);
printf("Enter num %d :", 2 );
scanf("%f", &num2);
And in the code snippet under the label default you should add one more statement
default:
printf("This is not a valid character please try again :(");
ifyorn = y;
break;
You don't have to be mean to the guy ,he is learning.
You are getting this error because you are passing characters to strcmp() instead of pointers to characters.
Here is more information regarding that function.
https://www.programiz.com/c-programming/library-function/string.h/strcmp

Suprisingly small limits of the calculator written in C

My task is to write a calculator, which accepts only valid operands, that is, * / + - ^. The calculator has to evaluate (check the validity) of the line being entered. For example, it accepts only lines of the following form: 20 + 9, 8 ^ 2, etc. If someone entered 9y, 20+2 or exit, the expression would be evaluated to 0. Then the user has to have the possibility of displaying lines, which were entered, regardless of their validity. (Switch E for invalid lines, switch V for valid lines, if valid line is entered and V is chosen it also displays the value of an expression).
Let's now consider the example in order to see how it works.
Line: 20 + 20
Switch: E
Output: There's nothing wrong with the line 20 + 20.
Switch: V
Output: The result is 40.
Line: 20r
Switch: E:
Output: The line is 20r
Switch: V:
Output: The line 20r is invalid.
The problem:
Every time I enter a line, which would have the result of calculation more then, I guess 7000 (it doesn't work for 8 * 900), it doesn't even allow me to choose the char for the switch. It displays the line Choose E for... and then automatically You haven't chosen the valid option of the switch..
MAIN.C:
#include "stdio.h"
#include "evalexpression.h"
int main() {
char string[100];
int result;
result = InterCalc(string);
CalcFilter(result, string);
return 0;
}
EVALEXPRESSION.C
#include "stdio.h"
#include "string.h"
#include "evalexpression.h"
#include "math.h"
#include "float.h"
static float f1, f2;
static char op;
int isValidExpression(const char *str) {
int res;
char ops[10];
res=sscanf(str, "%f %s %f", &f1, ops, &f2);
if (res==3) {
if (ops[0]=='+' || ops[0]=='-' || ops[0]=='^' || ops[0]=='*' || ops[0]=='/') {
op=ops[0];
return 1;
}
else
return 0;
}
else
return 0;
}
int getOperator() {
if (op=='+')
return 1;
else if (op=='-')
return 2;
else if (op=='/')
return 3;
else if (op=='*')
return 4;
else if (op=='^')
return 5;
else return 0;
}
float getFstOperand() {
return(f1);
}
float getSecOperand() {
return(f2);
}
int InterCalc(char *my_string) {
fgets(my_string, sizeof(my_string), stdin);
if (strcmp(my_string, "exit\n")==0 ) {
printf("Program ended\n");
return 0;
}
else if ( isValidExpression(my_string) == 0 ) {
printf("Expression error\n");
return 0;
}
else
return 1;
}
float getExprValue() {
int operation;
operation = getOperator();
switch (operation) {
case 1:
return (getFstOperand() + getSecOperand());
break;
case 2:
return (getFstOperand() - getSecOperand());
break;
case 3:
return (getFstOperand() / getSecOperand());
break;
case 4:
return (getFstOperand() * getSecOperand());
break;
case 5:
return ( pow(getFstOperand(), getSecOperand()) );
break;
default:
return 0;
}
}
void CalcFilter(int a, char *str) {
float calculation_value;
printf("Press 'E' to display the invalid line or press 'V' to display the valid line\n");
int choice;
choice = getchar();
switch (choice) {
case 'E':
case 'e':
if (a==0)
printf("The line %s is invalid.\n", str);
else if (a==1)
printf("There's nothing wrong with the line %s\n", str);
break;
case 'V':
case 'v':
if (a==1) {
calculation_value = getExprValue();
//if (calculation_value > FLT_MAX || calculation_value < FLT_MIN)
// printf("The value of expression is beyond limits\n");
//else
printf("The result of %s is %f.\n", str, calculation_value); }
if (a==0)
printf("The line %s is invalid\n", str);
break;
default:
printf("You haven't chosen the valid option of the switch\n");
break;
}
}
Look at the first lines of your InterCalc() function
int InterCalc(char *my_string) {
fgets(my_string, sizeof(my_string), stdin);
sizeof is a compile-time operator. sizeof(my_string) is the size of a pointer to char which for a 32 bit system is typically 4 bytes.
sizeof does not give the length of whatever string my_string points at. It will not give 100 (the length of the array in main()).
You will need to pass the value 100 (or whatever the size is in main() if you change it) by some other means, such as an extra function parameter.

Could someone please why this program is not running correctly. I'm new to C

Good evening. I just started learning C in college and our 1st assignment was to make a program that calculates the user's bmi. For the life of me I can't figure out why Im not getting the results I want. No matter what height & weight I submit to the program...I keep getting a ridiculously high bmi like 4258544 and then it tells me I'm underweight. i thought I could use another set of eyes.
Please help.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void h_conversion (double *h) {
*h = *h/12;
}
int bmi_category (double h, double w, double b) {
b = (w * 4.88)/(h * h);
if (b < 20)
return 1;
else if (b >= 20 && b < 25)
return 2;
else if (b >= 25 && b < 30)
return 3;
else if (b >= 30 && b < 40)
return 4;
else
return 5;
}
int main (void) {
double height, weight, bmi;
double *h, *w, *b;
h = &height;
w = &weight;
b = &bmi;
printf ("Please enter height (inches): \n");
scanf (" %lf", &height);
while ( h <= 0 ) {
printf ("Weee, this is fun! Try again.\n");
scanf (" %.2lf", &height);
}
if ( *h < 42 || *h > 84 )
printf ("Your entry falls outside the norm for an adult.\n");
h_conversion( h );
printf ("Please enter weight (lbs): \n");
scanf (" %.2lf", &weight);
while ( w <= 0 ) {
printf ("This is why we can't have nice things. Try again.\n");
scanf (" %.2lf", &weight);
}
switch ( bmi_category(*h, *w, *b)) {
case 1:
printf ("BMI: %d. Underweight.", (int)&bmi);
break;
case 2:
printf ("BMI: %d. Normal weight.", (int)&bmi);
break;
case 3:
printf ("BMI: %d. Slightly overweight.", (int)&bmi);
break;
case 4:
printf ("BMI: %d. Overweight.", (int)&bmi);
break;
case 5:
printf ("BMI: %d. Extremely overweight.", (int)&bmi);
break;
default:
printf ("error condition\n");
}
system ("pause");
return 1;
}
In your printf's you're using
(int)&bmi
// this request the address of bmi and casts that value to an integer (addresses are always integers)
When you should be using
(int)bmi
// this casts the value of the variable bmi to an integer which is what you want.
The weird values you're always getting is because you're getting addresses instead of the values of the variables.
Also why all the pointer variables? You only need the h one. The bmi function doesn't require you use pointers so why use them instead of the of its non-pointer counterparts?
Also main returns 0 when it's finished its execution without any issues. For some reason you're returning 1 indicating the program didn't finish execution properly.
int bmi_category (double h, double w, double b) {
b = (w * 4.88)/(h * h);
...
switch ( bmi_category(*h, *w, *b)) {
case 1:
printf ("BMI: %d. Underweight.", (int)&bmi);
The assignment to b inside bmi_category will not change the value
of bmi in your main routine, as you seem to expect, since you're passing
the value *b, rather than the pointer b. And as another answer points out, the (int)&bmi expressions are also not what you need.
for double should use it:
scanf("%lf", &height);
In your call to bmi_category function, the parameters were passed incorrectly. You were passing the value when pointer was expected. Because of this, the value of calculated bmi was local to the bmi_category function and wouldn't get updated to the caller.
When printing the value of bmi, you were printing the address &bmi instead of the value.
Here is the fixed code with a little cleanup:
#include <stdio.h>
#include <stdlib.h>
void h_conversion(double *h) {
*h = *h / 12;
}
int bmi_category(const double *h, const double *w, double *b) {
*b = (*w * 4.88) / (*h * *h);
if (*b < 20)
return 1;
else if (*b >= 20 && *b < 25)
return 2;
else if (*b >= 25 && *b < 30)
return 3;
else if (*b >= 30 && *b < 40)
return 4;
else
return 5;
}
int main(void) {
double height, weight, bmi;
printf("Please enter height (inches): \n");
scanf(" %lf", &height);
while (height <= 0) {
printf("Weee, this is fun! Try again.\n");
scanf(" %lf", &height);
}
if (height < 42 || height > 84)
printf("Your entry falls outside the norm for an adult.\n");
h_conversion(&height);
printf("Please enter weight (lbs): \n");
scanf(" %lf", &weight);
while (weight <= 0) {
printf("This is why we can't have nice things. Try again.\n");
scanf(" %lf", &weight);
}
switch (bmi_category(&height, &weight, &bmi)) {
case 1:
printf("BMI: %d. Underweight.", (int)bmi);
break;
case 2:
printf("BMI: %d. Normal weight.", (int)bmi);
break;
case 3:
printf("BMI: %d. Slightly overweight.", (int)bmi);
break;
case 4:
printf("BMI: %d. Overweight.", (int)bmi);
break;
case 5:
printf("BMI: %d. Extremely overweight.", (int)bmi);
break;
default:
printf("error condition\n");
}
system("pause");
return 1;
}

Is it possible to test a float using isdigit() function?

I need to ask an input from a user and he/she should have the ability to write a float number, and I need to do some calculation on the 2 numbers, but I'm having a problem after the isdigit test...even if I enter an integer its going to the continue;
This is my code:
#include <stdio.h>
#include <ctype.h>
char get_choice(void);
float calc(float number1, float number2);
int main()
{
float userNum1;
float userNum2;
get_choice();
printf("Please enter a number:\n");
while ((scanf("%f", &userNum1)) == 1)
{
if (!isdigit(userNum1))
{
printf("Please enter a number:\n");
continue;
}
printf("Please enter another number:\n");
while ((scanf("%f", &userNum2) == 1))
{
if (!isdigit(userNum2))
{
printf("Please enter a number:/n");
continue;
}
else if (userNum2 == '0')
{
printf("Please enter a numer higher than 0:\n");
continue;
}
}
}
calc(userNum1, userNum2);
return 0;
}
float calc(float number1, float number2)
{
int answer;
switch (get_choice())
{
case 'a':
answer = number1 + number2;
break;
case 's':
answer = number1 - number2;
break;
case 'm':
answer = number1 * number2;
break;
case 'd':
answer = number1 / number2;
break;
}
return answer;
}
char get_choice(void)
{
int choice;
printf("Enter the operation of your choice:\n");
printf("a. add s. subtract\n");
printf("m. multiply d. divide\n");
printf("q. quit\n");
while ((choice = getchar()) == 1 && choice != 'q')
{
if (choice != 'a' || choice != 's' || choice != 'm' || choice != 'd')
{
printf("Enter the operation of your choice:\n");
printf("a. add s. subtract\n");
printf("m. multiply d. divide\n");
printf("q. quit\n");
continue;
}
}
return choice;
}
Apologize for uploading the functions as well, but since I'm a newbie the problem might be there.
Cheers.
isDigit() only takes a character input.
The best way to check that you are getting input correctly is to use
if(scanf("%f", &userNum) != 1) {
// Handle item not float here
}
Since scanf() will return the number of items correctly scanned.
IsDigit() Function check only if the character is decimal digit or not.
Let say:
int isdigit ( int c );
Checks whether c is a decimal digit character.
Decimal digits can be any of: 0 1 2 3 4 5 6 7 8 9.
The isdigit() function will return non-zero if c is a decimal digit; otherwise, it shall return 0.
You can also try something like this:
int get_float(char *val, float *F){
char *eptr;
float f;
errno = 0;
f = strtof(val, &eptr);
if(eptr != val && errno != ERANGE){
*F = f;
return 1;
}
return 0;
If val points to float number function return 1 & put this number to *F, else it returns 0.

Resources