I am creating a program that calculates the average for a bunch of numbers. The first input is the number of values, and the second output is/are the numbers. For example, with the inputs of the following, I would get the outputs afterward.

5
10 20 30 40 50
Average of 5 values is 30.00
7
15 20 40 50 60 40 50
Average of 7 values is 39.29

I want to make the program more robust so that it will only read integer values. If I were to enter the following, this would be the ouput that I want.

garbage
10 20 whatever 40 50
Error! Can't read number of expected values.

or

5
10 20 30 40 50
Average of 5 values is 30.00
6
50 70 whatever 40 60
Error! Can't read expected value #2.
Average of 2 values is 60.00

Here's my program so far:

/* Read in a number of values to read and then print the average
* of those values.
*/

#include <stdio.h>

int main()
{
/* Declare variables */
int expected;
int count;
double sum;
int value;

/* While the input (number of values) is not equal to end of file */
while (scanf("%d", &expected) != EOF)
{

/* Initializee sum at 0 */
sum = 0;

/* Initialize count at 0 */
/* While the count is less than the expected count (input),
increase count by one */
for (count = 0; count < expected; count++)
{
/* Read input of values for the average */
scanf("%d", &value);

/* Sum is equal to previous sum increased by value */
sum += value;
}

/* Print average of all values */
printf("Average of %d values is %.2f\n",
count, count != 0 ? sum / count : 0.0);

if (expected < 0 || expected == getchar())
{
printf("Error!  Can't read number of expected values.");
}
}
}

I want to print an error if a character or number less than 0 is entered (for the expected value of inputs). My program compiles, but this is just not working out. Any suggestions please?

4
Contributors
10
Replies
12
Views
8 Years
Discussion Span
Last Post by Aia

The way to accomplish this task is to input everything as string. Then check the string character by character to make sure there are no bad chars entered. Then convert each value in the string to integers.

The way to accomplish this task is to input everything as string. Then check the string character by character to make sure there are no bad chars entered. Then convert each value in the string to integers.

I followed your suggestion, but now I have another problem.

Here is the my current code:

/* Read in a number of values to read and then print the average
*  *  * of those values.
*   *   */

#include <stdio.h>
#define DEBUG
#include "tfdef.h"

int IS_DIGIT(char c);

int main()
{
/* Declare variables */
int expected[10];
int count;
double sum;
int value;
char input[10] = " ";
int i = 0;
int digit;

#ifdef DEBUG
printf("debug: Enter expected number value of inputs: ");
#endif

scanf("%s", &input);

#ifdef DEBUG
printf("debug: The expected number value is %s\n", input);
#endif

/* For i is initially 0, increase i by one for every
character in input string */
for(i; input[i]; i++)
{
/* Call function to determine if character is a digit */
digit = IS_DIGIT(input[i]);

/* Test return value */
if (digit == FALSE)
{
printf("not a digit\n");
}
else
{
printf("is a digit\n");
}
}
if (digit == FALSE)
{
printf("final: not a digit\n");
}
else
{
printf("final: is a digit\n");
}

if (digit == TRUE)
{
/* While the input (number of values) is not equal to end of file */
while (scanf("%s", &input) != EOF)
{

/* Initializee sum at 0 */
sum = 0;

/* Initialize count at 0
While the count is less than the expected count (input),
increase count by one */
for (count = 0; count < expected ; count++)
{
#ifdef DEBUG
printf("Enter values for average: ");
#endif

/* Read input of values for the average */
scanf("%d", &value);

/* Sum is equal to previous sum increased by value */
sum += value;
}

/* Print average of all values */
printf("Average of %d values is %.2f\n",
count, count != 0 ? sum / count : 0.0);

}
}
}

/* Functions */
int IS_DIGIT(char c)
{
if ((c) >= '0' && (c) <= '9')
{
return TRUE;
}
else
{
return FALSE;
}
}

At line 70, I am getting the following compile error:
test2.c: In function ‘main’:
test2.c:70: warning: comparison between pointer and integer

I realize that I declared expected as an int, and that I need expected to equal input. But, input is a char. How can I go about converting all character values in the string into an integer in its binary form?

actually, I discovered a way to convert a character to integer.

Here's my most current code:

/* Read in a number of values to read and then print the average
* of those values.
*/
#include <stdlib.h>
#include <stdio.h>
#include "tfdef.h"
#define DEBUG

int IS_DIGIT(char c);

int main()
{
/* Declare variables */
int expected;
int count;
double sum;
int value;
char input[10] = " ";
int i = 0;
int digit;

#ifdef DEBUG
printf("debug: Enter expected number value of inputs: ");
#endif

scanf("%s", &input);

#ifdef DEBUG
printf("debug: The expected number value is %s\n", input);
#endif

/* For i is initially 0, increase i by one for every
character in input string */
for(i; input[i]; i++)
{
/* Call function to determine if character is a digit */
digit = IS_DIGIT(input[i]);

/* Convert string input to integer */
expected = atoi (input);

#ifdef DEBUG
printf("debug: The integer form of the input: %d\n", expected);
#endif

/* If the input is not a digit, it is a letter */
if (digit == FALSE)
{
#ifdef DEBUG
printf("debug: Input is not a digit\n");
#endif
}

/* If the input is a digit */
else
{
#ifdef DEBUG
printf("debug: Input is a digit\n");
#endif
}
}

/* Check for last value of string */

/* If the input is not a digit, it is a letter */
if (digit == FALSE)
{
#ifdef DEBUG
printf("debug: Final value on line: not a digit\n");
#endif
}

/* If the input is a digit */
else
{
#ifdef DEBUG
printf("debug: Final value on line: is a digit\n");
#endif
}

/* While the input (number of values) is not equal to end of file */
while (scanf("%d", &expected) != EOF)
{

/* Initializee sum at 0 */
sum = 0;

/* Initialize count at 0
While the count is less than the expected count (input),
increase count by one */
for (count = 0; count < expected ; count++)
{
#ifdef DEBUG
printf("debug: Enter values for average: ");
#endif

/* Read input of values for the average */
scanf("%d", &value);

/* Sum is equal to previous sum increased by value */
sum += value;
}

/* Print average of all values */
printf("Average of %d values is %.2f\n",
count, count != 0 ? sum / count : 0.0);

}

if (digit == FALSE)
{
printf("Error!  Can't read number of expected values.\n");
}
}

/* Functions */

int IS_DIGIT(char c)
{
if ((c) >= '0' && (c) <= '9')
{
return TRUE;
}
else
{
return FALSE;
}
}

I think I may almost be done. But there seem to be something wrong in the last while loop. Does anyone know what I did wrong?

Do not use scanf() to read strings. Here's why.

So how are you going to check for letters when you left all the other inputs to read integers only? They will still cause problems.

Do not use scanf() to read strings. Here's why.

So how are you going to check for letters when you left all the other inputs to read integers only? They will still cause problems.

so would I use something like fgets instead?

Edited by tquiva: n/a

so would I use something like fgets instead?

Didn't the link offer a replacement?

I replaced my scanf with an fgets and this is what I got:

/* Read in a number of values to read and then print the average
* of those values.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "tfdef.h"
#define DEBUG

int IS_DIGIT(char c);
/* Given  : character
* Returns: TRUE if digit, FALSE otherwise
*/

int main(void)
{
/* Declare variables */
int expected;
int count;
float sum;
int value;
char input[10] = " ";
int i = 0;
int digit;

/* Prompt user for expected number of inputs for desired avg */
#ifdef DEBUG
printf("debug: Enter expected number value of inputs: ");
#endif

while (fgets(input, 10, stdin) != NULL)
{

#ifdef DEBUG
printf("debug: The expected number value is %s\n", input);
#endif

/* For i is initially 0, increase i by one for every
character in input string */
for(i; input[i]; i++)
{
/* Call function to determine if character is a digit */
digit = IS_DIGIT(input[i]);

/* Convert string input to integer (binary) */
expected = atoi (input);

#ifdef DEBUG
printf("debug: The integer form of the input: %d\n", expected);
#endif

/* If the input is not a digit, it is a letter */
if (digit == FALSE)
{
#ifdef DEBUG
printf("debug: Input is not a digit\n");
#endif
}

/* If the input is a digit */
else
{
#ifdef DEBUG
printf("debug: Input is a digit\n");
#endif
}
}

/* Check for last value of string */

/* If the input is not a digit, it is a letter */
if (digit == FALSE)
{
#ifdef DEBUG
printf("debug: Final value on line: not a digit\n");
#endif
}

/* If the input is a digit */
else
{
#ifdef DEBUG
printf("debug: Final value on line: is a digit\n");
#endif
}

/* Initializee sum at 0 */
sum = 0;

/* Initialize count at 0
While the count is less than the expected count (input),
increase count by one */
for (count = 0; count < expected; count++)

{
#ifdef DEBUG
printf("debug: Enter values for average: ");
#endif

/* Read input of values for the average */
scanf("%d", &value);

/* Sum is equal to previous sum increased by value */
sum += value;

}

/* Print average result of all values */
printf("Average of %d values is %.2f\n", count, count != 0 ? sum / count : 0.0);

/* If the last character is not a digit, print an error */
if (digit == FALSE)
{
printf("Error!  Can't read number of expected values.\n");
}

/* Update loop */
#ifdef DEBUG
printf("debug: Enter expected number value of inputs: ");
#endif
}
}

/* Functions */

int IS_DIGIT(char c)
/* Given  : character
* Returns: TRUE if digit, FALSE otherwise
*/
{
if ((c) >= '0' && (c) <= '9')
{
return TRUE;
}
else
{
return FALSE;
}
}

It compiled fine, but my debug statements were different compared to my code with a scanf. The results were not correct. Did I code my fgets incorrectly or am I better off with scanf? My assignment is almost due and I am so frustrated... could anyone please help me?

For the second scanf, I plan to change it to read a string once I get the first one to work.

Edited by tquiva: n/a

I replaced my scanf with an fgets and this is what I got:

--snipped---

It compiled fine, but my debug statements were different compared to my code with a scanf. The results were not correct. Did I code my fgets incorrectly or am I better off with scanf? My assignment is almost due and I am so frustrated... could anyone please help me?

For the second scanf, I plan to change it to read a string once I get the first one to work.

I'm not psychic. I don't know what's different, don't know what's not correct, nor how. You have to explain since you are the only one that knows.

No, you are not better off with scanf()

look, heres a quick-and-dirty way to get an integer from input, using fgets().

char buffer[32];
int number;

do {
printf("enter integer : ");
fflush(stdout);                         // needed because no newline char
fgets(buffer, sizeof(buffer), stdin);   // get string input
number = atoi(buffer);                  // converts integer found in string
if (number == 0)                        // if no conversion was made
printf("Invalid Input!  ");          // then print warning and repeat
} while (number != 0);

printf("you entered the number '%d'\n", number);

this does very minimal error checking and will not accept the value of zero (0). It just ignores any non-numeric characters after a valid value. If you enter more than 31 characters you will have problems with extra characters remaining in the input buffer.

i personally do not like using "atoi()" and i would prefer a robust method using "strtol()" and full error checking, but you've got enough issues to deal with at the moment.

so it will do for now.

Edited by jephthah: n/a

scanf("%s", &input);

scanf("%s", input); (notice that there's no &) does not add the new line representing the ENTER/RETURN key. Therefore, the string obtained into input never contains a '\n'.
On the other hand

fgets(input, sizeof input, stdin);

starts reading until it reaches one less than the sizeof input or the ENTER key (newline), whichever is first.
The ENTER key is stored as well as a new line breaker if it is read before the buffer is full.

You are facing that problem. There are diverse ways of dealing with that. One of them.

#include <string.h>

if (fgets(input, sizeof input, stdin)) {
/* length of input without '\0' */
size_t length = strlen (input);

/* is the newline present? */
if (input[length -1] == '\n') {
/* remove newline */
input[length -1] = '\0';
}
}

Edited by Aia: n/a

This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.