I've this difficult assignment where I only have to use for loop.. so we're not allowed to use while or do.. while loop also else statement.. am trying to take the user input until he/she input EOF, so that the program will return the average number. So I wrote the code and ran it but whenever I enter ctrl+z (EOF) the program wont stop or even return the average values :(
for (int i = 0; i < 50; i++) {
printf("Please enter employee rank: ");
scanf("%d", &newnum);
sumavg += newnum;
counter++;
avg = sumavg / counter;
if (newnum < 8) {
summ += newnum;
ccoun++;
avgle = summ / ccoun;
}
}
printf("the avg : %d", avg);
printf("\nthe avg : %d \n", avgle);
So, I updated the code and there is a minor problem here.. idk why the program don't respond from the first time I enter EOF..
for (int i = 0; i < BN; i++) {
printf("Please enter employee rank: ");
result = scanf("%d", &newnum);
if (result == EOF)
break;
sumavg += newnum;
counter++;
avg = sumavg / counter;
if (newnum < 8) {
summ += newnum;
ccoun++;
avgle = summ / ccoun;
}
You can just check the return value of scanf(). From the scanf() manual,
The value EOF is returned if the end of input is reached before
either the first successful conversion or a matching failure
occurs. EOF is also returned if a read error occurs, in which
case the error indicator for the stream (see ferror(3)) is set,
and errno is set to indicate the error.
#include <stdio.h>
int main(void)
{
int newNum[50];
for (int i = 0; i < 50; i++)
{
int ret = scanf("%d", &newNum[i]);
if (ret != 1) /* 1 int to read */
{
if (ret == EOF)
{
/* input error might also have occured here, check errno to be sure */
break;
}
}
/* code */
}
return 0;
}
or directly in the for loop,
for (int i = 0; i < ARRAY_SIZE && scanf("%d", &newNum[i]) == 1; i++)
{
/* code */
}
scanf("%d", &foo) doesn't store EOF in foo on end of file. But you are allready checking for EOF when doing scanf, use that to break your loop.
for(....)
{
if(scanf(...) != EOF)
{
....
}
else
{
break;
}
}
The code above has only a minor problem, it does detect IO errors and end of file, but not parse errors. It would be better to write something like this:
for(int i=0; ...)
{
int n;
int err;
err = scanf("%d", &n);
if ( err == 1)
{
/* Process input */
newnum[i] = n;
}
else if (err == EOF && ferror(stdin))
{
/* IO error */
perror ("Failure to read from standard input");
exit(EXIT_FAILURE);
}
else if (err == EOF)
break;
else
{
/* Handle parse errors */
}
}
Naturally you have to fit error handling to your needs.
When I need EOF from stdin I run program as bellow.
./a.out <<DATA
1
2
3
4
5
6
7
8
9
10
DATA
This works fine on Linux. Not sure how is works on other platform
Related
I have an integer 'n' that is responsible for amount of numbers to enter later on.
I need to check for any incorrect inputs here.
The first scanf for 'n' works fine, but the second has some flaws.
The case is following:
n = 3 (e.g.) - doesn't matter
Then I want to scanf: 1 2 3 4
It will be scanned first 3 values but I need to throw out an error.
Same goes with: 1 2 3.5 - (last number is float but it still reads 3)
and with a char: 1 2 3g
if (scanf("%d", n) == 1 && getchar() == '\n') {
if (n > NMAX || n < 0) {
error = 1;
return;
}
for (int i = 0; i < n; i++) {
if (scanf("%d", p) == 1) {
The ONLY correct input is the exact same amount of integer numbers (equals to 'n') to scan in a for loop.
UPD: I can use only <stdio.h> library as well as only scanf.
Create a helper function to read an int and validate it.
The key is that to validate input, form a helper function that you can improve as needed, like using fgets() rather than scanf() once the poor "only scanf" requirement is removed.
// Sample
// Return 1 on success
// Return EOF on end-of-file
// Else return 0
int read_int(int *i, int min, int max, int line) {
long long num;
int result = scan("%18lld", &num); // Accept many out of int range input
if (result == EOF) return result; // or if (result < 0)
if (line) {
// consume the rest of the line
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) {
if (!isspace(ch)) { // or `ch != ' ' && `ch != '\t' && ...
result == 0;
}
}
}
if (result == 1) {
if (num < min || num > max) {
return 0;
}
*i = (int) num;
}
return result;
}
Sample usage
if (read_int(&n, 0, NMAX, 1) != 1) {
error = 1;
return;
}
for (int i = 0; i < n; i++) {
if (read_int(&p, INT_MIN, INT_MAX, i + 1 == n) != 1) {
error = 1;
return;
}
...
Note: read_int() does not catch all errors, just many of them. Easy enough to improve, once all OP's limitations and goals are known.
Try using scansets with scanf. %1[\n] will scan up to one character that is a newline. %99[ \t] will scan up to 99 characters that are space or tab. If the character is not a newline, space or tab, it is replaced in the input stream.
If scanf with %d can't scan an int, it will return 0. scanf could also return EOF.
fgets and parse with strtol or others is the better solution.
#include <stdio.h>
int main ( void) {
char space[100] = "";
char newline[2] = "";
int number = 0;
int count = 0;
int quantity = 3;
printf ( "enter %d integers\n", quantity);
while ( 1) {
if ( 1 == scanf ( "%d", &number)) {
++count;
}
else {
printf ( "could not parse an integer\n");
break;
}
scanf ( "%99[ \t]", space);
if ( 1 == scanf ( "%1[\n]", newline)) {
if ( count == quantity) {
printf ( "scanned %d integers\n", quantity);
break;
}
else if ( count > quantity) {
printf ( "too many integers\n");
break;
}
else printf ( "enter another integer\n");
}
}
return 0;
}
Check if this works
while(n-1)
{
scanf("%d ",p);
n-=1;
}
scanf("%d",p);
//After this you can scan again to check if there is anything extra in input
//and throw error accordingly
writing a program that will be finding min, max, avg of values entered by user. Having trouble writing something that will check to make sure there are only postive integers entered and produce an error message. heres my for statement that is reading the input so far:
for (int value = 0; value <= numofvals; ++value) {
printf("Value %d: %f\n", value, val_input);
scanf("%f", &val_input);
}
mind you I've been learning code for about 3 weeks and was just introduced to loops this week so my understanding is rudimentary at best!
First, don't use scanf. If stdin doesn't match what it expects it will leave it in the buffer and just keep rereading the same wrong input. It's very frustrating to debug.
const int max_values = 10;
for (int i = 0; i <= max_values; i++) {
int value;
if( scanf("%d", &value) == 1 ) {
printf("Got %d\n", value);
}
else {
fprintf(stderr, "I don't recognize that as a number.\n");
}
}
Watch what happens when you feed it something that isn't a number. It just keeps trying to read the bad line over and over again.
$ ./test
1
Got 1
2
Got 2
3
Got 3
foo
I don't recognize that as a number.
I don't recognize that as a number.
I don't recognize that as a number.
I don't recognize that as a number.
I don't recognize that as a number.
I don't recognize that as a number.
I don't recognize that as a number.
I don't recognize that as a number.
Instead, use fgets to reliably read the whole line and sscanf to parse it. %f is for floats, decimal numbers. Use %d to recognize only integers. Then check if it's positive.
#include <stdio.h>
int main() {
const size_t max_values = 10;
int values[max_values];
char buf[1024];
size_t i = 0;
while(
// Keep reading until we have enough values.
(i < max_values) &&
// Read the line, but stop if there's no more input.
(fgets(buf, sizeof(buf), stdin) != NULL)
) {
int value;
// Parse the line as an integer.
// If it doesn't parse, tell the user and skip to the next line.
if( sscanf(buf, "%d", &value) != 1 ) {
fprintf(stderr, "I don't recognize that as a number.\n");
continue;
}
// Check if it's a positive integer.
// If it isn't, tell the user and skip to the next line.
if( value < 0 ) {
fprintf(stderr, "Only positive integers, please.\n");
continue;
}
// We got this far, it must be a positive integer!
// Assign it and increment our position in the array.
values[i] = value;
i++;
}
// Print the array.
for( i = 0; i < max_values; i++ ) {
printf("%d\n", values[i]);
}
}
Note that because the user might input bad values we can't use a simple for loop. Instead we loop until either we've read enough valid values, or there's no more input.
Something easy like this may work for you:
int n;
int ret;
for (;;) {
ret = scanf("%d", &n);
if (ret == EOF)
break;
if (ret != 1) {
puts("Not an integer");
for (;;)
if (getchar() == '\n')
break;
continue;
}
if (n < 0) {
puts("Not a positive integer");
continue;
}
printf("Correct value %d\n", n);
/* Do your min/max/avg calculation */
}
/* Print your results here */
This is just an example and assumes you do not need to read floating point numbers and then check if they are integers, as well as a few other things. But for starters, it is simple and you can work on top of it.
To break out of the loop, you need to pass EOF (typically Ctrl+D in Linux/macOS terminals, Ctrl+Z in Windows ones).
An easy and portable solution
#include <limits.h>
#include <stdio.h>
int get_positive_number() {
char buff[1024];
int value, ch;
while (1) {
printf("Enter positive number: ");
if (fgets(buff, 1023, stdin) == NULL) {
printf("Incorrect Input\n");
// Portable way to empty input buffer
while ((ch = getchar()) != '\n' && ch != EOF)
;
continue;
}
if (sscanf(buff, "%d", &value) != 1 || value < 0) {
printf("Please enter a valid input\n");
} else {
break;
}
}
return value;
}
void solution() {
// Handling malformed input
// Memory Efficient (without using array to store values)
int n;
int min = INT_MAX;
int max = INT_MIN;
double avg = 0;
printf("Enter number of elements: ");
scanf("%d", &n);
getc(stdin);
int value;
for (int i = 0; i < n; i++) {
value = get_positive_number();
if (value > 0) {
if (min > value) {
min = value;
}
if (max < value) {
max = value;
}
avg += value;
}
}
avg = avg / n;
printf("Min = %d\nMax = %d\nAverage = %lf\n", min, max, avg);
}
int main() {
solution();
return 0;
}
Output:
Enter number of elements: 3
Enter positive number: 1
Enter positive number: 2
Enter positive number: a
Please enter a valid input
Enter positive number: -1
Please enter a valid input
Enter positive number: 1
Min = 1
Max = 2
Average = 1.333333
Yes, hello. I'm really new to programming. I genuinely need help because I would like to both understand what I'm doing wrong and also pass my class.
I'm in a Intro to Programming class and my assignment is to create a program that uses an array to store percentage grades in the range from 0 to 100 (inclusive). The program should allow the user to indicate when they are done entering grades. When the user is done entering grades, the program should print out the grades entered.
I have a running code, compiled in Code::Blocks. But my questions/problems are:
A.) What's the best way to tell C when the user is done? Should I
Leave the code as is and let any key be hit?
Add a specific variable like 'done'?
Do something else?
B.) How do I print only the grades that have been entered without it going through all 100 slots? I can't for the life of me find the solution.
Any and all suggestions welcome and appreciated!!!
int i = 0;
float percentScore[100];
for (i = 0; i < 10; i++) {
printf("Grade %d: ", i + 1);
scanf("%f", &percentScore[i]);
}
for (i = 0; i < 10; i++) {
printf("\n%.2f%%", percentScore[i]);
}
return 0;
Your choices for A) are not mutually exclusive; the first is something the user can do, the second is a way to represent that in the code. As such, you could reasonably do both.
As for B), you need a way to represent the number of grades entered (hint: a variable); this can then be used to control how many get printed.
Here is a simple approach for your problem:
for each input, read a full line from the user ;
try and convert this line as a number with sscanf() ;
if the conversion fails, consider the input exhausted ;
if the value is out of bounds, restart this input.
The user can thus signal the end of the list by entering a blank line.
Here is a example:
#include <stdio.h>
#define GRADE_NB 100
int main(void) {
int i, n;
float grade, percentScore[GRADE_NB];
char buf[100];
for (n = 0; n < GRADE_NB;) {
printf("Grade %d: ", n + 1);
if (!fgets(buf, sizeof buf, stdin)) {
/* end of file reached: input exhausted */
break;
}
if (sscanf(buf, "%f", &grade) != 1) {
/* not a number: input exhausted */
break;
}
if (grade >= 0 && grade <= 100) {
/* value is OK, grade accepted */
percentScore[n] = grade;
n++;
} else {
printf("Invalid grade: %f\n", grade);
}
}
for (i = 0; i < n; i++) {
printf("%.2f%%\n", percentScore[i]);
}
return 0;
}
If the potential number of inputs is not limited, you must allocate the array from the heap and reallocate it as more inputs are gathered. Here is a simple solution for this where the array is reallocated for each input:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int i, n;
float grade, *percentScore;
char buf[100];
for (n = 0, percentScore = NULL;;) {
printf("Grade %d: ", n + 1);
if (!fgets(buf, sizeof buf, stdin)) {
/* end of file reached: input exhausted */
break;
}
if (sscanf(buf, "%f", &grade) != 1) {
/* not a number: input exhausted */
break;
}
if (grade >= 0 && grade <= 100) {
/* value is OK, grade accepted */
percentScore = realloc(percentScore, (n + 1) * sizeof(*percentScore));
if (percentScore == NULL) {
printf("allocation failed\n");
return 1;
}
percentScore[n] = grade;
n++;
} else {
printf("Invalid grade: %f\n", grade);
}
}
for (i = 0; i < n; i++) {
printf("%.2f%%\n", percentScore[i]);
}
free(percentScore);
return 0;
}
Does anybody see the error I seem to miss? It just continues to print 0.00 without stopping not sure why its doing. It was working earlier and I didn't make any changes to the while that would affect it so I'm really confused.
`
int main (int argc, const char * argv[])
{
int i, j, numStudents;
double total, average, difference, lessThan, greater, exchange;
total = 0;
while (scanf("%1d", &numStudents) != EOF)
{
/* Ends program at zero */
if (!numStudents)
{
return 0;
}
double amountSpent[numStudents];
total = 0;
greater = 0;
lessThan = 0;
for(i = 0; i < numStudents; i++)
{
scanf("%1lf\n", &amountSpent[i]);
total += amountSpent[i];
}
/* cleans total, than calculates */
average = total/numStudents;
exchange = 0;
for(i = 0; i < numStudents; i++)
{
difference = amountSpent[i] - average;
if (difference < 0)
{
lessThan += difference;
}
else
{
greater += difference;
}
}
/* if (-lessThan > greater)
{
exchange = -lessThan;
}
else
{
exchange = greater;
}
*/
exchange = (-lessThan > greater)? -lessThan : greater;
printf("$%.2f\n", exchange);
}
return 0;
}
`
User input is confused without prompts and use of the scanf() trailing '\n'. Else code does work although some ideas may help.
Strange to limit input numeric input to 1 character, - recommend dropping the 1 before the specifier.
Also test against == 1 rather than != EOF to cope with non-numeric input.
// while (scanf("%1d", &numStudents) != EOF)
while (puts("Enter students (0 to quit)", scanf("%d", &numStudents) == 1)
Good idea to check results of user input. Drop the scanf() trailing '\n'
// scanf("%1lf\n", &amountSpent[i]);
puts("Enter amount spent");
if (1 != scanf("%lf", &amountSpent[i])) {
return 1;
}
I need scanf to read numbers, including the number which is entered just before EOF (no space or enter after putting this number, just EOF - like "1 2 3 4EOF" - 4 is not read). My code looks like this:
for (i = 0; i < 100; i++)
{
if ((scanf ("%d", &number) != 1 && !feof(stdin)))
{
printf ("Wrong input.\n");
return (0);
}
if (feof(stdin) && count == 0)
{
printf("Empty input.\n");
return 0;
}
if (feof(stdin)) break;
field[i] = number;
count++;
}
Where is the part which needs to be adjusted to accept also the last entered number not separated before EOF? Thanks a lot, I really can't see it..
It is the if (feof(stdin)) break; that does the damage. You should only break on EOF if you do not get 1 from scanf(). In your example, the system knows it has reached EOF, but it also successfully converted a value, and it told you so by returning 1 from scanf(), but you went ahead and ignored the successfully converted value because EOF was also detected.
You should probably use:
#include <stdio.h>
int main(void)
{
int field[100];
int count = 0;
int n;
for (int i = 0; i < 100; i++)
{
int number;
if ((n = scanf("%d", &number)) != 1)
break;
printf("-- %d: %d (%d)\n", i, number, n);
field[i] = number;
count++;
}
if (n == 0)
{
printf("Wrong input.\n");
return 1;
}
else if (ferror(stdin))
{
printf("I/O error on stdin\n");
return 1;
}
else if (feof(stdin) && count == 0)
{
printf("Empty input.\n");
return 1;
}
printf("Count: %d\n", count);
for (int j = 0; j < count; j++)
printf("%d: %d\n", j, field[j]);
return 0;
}
check !feof(stdin) right at the end of the loop. It will be true after you have read the last value, so in this case the last value is not stored
After successfully reading the last number via scanf ("%d"..., calling feof() may return true or false, depending on if additional white space, like \n follows the number. Thus feof() is not a definitive test to stop looping. Simpler code is possible.
In general, avoid using fscanf() and feof() in the same parsing routine. Instead use the return value from fscanf() to know when EOF occurred.
while ((retval = fscanf(...)) == expected value) {
// The happy path
do_stuff();
}
if (retval == EOF) {
Deal_with_EOF_or_IOerror();
}
else {
Deal_with_unexpected_number_of_parameters_scanned();
}