Why am I getting 0.00 when I enter alphabetical character? - c

The following is the code that I wrote. I feel like I have missed something with the pointer or might have made mistake in the calculation. But as for as I see, everything seems good for me but when I enter, for example: hello or anything else, it gives me 0.00 as output.
The below is correct
Enter a number:
6
Your number is: 6.00
But this why?
Enter a number:
h
Your number is: 0.00
Following is the complete code:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 250
float myAtof(char *string, char *error);
int main() {
char string[SIZE]; // Array declaration.
float fnum1;
char errorState=0;
printf("Enter a number:\n");
gets(string);
fnum1=myAtof(string,&errorState);
if (errorState == 0) {
printf("Your number is: %.2f \n", fnum1);
} else if (errorState == 1) {
printf("Error has been occurred due to inappropriate input!\n");
}
return 0;
}
float myAtof(char* string, char* error) {
*error != '1';
float num= 0;
float decimalFlag = 1;
int decimalNumberFound = 0;
for (int i = 0; string[i]!= '\0'; i++) {
char ch = string[i];
if (ch != '.' && (ch < '0' || ch >'9')) {
error ='1';
return 0;
}
if (decimalNumberFound == 1 && ch == '.') {
error = '1';
return 0;
} else {
num = num* 10 + (ch - '0');
if (decimalNumberFound == 1)
decimalFlag *= 10;
}
}
num = num / decimalFlag;
return num;
}

Since your myAtof routine has a parameter for reporting an error and your main routine tests the error-reporting variable, errorState, presumably you expect the program to print an error message when you enter “h” or other non-numerals, and your question is why it prints “0.00” rather than the error message.
In the function declared with float myAtof(char* string, char* error), error is a pointer, and *error is the thing it points to. So, when the code executes error = '1';, that attempts to set the pointer to '1'. It does not change the thing it points to.
When you compiled this, the compiler issued a warning message, something like “warning: incompatible integer to pointer conversion assigning to 'char *' from 'int'”. You should not have ignored that message.
The function also contains the statement *error != '1';. That statement does nothing. It says to compare the value of *error to '1' to see if they are unequal. The result of the != operator is 1 or 0 indicating whether the values are unequal or not. But the statement does nothing with that result. It is just discarded, so the statement has no effect.
Nothing in your function changes the value of *error, so the thing it points to, errorState in main, is never changed. So main does not see that an error has occurred. It evaluates errorState==0 as true and executes printf("Your number is: %.2f \n", fnum1);.
To fix this, delete the statement *error != '1'; and change the two error = '1'; statements to *error = '1';.
Additionally, change '1' to 1. Setting *error to '1' sets it to the code for the character “1”. It does not set it to the value 1, which is what errorState == 1 tests for. Typically, an error status would be either 0 or 1, not 0 or '1'.
Also change else if (errorState == 1) to else. When you have an if and else that are intended to completely select between some condition X and its alternative, you do not need a second test. With your code if (X) { … } else if (Y) { … }, the first { … } is executed if X is true, the second { … } is executed if X is false and Y is true, and neither is executed if X is false and Y is false. But it should never be the case that X is false and Y is false—you want the program always to either have a number or have an error status. There should be only two possibilities, not three. So use just else, not else if.
(Conceptually, it is a bug for the program to have errorState be something other than 0 or 1, so the program would never have both X false and Y false if it were working, and the else if would be okay. But you did have a bug, and that would cause neither { … } to be executed. Designing the code to use else instead of an unnecessary else if makes it a little more resistant to misbehaving when there is a bug. Designing programs to be robust in this way is useful.)
Also pay attention to warning messages from your compiler. Preferably, tell the compiler to treat all warnings as errors, so that your program will not compile while warning messages remain. If you are using GCC or Clang, use the -Werror switch. If you are using Microsoft Visual C++, use /WX.

Related

Using strcmp within an if() statement within a user-defined function does not return expected output

I am working on a homework assignment focusing on strings for an Intro to C class. I am having trouble using the strcmp() function within an if statement, within a user-defined function.
The assignment requires us to use a user-defined function (mine is Check()) to check whether two strings are the same (comparing a user-inputted string to a string from a file). For some reason, my professor wants Check() to return a 1 if the strings match and a 2 if the strings don't match, even though to my knowledge strcmp() already returns 0 if the strings match and some other value if they don't.
Once my Check() function returns a value (x=1 for match, x=2 for no match), I run that x value through another if statement within my main function that should print "You are correct" for x=1, and "You are incorrect" for x=2.
The problem I am having is that no matter whether the strings match or not, my conditional within my main function always tells the user they are correct, i.e. the strings match. I assume the issue lies within my Check() function and my use of strcmp(), as I am not entirely familiar with how strcmp() works.
I have already tried modifying my conditional within Check() so that I have if(strcmp(solution, guess)==0) followed by else if(strcmp(solution, guess)!=0), and that did not fix my problem.
My user defined function:
int Check(char solution[], char guess[])
{
if (strcmp(solution, guess) == 0)
{
int x = 1;
return x;
}
else
{
int x = 2;
return x;
}
}
This is fed to my main function as:
Check(solution, guess);
if (x == 1)
{
printf("Congratulations, you guessed correctly");
}
else if (x == 2)
{
printf("You guessed incorrectly");
}
When solution = "FLORIDA" and guess = "FORLIDA", "You guessed incorrectly" should be printed, but "Congratulations, you guessed correctly" is instead.
You are not assigning the return value to any variable.
Write
x = Check(solution, guess);
before the if statement.
if (x == 1)
{
printf("Congratulations, you guessed correctly");
}
else if (x == 2)
{
printf("You guessed incorrectly");
}
in fact instead of else if you can write just else because there are only two possibilities.
So without the variable x the if statement may be rewritten like
if ( Check(solution, guess) == 1 )
{
printf("Congratulations, you guessed correctly");
}
else
{
printf("You guessed incorrectly");
}
Take into account that the function can be defined simpler
int Check( const char solution[], const char guess[] )
{
return strcmp( solution, guess ) == 0 ? 1 : 2;
}

Weird Error when using atof in c

I understand there are bugs with "Bad Input" but for some reason i cant even get good input to go through. It's either returning a value of 10 or 0 and i can't seem to find the reason why. Below is where i am calling it:
var1 is datatype float. All headers are included that are needed.
floatHolder is datatype char array.
Below is where i am calling it:
scanf("%s", &floatHolder);
var1 = inputchecker(floatHolder);
this is the function that is called:
float inputchecker(char *charArray)
{
float f = 0;
float f2 = 0;
int i = 0;
int z = 0;
int badInput = 0;
char errorArray[15];
func1:
while (i<strlen(charArray))
{
if (charArray[i]<48 || charArray[i]>57)
{
if (charArray[i] == 46)
{
i++;
goto func1;
}
printf("\n Entered value contains alphabets or symbols, please enter numerical/Floating point values only.\n");
printf("Re-enter Correct Input Please: ");
scanf("%s", &errorArray);
getchar();
badInput = 1;
goto func2;
}
i++;
}
func2:
while (z < strlen(errorArray) && badInput == 1)
{
if (errorArray[i] < 48 || errorArray[i]>57)
{
if (errorArray[i] == 46)
{
z++;
goto func2;
}
printf("Re-enter Correct Input Please: ");
scanf("%s", &errorArray);
getchar();
}
z++;
}
badInput = 0;
f = atof(charArray);
f2 = atof(errorArray);
if (f == 0)
{
return f2;
}
if (f2 == 0)
{
return f;
}
}
For some reason after the function is called it shows a correct return value ex. if i give it 4 it will return 4 but var1 will show a insanely large number, 0, and 10. If anyone can let me know what i'm doing wrong it would be greatly appreciate.
I tried out your routine and received similar results. Then I realized what you problem is. You probably neglected to put a function prototype at the top of your file.
float inputchecker(char *charArray);
By neglecting to use a prototype the compiler will have to guess the signature of the function and the stack may not be restored properly and your return value then will be corrupted.
When I added the prototype at the top of the file, everything worked fine for valid float inputs such as 3.14
Note: different versions of C will behave differently. For example C89/C90 will 'guess' what the parameters will be without a prototype. This can be quite dangerous and it is what I think happened in your situation. I think C99 works in a similar way but with some differences.
Another, proof that you are not using a prototype is that you are receiving integer answers. When the compiler 'guesses' the prototype, it will typically return an int. Furthermore, this also explains why you are getting the same results for different input, you are getting the contents of the same memory location (not your f variables) due to the stack corruption.
Its very very good practice to always define function protoypes at the top of your file.

Conversion of float to int changes the value

I've looked at this question, and it doesn't appear to be the same situation.
I have a function in the check register program I'm writing that reads in a dollar amount from the user, validates it wasn't entered with fractional cents, and checks with the user that it was entered correctly. What I'm getting, though, is that after multiplying the float value that was entered by 100 and truncating with (int), the value changes. For instance, if I enter 1118.58, I can (via debug printf statements) verify that 1118.58 was scanned and assigned to amt correctly, and my while conditional (int)100 * amt == 100 * amt is correctly testing as TRUE, but after conversion to integer, the integer value is stored as 111857. More perplexing, it doesn't happen with every value (though I'm just getting going well on testing, this is the first entry I've seen change this way).
I'm using gcc on Kubuntu 14.04 64-bit, with C99 standard setting in my compile command.
Here's the function that's giving the problem (presuming you don't want/need to see 1300 lines of the complete program). Note: I have Boolean values and operators defined in a header file for my convenience -- I've recently discovered there's a standard way to do that, but haven't converted my header file yet.
int get_amt (void)
{
float amt;
int scanned, i_amt;
int success = FALSE;
char yn = '\0';
while (NOT success)
{
scanned = scanf("%f%*c", &amt);
/* validate and verify amount */
if (scanned >= 1 AND (int)100*amt == 100*amt AND amt <= 100000)
{
i_amt = (int)(100 * amt);
printf("\n amt = %4.2f i_amt = %i", amt, i_amt);
printf("\nYou entered $%i.%.2i -- Correct (Y/n)?", i_amt/100, i_amt%100);
scanf("%c%*c", &yn);
if (yn == '\0' OR yn == 'Y' OR yn == 'y')
success = TRUE;
}
}
return (i_amt);
}
And here's an output sample with the debug print statement:
Enter deposit amount (dollars and cents): $ 1118.58
amt = 1118.58 i_amt = 111857
You entered $1118.57 -- Correct (Y/n)?
Why is this happening, and how do I fix it?
After discussion in the comments below, I've converted the function to use integers, so there's no question of float precision (I hadn't really thought about just how little precision a standard float has on a 64-bit OS and compiler). Here's the updated version, which can't give this failure because there are no floats:
int get_amt (void)
{
int scanned, amt1, amt2;
int success = FALSE;
char yn = '\0';
while (NOT success)
{
scanned = scanf("%i.%i%*c", &amt1, &amt2);
/* validate and verify amount */
if (scanned >= 1)
{
printf("\nYou entered $%i.%.2i -- Correct (Y/n)?", amt1, amt2);
scanf("%c%*c", &yn);
if (yn == '\0' OR yn == 'Y' OR yn == 'y')
success = TRUE;
}
}
return (100*amt1 + amt2);
}
As #MitchWheat has already alluded to in a comment above, it is likely that when you print out the float, it rounds up, whereas when you calculate the int, it simply truncates. Get around this by using the round function. I.e., i_amt = round(100 * amt);, which will round the number in the same manner as the float is rounded.

Code working on DEvC++ and Ideone but not on competetion website

This code works on DEVCPP and IDEONE but is not accepted by the website where this question is.
It is an on-line competition where the in built compiler is saying: COMPILATION FAILED.
This is a program which finds str2 in str1 and returns index of sub-string if found. Else prints -1.
I know using GOTO is not recommended. :( Sorry for this. Cant figure out a way for this.
IDEONE link: LINK
Code is:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char s1[19], s2[19],*p,c,d,k=0;
int i;
gets(s1); gets(s2);
p = strstr(s1,s2);
if( (strlen(s2) > strlen(s1)) || !p )
{printf("-1");goto ex;}
for(i=0;i<strlen(s1); i++)
{
c = s1[i];
d = s1[i+1];
if(c == s2[k] && d == s2[k+1])
{
printf("%d", i);
goto ex;
}
}
ex:
return 0;
}
a.c:15:14: error: comparison between signed and unsigned integer expressions
Make i unsigned.
a.c:19:9: error: array subscript has type 'char'
Make k int.
Notes:
Use fgets instead of gets.
goto is ok in some circumstances, like the pattern you use can be used to do some default-stuff (eg logging) before return. Also for dropping out from inner loops, jump-table usage (&&), doing default: after having done one of the case x:'s, retry after case x: and a few others.

Averaging 3 integers

My assignment is to fix the code. I have my edited code below and the original code below that. I figure I still have a few errors in here. My error checking doesnt seem to work, and I am not sure if my getchar() function is written or working properly.
Please assume I know nothing becasue that is fairly accurate.
The code compiles, but the answer is always 2. I am about 4 hours into this piece of code with 3 more to work after this.
My code
#include <stdio.h>
double get_number(double num);
main () {
double n1,n2,n3;
double average;
printf("\nCompute the average of 3 integers\n");
printf("--------------------------------\n");
n1 = get_number(1);
n2 = get_number(2);
n3 = get_number(3);
average = (n1 + n2 + n3)/3;
printf("The average is %0.2f\n",average);
}
double get_number(double num) {
double value = 0;
char c;
int i;
printf("Please input number %d: ", num);
while (c = getchar != '\n') {
if ( (c>9) || (c<0) ) {
printf("Incorrect character entered as a number - %c\n",c);
return(0);
}
else {
value = num;
}
}
return(value);
}
Original code
#include <stdio.h>
main () {
double n1,n2,n3;
double average;
printf("\nCompute the average of 3 integers\n");
printf("--------------------------------\n");
n1 = get_number(1);
n2 = get_number(2);
n3 = get_number(3);
average = (n1 + n2 + n3)/3;
printf("The average is %0.2f\n",average);
}
double get_number(int num) {
double value = 0;
char c;
printf("Please input number %d: ", num);
while (c = getchar() != '\n') {
if ( (c<=9) && (c>=0) ) {
printf("Incorrect character entered as a number - %c\n",c);
exit(-1);
}
else {
value = 10*value + c - '0';
}
}
return(value);
}
A few issues:
1. You should be using '9' and '0', since you want the ASCII values for digit '9' (0x39) and '0' (0x30), not 0x9 and 0x0.
if ( (c>'9') || (c<'0') ) {
2. != has higher precedence than =, so you need parens. Learn operator precedence, and if you're in doubt, use parens:
3. getchar is a function not a variable.
while ((c = getchar()) != '\n') {
4. You use the wrong conversion. num is a double, so you would need %f. Or, you could make num a int.
printf("Please input number %f: ", num);
5. You never actually use c in any way (except error checking). You always return 0 or num (see your else clause), which makes no sense. The else body of the original is correct.
You got the floating point parsing all wrong and shouldn't be doing it yourself. There's an easier way:
double get_number(double num) {
double value = 0.0;
printf("Please input number %lf: ", num);
scanf("%lf", &value);
return(value);
}
The issues with the original program are:
getchar() returns an ASCII code, and the condition was wrong. When checking for boundaries, use ((c<'0') || (c>'9')).
For the exit function you need to include "stdlib.h".
For the main function to understand what is get_number, you need to either move the function to be before the main function, or you can use a forward declaration.
The assignment operator (=) has lower precedence than the inequality operator (!=), so you need to use parenthesis, like: ((c = getchar()) != '\n')
You have actually created several more issues, so I wouldn't rely on your code.
In any case, in general - it is advised you study how to use a debugger. Once your code is compiling (and for that you'll need to get accustomed to the compilation error messages), you need to start debugging your code. I suggest you take some time to learn how to set breakpoints, set watches, and go step by step into your code. That skill is absolutely essential for a good developer.
Here's how I'd go about correcting the code ...
http://ideone.com/a0UMm -- compilation errors
http://ideone.com/ljUg1 -- warnings, but it works now
http://ideone.com/Qd0gp -- no errors, no warnings, test run ok
For 1. I used the "original code" as posted by you.
For 2. I used int main(void), declared the function get_number before defining main, added parenthesis in line 20, and added #include <stdlib.h>
For 3. I added return 0; before the final } of main. I also removed the extra output that messed up the ideone interface (it looks better on an interactive interface)
Edit more tests needed to complete the task of correcting the original code

Resources