Averaging 3 integers - c

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

Related

Store doubles in an array in C

I really need help to store double values in a double array. I am trying using scanf_s and it works. But if I try to input more than 4 values, my program crashes and returns me the error code 3
I actually need a dynamic array, but as I was getting too many errors with that, I changed and I'm trying to use a common array, just so I can get at least some marks for this project.
This is the code I am using now...
int main()
{
printf("Enter white-space separated real numbers. Terminate input with ^Z\n");
//get the dynamic array
double numSet[1000] = { 0 };
int size = 0;
double number;
while (scanf_s("%lf", &number) == 1)
{
numSet[size] = number;
size++;
}
//sort the array using qsort
//range of the array
double min = numSet[0];
double max = numSet[size - 1];
//get the mean
double sum = 0.0;
for (size_t i = 0; i < size; i++)
{
sum += numSet[i];
}
double mean = sum / size;
printf("Range: [%.2f ... %.2f]\n", min, max);
printf("Arithmetic mean is: %f", mean);
}
I have two problems:
Is a warning about buffer overrun:
Warning C6385 Reading invalid data from 'numSet':
the readable size is '8000' bytes, but '-8' bytes may be read.
When I try to input more than 4 numbers, my program crashes and returns the code 3
while (scanf_s("%lf", &number) == 1)
{
numSet[size] = number;
size++;
}
instead of this use
while (scanf_s("%lf", &number) == 1 && size <= 1000)
{
numSet[size] = number;
size++;
}
Your loop goes infinitely because it has no termination character.
scanf_s only reads value from keyboard and has another parameter to set its maximum input buffer value which is useful to limit your input.
What you can do is either read size from the user before letting him enter values or you can ask every time if the user wants to add more values to the array or not.
for example:
char option = 'Y';
while ( (scanf_s("%lf", &number) == 1 && option == 'Y'){
// code to enter a new number
printf("Do you want to add more numbers? (Y/N) ");
scanf("%c", &option);
}
Also, the scanf_s function returns the number of values scanned and every time is 1 as you are always taking one double value.
So even if you remove it, it wont be of much trouble.
I think the problem is how you end the input loop, scanf_s isn't needed, please see the watch window. I simply change the end condition to some no digit char.
Code::Blocks watch window
As mentioned in the comments, it's possible for
double max = numSet[size - 1];
to evaluate as
double max = numSet[-1];
when size = 0. I'm guessing that a double is 8 bytes wide, so the compiler warns that it could try to read -1 * 8 = -8 bytes from memory.

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.

Error when using array elements in conditional statements in C

I have done my fair share of studying the C language and came across this inconsistency for which I cannot account. I have searched everywhere and reviewed all data type definition and relational syntax, but it is beyond me.
From the book C How to Program, there is a question to make a binary to decimal converter where the input must be 5-digits. I developed the follow code to take in a number and, through division and remainder operations, split it into individual digits and assign each to an element in of an array. The trouble arises when I try to verify that the number entered was indeed binary by checking each array element to see whether it is a 1 or 0.
Here is the code:
#include <stdio.h>
int power (int x, int y); //prototype
int main(void)
{
int temp, bin[5], test;
int n=4, num=0;
//get input
printf("%s","Enter a 5-digit binary number: ");
scanf("%d", &temp);
//initialize array
while(n>=0){
bin[n]=temp/power(10,n);
temp %= power(10,n);
n--; }
//verify binary input
for (test=4; test>=0; test--){
if ((bin[n]!=0)&&(bin[n]!=1)){
printf("Error. Number entered is not binary.\n");
return 0; }
//convert to decimal
while(n<=4){
num+=bin[n]*power(2,n);
n++; }
printf("\n%s%d\n","The decimal equivalent of the number you entered is ",num);
return 0;
}
//function definition
int power(int x, int y)
{
int n, temp=x;
if(y==0) return 1;
for(n=1; n<y; n++){
temp*=x; }
return temp;
}
Could someone explain to me why regardless of input (whether: 00000, or 12345), I always get the error message? Everything else seems to work fine.
Thank you for your help.
Update: If the if statement is moved to the while loop before. This should still work right?
Update2: Never mind, I noticed my mistake. Moving the if statement to the while repetition before does work given the solution supplied by sps and Kunal Tyagi.
After this
while(n>=0){
bin[n]=temp/power(10,n);
temp %= power(10,n);
n--; }
n is set as -1 so when you try to convert to decimal the statement bin[n] is actually bin[-1] so it returns you error.
One issue is that, while checking if the number is binary or not, you are returning at wrong place. You need to return only if the number is not binary. But you are returning outside the if condition. So your program returns no matter what the input is.
for (test=4; test>=0; test--){
if ((bin[test]!=0)&&(bin[test]!=1))
printf("Error, numbered entered was not binary.\n");
// Issue here, you are returning outside if
return 0; } //exit program
You can change that to:
for (test=4; test>=0; test--){
if ((bin[test]!=0)&&(bin[test]!=1)) {
printf("Error, numbered entered was not binary.\n");
// Return inside the if
return 0; // exit program
}
}
There is one more issue. Before you convert your number to decimal, you need to set n = 0;
//convert to decimal
n = 0; /* need to set n to zero, because by now
n will be -1.
And initially when n is -1, accessing
bin[-1] will result in undefined behavior
*/
while(n<=4){
num+=bin[n]*power(2,n);
n++; }
This looks like a homework, but your issue is in the brackets. More specifically line 23. That line is not part of the logical if statement despite the indentation (since that doesn't matter in C).
No matter what, the program will exit on test=4 after checking the condition.
Solution:
if ((bin[test]!=0)&&(bin[test]!=1)) { // << this brace
printf("Error, number entered was not binary.\n");
return 0; } } //exit program // notice 2 braces here

C - Can't stop program using while and logical operator

I'm just starting learning C but I really don't know what am I doing wrong. I wrote this code, and it was supposed to stop reading numbers when it receives a negative number. I have wasted a lot of time trying to figure out what it is wrong, and I still don't know what it is.
#include<stdio.h>
int main(){
const int qtd = 3;
float ent[qtd];
int i = qtd;
printf("Digite os numeros\n");
do{
scanf("%f", &ent[i]);
i--;
}while (ent[i] >= 0 && i >= 1);
printf("\n\n\n\nPressione 'Enter' para sair");
fflush(stdin);
getchar();
return 0;
}
The problem is with the index of ent that you check for being negative. It's ent[i], but it is after i has been decremented, so you are reading the location that has not been written yet by scanf.
To fix the problem, change the code to use the prior location, i.e.
do {
...
} while (ent[i+1] >= 0 && ...);
There are several other problems with your code, all coming from the assumption that array indexes start at 1. In C, however, the initial index is zero, not one, so the correct check should be
do {
...
} while (ent[i+1] >= 0 && i >= 0);
In addition, i should be initialized to int i = qtd-1; to avoid writing past the end of allocated array.

Issues by the redefinition of a macro in C

I want to change the value of a macro during the run of the program, for that I've wrote this example :
#include <stdio.h>
#define MAX (65535 *0.5)
int main ( ){
float amp = 0.0;
float temp = 0.0 ;
temp = MAX ;
char c;
while (1){
printf(" MAX value %.2d.%.3d \n ", (short)temp,(short)(temp*1000));
scanf("%c",&c);
if( c =='x') {
#undef MAX
#define MAX (65535 +amp);
amp+= 0.1;
temp = MAX;
}
}
return 0 ; }
I've got two problems :
1. the printf doessn't show the values as hoped, for instand 19.211, it always
-32768.-32768
2. I don't see any change of the value of the macro.
any idea what I'm doing wrong here ?
You can only define macros at compile time. The c preprocessor replaces every occurrance of a macro before actual compilation happens, with gcc you can see what code was generated after preprocessing by using the -E switch, if you try it experimenting with different macros, you may get to understand the preprocessor a little better, read the link to understand more.
This
if( c =='x') {
#undef MAX
#define MAX (65535 +amp);
amp+= 0.1;
temp = MAX;
}
does not do what you think.
If you execute the preprocessor on the source code, then what will actually happen is that the snippet above will be compiled as
if( c =='x') {
amp+= 0.1;
temp = MAX;
}
so as you can see, it doesn't do what you think.
Also, this is not related to the macro redefinition issue, but your code has a bug that can make it enter an infinite loop, this
scanf("%c",&c);
will keep scanning the '\n' that is left in the stdin after pressing Enter/Return, so you need to explicitly ignore that character by adding a white space before the specifier like this
scanf(" %c", &c);
/* ^ white space goes here */
Note: another answer has suggested that you are using the incorrect data type and suggested a solution, you should take a look at it, since in fact it seems your program has an integer overflow issue.
Let's run your file through the C preprocessor (CPP) manually. The result is
int main ( ) {
float amp = 0.0;
float temp = 0.0 ;
temp = (65535 *0.5) ;
char c;
while (1) {
printf(" MAX value %.2d.%.3d \n ", (short)temp,(short)(temp*1000));
scanf("%c",&c);
if( c =='x') {
amp+= 0.1;
temp = (65535 +amp);;
}
}
return 0 ;
}
Macros are evaluated before the compiler even sees your source code. You cannot change the value of a macro based on a decision taken at runtime.
Why not instead use a variable float max = ... and change that one's value depending on user input?
Macros are resolved during compilation, so during program execution there is no such thing like MAX - each occurence was already replaced by its value (65535).
However, if you need to define local constant (local in terms of translation unit), why not use static variable?
static unsigned int MAX = 65535;
And then:
if (c == 'x')
{
MAX = 65535 + amp;
//...
}
You are using too short data type and printing the fractional part incorrectly. Consider doing this:
double i;
printf(" MAX value %.2d.%.3d \n ", (int)temp,(int)(modf(temp,&i)*1000));
...instead of this:
printf(" MAX value %.2d.%.3d \n ", (short)temp,(short)(temp*1000));
Be sure to #include <math.h> if using modf.
Your redefinition of the MAX macro looks strange to me, though. Macros are defined at compile time, not at run time, so most of the time you don't want to redefine macros.
Note also that
scanf("%c",&c);
will read the newline as a separate character, so you want to do instead:
scanf(" %c",&c);
...to consume whitespace. Do consider checking also for the EOF (end-of-file) condition; currently you don't do that.

Resources