I'm trying to learn some C, but it's a pain.
I have this task: 'Write a C program to determine the minmum and maximum of a sequence of integer numbers on input, terminged by the string "done".' Very simple task, just like the input:
5
2
9
done
However the output is wrong, and I can't figure it out. I would very much appreciate some help. Thx!
The code:
#include <stdio.h>
#include <string.h>
int main() {
char line[1000];
int val, min = 10, max = -1;
while ( 1 ) {
scanf("%d", &val);
if (val < min) min = val;
if (val > max) max = val;
scanf("%4s", line);
if (strcmp("done", line) == 0) break;
}
printf("Maximum %d\n", max);
printf("Minimum %d", min);
}
Both of the environments I tested the code in will output Max 9, Min 5.
Can someone explain what is going on?
According to the while loop
while ( 1 ) {
scanf("%d", &val);
if (val < min) min = val;
if (val > max) max = val;
scanf("%4s", line);
if (strcmp("done", line) == 0) break;
}
you have to enter a string after each input of a number.
So the second number 2 is considered as an input of a string.
Also integer numbers can be negative less than -1 or positive greater than 10. So this declaration
int val, min = 10, max = -1;
does not make sense.
Instead you can read all numbers in a character array and then to use for example the function atoi to convert the entered string to a number.
For example a simple program can look like
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( void )
{
char line[16];
int min = 0, max = 0;
int empty = 1;
while ( scanf( "%15s", line ) == 1 && strcmp( line, "done" ) != 0 )
{
int val = atoi( line );
if ( empty )
{
min = val;
max = val;
empty = 0;
}
else if ( max < val )
{
max = val;
}
else if ( val < min )
{
min = val;
}
}
if ( empty )
{
puts( "The sequence of numbers is empty." );
}
else
{
printf( "Maximum %d\n", max );
printf( "Minimum %d\n", min );
}
}
You will need to enter the string "done" only once to break the loop. In all other cases you will need to enter only integer numbers.
Related
I am having an issue with the output of my code, which is trying to return an array backwards in c using pointers. Do you guys have any solutions to the error I am getting?
Sample input:
Please enter the array size: 3
Please enter 3 elements:
4, 5, 7
Segmentation fault (core dumped)
Code:
#include <stdio.h>
int main(void){
int size, i;
int *pointer;
int arr[size];
printf("Please enter the array size: ");
scanf("%d/n", &size);
pointer = &arr[0];
printf("Please enter %d elements: \n", size);
for(i = 0; i < size; i++){
scanf("%d", arr[i]);
pointer++;
}
pointer = &arr[size - 1];
printf("The reversed array is \n");
for(i = size; i > 0; i--){
printf("%d", arr[i]);
pointer--;
}
return 0;
}
The task is not simple for beginners like you and me.
As I have understood the user can enter any number of integers in one line and all entered integers in the line must be outputted like
You entered 2
In this case neither array nor character array nor integer array will help. And in fact you need not to define an array if you want only to output numbers stored in the input buffer.
In this case you can just use the standard function getchar. Using the function in a loop you can read all numbers placed by the user in one line in the I/O buffer.
Here is a sample program. It is a little complicated because I allow the user to enter sign symbols.
There is no check in the program whether the user entered not a digit or a sign. You can develop the program further. The program demonstrates an approach to solve the task.
#include <stdio.h>
#include <ctype.h>
int main( void )
{
const int Base = 10;
printf( "Enter a seria of integer numbers in one line: " );
int c;
int sign = 0;
int num = 0;
do
{
c = getchar();
if (c == EOF || c == '\n' )
{
if (sign)
{
printf( "You entered %d\n", num );
}
}
else if (isblank( ( unsigned char )c ))
{
if (sign)
{
printf( "You entered %d\n", num );
sign = 0;
num = 0;
}
}
else
{
if (c == '-' || c == '+')
{
if (sign)
{
printf( "You entered %d\n", num );
num = 0;
}
sign = c == '-' ? -1 : 1;
}
else if (isdigit( ( unsigned char )c ))
{
c -= '0';
if (sign == 0) sign = 1;
if (sign == 1)
{
num = Base * num + c;
}
else
{
num = Base * num - c;
}
}
}
} while (c != EOF && c != '\n');
}
The program output might look for example like
Enter a seria of integer numbers in one line: 1 -1 +12-12+13 +14 -15
You entered 1
You entered -1
You entered 12
You entered -12
You entered 13
You entered 14
You entered -15
If you want to enter several lines of numbers and output numbers that are present in each line then the program can look the following way
#include <stdio.h>
#include <ctype.h>
int main( void )
{
const int Base = 10;
size_t i = 0;
while (1)
{
printf( "Enter a seria of integer numbers in one line (or press just Enter to exit): " );
int c = getchar();
if (c == EOF || c == '\n') break;
ungetc( c, stdin );
printf( "Line %zu contains the following numbers:\n", i++ );
int sign = 0;
int num = 0;
do
{
c = getchar();
if (c == EOF || c == '\n')
{
if (sign)
{
printf( "You entered %d\n", num );
}
}
else if (isblank( ( unsigned char )c ))
{
if (sign)
{
printf( "You entered %d\n", num );
sign = 0;
num = 0;
}
}
else
{
if (c == '-' || c == '+')
{
if (sign)
{
printf( "You entered %d\n", num );
num = 0;
}
sign = c == '-' ? -1 : 1;
}
else if (isdigit( ( unsigned char )c ))
{
c -= '0';
if (sign == 0) sign = 1;
if (sign == 1)
{
num = Base * num + c;
}
else
{
num = Base * num - c;
}
}
}
} while (c != EOF && c != '\n');
putchar( '\n' );
}
}
The program output might look for example like
Enter a seria of integer numbers in one line (or press just Enter to exit): 1 -2 3 +4
Line 0 contains the following numbers:
You entered 1
You entered -2
You entered 3
You entered 4
Enter a seria of integer numbers in one line (or press just Enter to exit): 11-12 13+14
Line 1 contains the following numbers:
You entered 11
You entered -12
You entered 13
You entered 14
Enter a seria of integer numbers in one line (or press just Enter to exit):
As the program just outputs entered numbers then actually there is no need to build an object of the type int like
num = Base * num + c;
You could just output adjacent digits in a line.
int array[100];
int n;
scanf("%d", &n);
for(int i=0; i<n; i++) {
scanf("%d", &array[i]);
}
for(int i=0; i<n; i++) {
printf("You entered %d \n", array[i]);
}
We use the array to get all of the values, and just print them out at the end.
In C and C++ it does not matter if the values are separated by space or a newline, so you can get every integer in a single line if separated by spaces.
output
3
1 2 3
You entered 1
You entered 2
You entered 3
C makes this very easy, but you need to leverage some library functions. At the most simple:
use fgets() and strpbrk() to obtain and verify a line of text
use strtok() and strtol() to parse and verify integer values.
What you do with those values is up to you. Following your example prompt, let’s just print them.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int error( const char * message, const char * value )
{
fprintf( stderr, "%s%s\n", message, value );
return 1;
}
int main()
{
printf( "Input: " );
// Get all input on a single line
char text[1000];
fgets( text, sizeof(text), stdin );
// Verify that the entire line of input was obtained
char * nl = strpbrk( text, "\r\n" );
if (!nl) return error( "Line too long!", "" );
*nl = '\0';
puts( "Output:" );
// For each whitespace-delimited (spaces, tabs) token in the line:
for (char * token = strtok( text, " \t" ); token; token = strtok( NULL, " \t" ))
{
// Attempt to convert it to an integer
char * nok;
int n = strtol( token, &nok, 10 );
if (*nok) return error( "Invalid integer value: ", token );
// Success!
printf( "You entered %d\n", n );
}
return 0;
}
Notice also how it is OK to create a little helper function (error()). You can make helpers as complex or simple as you need. For this helper, all we need was to complain with one or two strings and return an “error happened” exit code that main() can pass right to the shell.
fgets can be used to read a line.
strtol can parse integers and report overflow and invalid input.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
int parselint ( char *line, int *value, char **end) {
long int number = 0;
errno = 0;
number = strtol ( line, end, 10);
if ( *end == line) {// nothing was parsed. no digits
size_t span = strcspn ( *end, "-+0123456789"); // characters to next int
if ( ! span) {
span = 1;
}
fprintf ( stderr, "problem parsing: %.*s\n", (int)span, line);
*end += span; // advance pointer to next int
return 0;// return failure
}
if ( ( errno == ERANGE && ( number == LONG_MAX || number == LONG_MIN))
|| ( errno != 0 && number == 0)) {// parsing error from strtol
fprintf ( stderr, "problem %.*s", (int)(*end - line), line);
perror ( " ");
return 0;
}
if ( number > INT_MAX || number < INT_MIN) {
fprintf ( stderr, "problem %.*s ", (int)(*end - line), line);
fprintf ( stderr, "out of int range\n");
return 0;
}
*value = number;//assign number to pointer
return 1;//success
}
int main ( void) {
char line[4096] = "";
char *parse = line;
int number = 0;
fgets ( line, sizeof line, stdin);
line[strcspn ( line, "\r\n")] = 0; // remove newline
while ( *parse) {
if ( 1 == parselint ( parse, &number, &parse)) {
printf ( "you entered %d\n", number);
}
}
return 0;
}
Is there any way to define a variable for example that only accepts one values from 1 to 100?
If the user try to assign a value that is out of this interval the program signs an error.
I'm not looking for an algorithm of input control, like this:
#include <stdio.h>
int main ( ) {
int n ;
printf("give an interger number between 1 and 100 : ");
scanf("%d",&n);
while ( n < 1 || n > 100 )
{
printf("given value is wrong\ngive a new value between 1 and 100 : ");
scanf("%d",&n);
}
return 0 ;
}
Is there any way to define a variable for example that only accepts one values from 1 to 100?
No, not directly.
Alternative, form a struct and provide get and set functions. Information hiding. User can only set the variable using functions.
struct a1to100;
bool a1to100_set(struct a1to100 *a, val); // Return error flag.
int a1to100_read(struct a1to100 *a); // Return 1 on success, EOF on end-of-file
int a1to100_get(const struct a1to100 *a); // Return value
struct a1to100 *a1to100_create(void);
void a1to100_free(struct a1to100 *a);
Or create a helper function to read an int sub-range. Sample:
int read_int_subrange(int min, int max, int value_on_eof) {
char buf[100];
printf("Give an integer number between %d and %d : ", min, max);
while (fgets(buf, sizeof buf, stdin)) {
char *endptr;
errno = 0;
long val = strtol(buf, &endptr, 0);
if (endptr > buf && *endptr == '\n' && errno == 0 && val >= min && val <= max) {
return (int) val;
}
printf("Given value is wrong\nGive a new value between %d and %d :\n",
min, max);
}
return value_on_eof;
}
I am currently taking programming classes this semester and at the moment we are using C language to program.
For this program it has to find the highest even integer among the values entered by the user. It stops asking values when a value less than 1 has been entered. If there is no even integer it should display "NO ODD INTEGER
at the moment this is what I have
#include<stdio.h>
#include<stdlib.h>
#define MAXNUMBERS 5
int find_maximum(int[], int);
int main()
{
int c, array[MAXNUMBERS], location, maximum, amount_numbers;
clrscr();
amount_numbers = getNumbers(array);
printf("Highest odd integer: ");
for (c = 0 ; c < MAXNUMBERS ; c++)
{
location = find_maximum(array, MAXNUMBERS);
maximum = array[location];
}
printf("%d", maximum);
getch();
}
int find_maximum(int a[], int n) {
int c, max, index;
max = a[0];
index = 0;
for(c = 1 ; c < n ; c++) {
if(a[c] > max && a[c] %1==1) {
index = c;
max = a[c];
}
}
return index;
}
int getNumbers(int arr[])
{
int c;
int n = 0;
printf("You may enter a max. %d numbers, enter a number less than 1 to end.\n", MAXNUMBERS);
for(c = 0 ; c < MAXNUMBERS ; c++)
{
scanf("%d", &arr[c]);
fflush(stdin);
n++;
if(arr[c] < 1)
{
break;
}
}
return n;
}
*Problem has been fixed question can be closed or deleted because of unecessary question
I suggest this approach :
int main()
{
int c, array[MAXNUMBERS], maximum, amount_numbers;
clrscr();
getNumbers(array);
location = find_maximum(array, MAXNUMBERS);
if (location == -1 )
printf("No Even integer");
else {
maximum = array[location];
printf("Highest even integer :%d", maximum);
}
getch();
}
int find_maximum(int a[], int n) {
int c, max, index;
max = -10000; // A very low number
index = -1; // shows that no even integer is found yet.
for(c = 1 ; c < n ; c++) {
if(a[c] > max && a[c] %2 == 0) {
index = c;
max = a[c];
}
}
return index;
}
int getNumbers(int arr[])
{
int c;
printf("You may enter a max. %d numbers, enter a number less than 1 to end.\n", MAXNUMBERS);
for(c = 0 ; c < MAXNUMBERS ; c++)
{
scanf("%d", &arr[c]);
fflush(stdin);
if(arr[c] < 1)
{
break;
}
}
}
You should first scan the array from the user which is what getNumbers function does.
Next you need to find the highest even integer which is what find_maximum funciton does.
this function returns index of the highest event integer in your array. the default value is -1 which indicates that no even value is found ! if it's given any other value means that found the highest even integer.
so now that you have the index you check if it's -1(not found) or it's found (returned index).
There is no sense to define an array for a sequence of numbers with undefined size that to determine the maximum value. When a next number is entered you can compare it with the current maximum value provided that the entered number is even.
The program can look the following way
#include <stdio.h>
int main( void )
{
int max = 0;
int value;
printf("Enter a sequence of integer numbers.\n"
"Enter a number less than 1 to end: ");
while (scanf("%d", &value) == 1 && !(value < 1))
{
if (value % 2 == 0 && max < value) max = value;
}
if (max != 0)
{
printf("Highest even integer: %d\n", max);
}
else
{
puts("No even integer");
}
}
As for your program then this loop is wrong.
for (c = 0 ; c < MAXNUMBERS ; c++)
{
location = find_maximum(array, MAXNUMBERS);
maximum = array[location];
}
For starters the number of entered values can be less than MAXNUMBERS. You have to use at least the variable amount_numbers in the condition.
Moreover the loop is not needed Because it does the same that is it calls several times the function find_maximum and nothing is changed with the function result between iterations of the loop. Moreover you have to check whether the variable location gets value 0 and whether the element with this index is less or greater than 1. Otherwise you can show invalid result.
As commented, you are only required to output the answer so there is no need to store the input in an array. This shows how to do it with a simple loop. The program also ends at non-numeric input (effectively a 0 value).
#include <stdio.h>
int main(void) {
int innum = 0;
int maximum = 0;
while(scanf("%d", &innum) == 1 && innum > 0) {
if(innum % 2 == 0 && maximum < innum) {
maximum = innum;
}
}
if(maximum < 2) {
puts("NO EVEN INTEGER");
}
else {
printf("Highest even integer: %d\n", maximum);
}
return 0;
}
Program session:
3 8 1 5 3 4 -5
Highest even integer: 8
I'm trying to create a function that asks the user for a value, which then will be stored as the max or min value entered, or if the user inputs a number < 0, it will exit the dataentry() function, else it will keep asking the user for input.
#include <stdio.h>
#include <string.h>
void dataentry();
int count = 0;
float max, min, mean, old, new;
float data;
char Old[10],Data[10],choice[25];
int main(void)
{
dataentry();
}
void dataentry()
{
printf(" |Enter Wind Speed Value:\n");
printf("**|Enter -1 to exit data entry mode|**\n");
fgets(Old, sizeof(Old), stdin);
sscanf(Old, "%f",&old);
max = old;
min = old;
data = 1;
count = 1;
printf("max=%f, min=%f, data=%f, count=%d.", max, min, data, count);
for (count == 1;data >= 0; count++)
{
printf("\nEnter data value: ");
//fgets(Data, sizeof(Data), stdin); // I commented this out because I got a coredump error with it in
sscanf(Data,"%f", &data);
if (data >= max)
{
max = data;
}
else if (data <= min && data > 0)
{
min = data;
}
}
}
After the program prompts you the first time to enter data, before it reaches the for loop, it works and you enter your value. Then however it goes into an infinite loop printing "Enter data value: " over and over. I used the printf statement that prints out the max, min, data, and count values so I could check that they are being stored and they are, but when the function gets to the for loop it no longer does what I'm trying to do. Thank you in advance, this function is part of a larger program I'm writing but I cut all the irrelevant stuff out.
If you uncomment your fgets() line, it ought to work. Here's a working version, tidied up a little to check the return from the functions that you aren't monitoring, and to improve the logic of your loop:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void dataentry(void);
int count = 0;
float max, min, mean, old, new;
float data;
char Old[10], Data[10], choice[25];
int main(void)
{
dataentry();
}
void dataentry(void)
{
printf(" |Enter Wind Speed Value:\n");
printf("**|Enter -1 to exit data entry mode|**\n");
if ( !fgets(Old, sizeof(Old), stdin) ) {
fprintf(stderr, "No input.\n");
exit(EXIT_FAILURE);
}
if ( sscanf(Old, "%f", &old) != 1 ) {
fprintf(stderr, "Badly formed input, enter a float next time.\n");
exit(EXIT_FAILURE);
}
max = old;
min = old;
data = 1;
count = 1;
printf("max=%f, min=%f, data=%f, count=%d.\n", max, min, data, count);
while (1) {
printf("Enter data value: ");
fflush(stdout);
if ( !fgets(Data, sizeof(Data), stdin) ) {
break;
}
if ( sscanf(Data, "%f", &data) != 1 ) {
fprintf(stderr, "Badly formed input, enter a float next time.\n");
exit(EXIT_FAILURE);
}
if ( data < 0 ) {
break;
}
else {
++count;
}
if ( data >= max ) {
max = data;
} else if ( data <= min ) {
min = data;
}
}
printf("max=%f, min=%f, data=%f, count=%d.\n", max, min, data, count);
}
with sample output:
paul#thoth:~/src/sandbox$ ./ssf
|Enter Wind Speed Value:
**|Enter -1 to exit data entry mode|**
10
max=10.000000, min=10.000000, data=1.000000, count=1.
Enter data value: 11
Enter data value: 12
Enter data value: 9
Enter data value: 8
Enter data value: -1
max=12.000000, min=8.000000, data=-1.000000, count=5.
paul#thoth:~/src/sandbox$
It's pretty bad form to use all those global variables, too. With your current program, at least, you could define every single one of them within dataentry().
I'm having trouble figuring out the loop in the average function. User enters sequence and if the number of numbers in the sequence is greater than 0, output avg of the numbers and repeat for another sequence. If the sequence has no numbers, exit program.
I understand that I'm telling the average function to return 0 when sum = 0 and that's why it exits after the 1st sequence (I think).
Any suggestions as to how to avoid that? Pseudocode if possible!
#include<stdio.h>
#include<stdlib.h>
double average();
int main ()
{
while( average() )
{
}
}//end main
double average()
{
double n, sum = 0;
int count = 0;
printf ( "Enter sequence: " );
while( scanf( "%lf", &n ) )
{
sum += n;
count++;
}
if( sum > 0 )
{
printf( "average is %.2f\n", sum/(double)count );
return 1;
}
else
return 0;
}
}
Here is my output:
Enter sequence: 3 4 5 x
average: 4.00
Enter sequence: Press any key to continue . . .
#include <stdio.h>
#include <stdlib.h>
int average(void);
int main(void)
{
while (average())
;
return 0;
}
int average(void)
{
double n, sum = 0;
int count = 0;
printf("Enter sequence: ");
while (scanf( "%lf", &n ) == 1)
{
sum += n;
count++;
}
int c;
while ((c = getchar()) != EOF && c != '\n')
;
if (sum > 0)
{
printf("average is %.2f\n", sum / count);
return 1;
}
else
return 0;
}
This reads anything on the line up to the newline after a conversion fails, thus setting you up for reading the next sequence. The loop test for scanf() is improved; it will exit on EOF, too. The cast in the division was unnecessary; the compiler has to convert count to double because sum is a double, even without you telling it to do so explicitly. The return type of average() is not a double; it is a boolean, which is classically spelled int. In C99 or later (which the code assumes you have; if you don't, you're stuck on Windows and need to move int c; to the top of the function), then you could #include <stdbool.h> and use a return type of bool and replace return 1; by return true; and replace return 0; by return false;.
I think you can initially get input for the variable named count asking for the user to enter the total no of numbers in sequence,and then get those values in sequence.
And if the count is 0,then exit the program.. else continue finding average.
This is because in your case, you have to enter a non numeric char each time to end the sequence.
Well I ended up with this and its working perfectly:
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
double average();
int main () {
while( average() ) {}
}//end main
double average() {
double n, sum = 0;
int count = 0;
printf ( "Enter sequence: " );
getchar();
while( scanf( "%lf", &n ) ){
sum += n;
count++;
}//end while
if( n > 0 ){
printf( " average: %.2f\n", sum/(double)count );
return 1;
}//end if
else
return 0;
}//end function