Function in C not returning proper value - c

I'm trying to check whether an array is sorted without using a loop. It's working properly, i,e. if I have an array with elements that are in ascending order, the printf executes, since I get "Sorted." But
printf("Array 1 returns: %d \n\n", sortCheck(arr1, SORTED1));
returns 0? Why is this?
Thanks. Here's the entire code.
#include<stdio.h>
const int SORTED1 = 5;
int sortCheck (int arr[], int arrSize);
int indexCounter = 0;
int main()
{
int arr1[] = {1,2,3,4,5};
printf("Array 1: \n");
printf("Array 1 returns: %d \n\n", sortCheck(arr1, SORTED1));
indexCounter = 0;
return 0;
}
int sortCheck(int arr[], int arrSize)
{
if ( (arr[indexCounter]==arr[arrSize-1]) && (indexCounter==arrSize-1) )
{
printf("Sorted. \n");
return 1;
}
if ( arr[indexCounter] <= arr[indexCounter+1] )
{
indexCounter++;
sortCheck(arr, arrSize);
}
else
{
printf("Not sorted.");
return 0;
}
}

You are seeing undefined behavior due to a missing return statement.
if ( arr[indexCounter] <= arr[indexCounter+1] )
{
indexCounter++;
// Problem. Missing return.
sortCheck(arr, arrSize);
}
Change the offending line to:
return sortCheck(arr, arrSize);

Following changes should print value 1
int sortCheck(int arr[], int arrSize)
{
int val = 0;
if ( (arr[indexCounter]==arr[arrSize-1]) && (indexCounter==arrSize-1) )
{
printf("Sorted. \n");
return 1;
}
if ( arr[indexCounter] <= arr[indexCounter+1] )
{
indexCounter++;
val = sortCheck(arr, arrSize);
return val;
}
else
{
printf("Not sorted.");
return 0;
}
}

the sortCheck() function does not check if the array is sorted.
there are two reasons for this.
1) when the recursive call was invoked, the returned value is being ignored, so the information about a particular byte pair is lost.
2) the index (arrSize) is always passed, rather than the offset to the current byte index
I.E. the whole sortCheck() function needs to be re-designed.
Using a debugger (or a printf( of the parameters) in the path that calls the recursive sortCheck() would have revealed that fact.

Related

Why is my code for binary search not working? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 14 days ago.
Improve this question
The code doesn't print the position of elements at the far left or right positions. I've looked at it for hours please help me find out whats wrong.
type here
#include<stdio.h>
#define max 50
void binarysearch(int l,int r,int key,int num[])
{
int mid=(l+r)/2;
if(num[mid]==key)
{
printf("Element found at location %d",mid+1);return;
}
else if(num[mid]<key)
{
return binarysearch(l,mid-1,key,num);
}
else
{
return binarysearch(mid+1,r,key,num);
}
printf("Element not found ");return;
}
int main()
{
int i,key,size,num[max];
printf("Enter size of array : ");scanf("%d",&size);
for(i=0;i<size;i++)
{
printf("Enter the element : ");scanf("%d",&num[i]);fflush(stdin);
}
printf("Enter key to search : ");scanf("%d",&key);
binarysearch(0,size-1,key,num);
return 0;
}
I'm gonna go insane. Send help
For starters you need to check within the function whether r is not less than l. Without this check the function can invoke undefined behavior.
These if statements are incorrect
else if(num[mid]<key)
{
return binarysearch(l,mid-1,key,num);
}
else
{
return binarysearch(mid+1,r,key,num);
}
For example if num[mid] is less than key then you need to call the function recursively like
return binarysearch(mid+1, r, key,num);
otherwise like
return binarysearch(1, mid-1,key,num);
Pay attention to that the function should not output any message. It should returns to the caller either the index of the found element or for example -1 if the searched value is not found in the array. It is the caller of the function that will decide whether to output a message.
It would be much better to declare the function at least like
int binarysearch( const int num[], int size, int key );
or like
int * binarysearch( const int num[], size_t size, int key );
For the last declaration the function returns a pointer to the found element or NULL.
Here is a demonstration program that shows the function implemengtation.
#include <stdio.h>
int * binarysearch( const int a[], size_t n, int key )
{
if (n == 0)
{
return NULL;
}
else if (a[n / 2] < key)
{
return ( int * )binarysearch( a + n / 2 + 1, n - n / 2 - 1, key );
}
else if ( key < a[n / 2] )
{
return ( int * )binarysearch( a, n / 2, key );
}
else
{
return ( int * )a + n / 2;
}
}
int main( void )
{
int a[] = { 1, 3, 5 };
const size_t N = sizeof( a ) / sizeof( *a );
for (int key = 0; key < a[N - 1] + 2; ++key)
{
int *p = binarysearch( a, N, key );
if (p != NULL)
{
printf( "The value %d is found at position %td.\n", key, p - a );
}
else
{
printf( "The value %d is not found.\n", key );
}
}
}
The program output is
The value 0 is not found.
The value 1 is found at position 0.
The value 2 is not found.
The value 3 is found at position 1.
The value 4 is not found.
The value 5 is found at position 2.
The value 6 is not found.
Pay also attention to that this call in your program
fflush(stdin);
has undefined behavior.
You've simply wrote the code in opposite places.
The right code would be:
#include<stdio.h>
#define max 50
void binarysearch(int l,int r,int key,int num[])
{
int mid=(l+r)/2;
if(num[mid]==key)
{
printf("Element found at location %d",mid+1);return;
}
else if(num[mid]<key)
{
// Wrong Code
// you've done the opposite operation
//return binarysearch(l,mid-1,key,num);
// Correct Code
return binarysearch(mid+1,r,key,num);
}
else
{
// Wrong Code
// same problem as before.. you've done opposite operation
//return binarysearch(mid+1,r,key,num);
// Correct Code
return binarysearch(l,mid-1,key,num);
}
printf("Element not found ");return;
}
int main()
{
int i,key,size,num[max];
printf("Enter size of array : ");scanf("%d",&size);
for(i=0;i<size;i++)
{
printf("Enter the element : ");scanf("%d",&num[i]);fflush(stdin);
}
printf("Enter key to search : ");scanf("%d",&key);
binarysearch(0,size-1,key,num);
return 0;
}
Hope this would help.
There are two problems:
1- Your arguments about the recursive called functions are wrong.
2- The recursive call is infinite.
You should change your binarysearch function to this:
void binarysearch(int l, int r, int key, int num[])
{
int mid=(l+r)/2;
if(l > r)
{
printf("Element not found");
return;
}
if(num[mid] == key)
{
printf("Element found at location %d", mid+1);
return;
}
if(num[mid] < key)
{
return binarysearch(mid+1, r, key, num);
}
return binarysearch(l, mid-1, key, num);
}

Program that computes the nth element of a number series given by a formula

Write a method/function with name cpSeries that computes the nth element in a series of numbers, given by the formula: a(n) = (a(n-1))2+a(n-2) when: n>1 and assuming that: a(1)=1, a(0)=0 Note that indexing of the series starts from 0.
I have already written the above code but it runs for an infinite time and I don't know how to fix it in order to compute the nth element.
Any ideas? I have to use only functions to solve this problem.
# include <stdio.h>
int cpSeries(int n)
{
int Nthterm = 0;
int i;
if (n==0) {
cpSeries(0) == 0;
}
else if (n==1) {
cpSeries(1) == 1;
}
for (i=0; i<=n; i++){
Nthterm = cpSeries((n-1))*cpSeries((n-1)) + cpSeries((n-2));
return Nthterm;
}
}
int main()
{
int n=6;
printf("The Nth term of the series is: %d",cpSeries(n));
}
If the provided equation gives you the nth element, I don't see the need for a loop.
Also, in the if conditions, you are calling the function again, but what you should do is return the value you need.
int cpSeries(int n){
int Nthterm;
if (n==0){
Nthterm = 0;
}
else if (n==1){
Nthterm = 1;
}
else {
Nthterm = cpSeries((n-1))*cpSeries((n-1)) + cpSeries((n-2));
}
return Nthterm;
}
Your final conditions just call the function another time instead of returning 0 or 1.
instead of
if (n==0) {
cpSeries(0) == 0;
}
else if (n==1) {
cpSeries(1) == 1;
}
use
if (n==0) {
return 0;
}
else if (n==1) {
return 1;
}
C is not a declarative language where you can specify the return value y of a function f given an argument x by writing something like f(x) = y, but you have to use a return statement.
Change cpSeries(0) == 0; to
return 0;
to avoid the infinite recursion (and the same for n == 1).

C Recursive Collatz Conjecture only till the value is smaller than the original integer

I'm writing an recursion method to calculate collatz conjecture for a sequence of positive integers. However, instead of stopping the calculation when the value reaches 1, I need it to stop when the value become smaller than or equal to the original value. I can't figure out what condition I should put in the if statement.
int collatz (int n) {
printf("%d%s", n, " ");
if(n > collatz(n)) { // here I would get an error saying all path leads to the method itself
return n;
}
else {
if(n % 2 == 0) {
return collatz(n / 2);
}
else {
return collatz((3 * n) + 1);
}
}
}
I used two more parameters:
startValue, to pass through the recursive calls the initial value and
notFirstTime, to check if it is the first call (and not a recursive call). In this case a value n <= startValue is allowed.
Here the code:
int collatz (int startValue, int n, int notFirstTime){
printf("%d%s ", n, " ");
if(n <= startValue && !notFirstTime)
{ // here I would get an error saying all path
//leads to the method itself
return n;
}
else
{
if ( n%2==0 )
{
collatz(startValue, n/2, 0);
}
else
{
collatz(startValue, (3*n)+1, 0);
}
}
}
int main() {
int x = 27;
int firstTime = 1;
int test = collatz(x,x, firstTime);
printf("\nLast value: %d\n", test);
return 0;
}
Please note that I removed two return statements from the recursive calls.

Checking array for identical numbers and their value

As part of a program that I have to make, one of the function that I need to program should check if the array has any identical numbers that are the same, and if one of them is bigger/equals to a given number.
The given number is also the amount of numbers in the array
This is what I have so far:
int checkarray(int *arr, int num)
{
int check = num;
int check2 = num;
int *lor;
int *poi;
int *another;
another = arr;
lor = arr;
poi = arr;
int check3 = num;
for ( ; num > 1; num--) {
for ( ; check3 >= 0; check3--) {
if (*arr == *poi)
return 0;
poi++;
}
arr++;
poi = another;
}
for ( ; check2 > 0; check2--) {
if (*lor >= check)
return 0;
lor++;
}
return 1;
}
I know that I made too many pointers/int for the function, but that's not the problem..
The part of checking for a given value works fine if I'm not mistaken so I think you can ignore that part (that's the last 'for' loop)
I know it should be easy but for some reason I just can't get it to work...
Edit:
I'll give an example: If the array is 0 1 2 3 1 the function will return 0, cause the second and the last number are identical. The function will also return 0 if the given number is 5, and one of the numbers is bigger or equals to 5, for example 0 1 2 5 4.
Otherwise, the function returns 1.
I create a new array where I'm going to save the numbers so I can check if you have a repeat number in the array. I also have one more argument in the function to know the size of the array.
#include <stdio.h>
#include <stdlib.h>
int checkArray(int *arr, int size, int number){
int i,j;
int *countArray = calloc(size,sizeof(int));
for(i=0;i<size;i++){
if(arr[i]>=number){ //Check >= number
free(countArray);
return 0;
}
for(j=0;j<i;j++){ //Check repeat number
if(countArray[j]==arr[i]){
free(countArray);
return 0;
}
}
countArray[j]=arr[i]; //no repeat number so we save it.
}
free(countArray);
return -1; //Error
}
int main(){
int arr[6] = {0,8,2,3,4,1};
printf("Result %d",checkArray(arr,6,5));
}
I hope this can help you.
Update without new array
int checkArray(int *arr, int size, int number){
int i,j;
for(i=0;i<size;i++){
if(arr[i]>=number){
return 0;
}
for(j=0;j<i;j++){
if(arr[i]==arr[j]){
return 0;
}
}
}
return -1; //Error
}
Change your upper for loop to:
for ( ; num > 0; num--) {
if(arr[i]>=number){
return 0;
}
int check3 = num;
poi=arr+1;
for ( ; check3 > 0; check3--) {
if (*arr == *poi)
return 0;
poi++;
}
arr++;
}
and remove the bottom one.
The mistakes here are as following:
1- You need to change the lines:
int check3 = num;
for ( ; num > 1; num--) {
to be:
for ( ; num > 1; num --) {
int check3 = check; // Move to inside loop to reset each time for a fresh inner loop and use check instead of num to reset the value
2- You need to change the line:
for ( ; check3 >= 0; check3--) {
To be
for ( ; check3 > 0; check3--) { // Because `>=0` means attempting to read past the array
3- poi should be initialised every time in the loop as arr+1 to skip comparing the same member of the array to itself, and to skip re-comparing members more than one time.
I suggest re-writing the method with better code style to enable easier detection of such errors and typos

Input line freezing, segmentation fault

I'm working on a project for a class and have been stuck for quite a while. When I unit tested the input earlier, it accepted the values for numOfDataSets and createDataSets without error. Now, however, after typing in any set of values for createDataSets, the code freezes after the first input until I enter any character (such as 1 or a), then errors with a segmentation fault. I am not sure what went wrong, and I would appreciate any help.
#include <stdio.h>
#include <stdlib.h>
// Function to return the number of data sets the user wants.
int numOfDataSets(void) {
int ret;
printf("Enter number of data sets: ");
scanf("%d", &ret);
return ret;
}
// Function that creates the data sets in the input arrays.
void createDataSets(float **inputArr, int inputLength, int *lengths) {
int i = 0, j, k;
float value, *currentSet;
// For every element in inputArr...
while (i < inputLength) {
printf("Enter the number of values in this data set, followed by the values: ");
scanf("%d", &j);
*(lengths + i) = j;
currentSet = (float*)calloc(j, sizeof(float));
k = 0;
while (k < j-1) {
scanf("%f", &value);
*(currentSet + k) = value;
k++;
}
scanf("%f", &value);
*(currentSet + j - 1) = value;
*(inputArr + i) = (float*)&currentSet;
i++;
}
}
// Function to get int value of data set to choose.
int chooseDataSet(void) {
int ret;
printf("Enter the number of the data set on which you wish to do calculations: ");
scanf("%d", &ret);
ret = ret - 1;
return ret;
}
// Gets the number option of the operation that the user wants to do.
int getOption(void) {
int ret;
printf("Enter one of the following numbers:\n");
printf("1. Find the minimum value.\n");
printf("2. Find the maximum value.\n");
printf("3. Calculate the sum of all the values.\n");
printf("4. Calculate the average of all the values.\n");
printf("5. Sort the values in ascending order (i.e., from smallest to largest).\n");
printf("6. Select a different data set.\n");
printf("7. Exit the program.\n");
scanf("%d", &ret);
return ret;
}
// Function to find the minimum value of a dataset.
void minimum(float *ptr, int length) {
int i = 1;
float min;
min = *(ptr);
while (i < length) {
if (*(ptr + i) < min) {
min = *(ptr + i);
}
i++;
}
printf("The minimum value of the set is: %d\n", min);
}
// Function to find the maximum value of a dataset.
void maximum(float *ptr, int length) {
int i = 1;
float max;
max = *(ptr);
while (i < length) {
if (*(ptr + i) > max) {
max = *(ptr + i);
}
i++;
}
printf("The maximum value of the set is: %d\n", max);
}
// Function to find the sum of the values of a dataset.
void sum(float *ptr, int length) {
int i = 1;
float sum;
sum = *(ptr);
while (i < length) {
sum = sum + *(ptr + i);
i++;
}
printf("The sum of the set is: %d\n", sum);
}
// Function to find the average of the values of a dataset.
void average(float *ptr, int length) {
int i = 1;
float sum;
sum = *(ptr);
while (i < length) {
sum = sum + *(ptr + i);
i++;
}
sum = sum / length;
printf("The average of the set is: %d\n", sum);
}
// Function to sort the values of a dataset.
void sort(float *ptr, int length) {
int i = 1, j;
float temp;
while (i < length) {
j = i;
while ((j > 0) && (*(ptr + j - 1) > *(ptr + j))) {
temp = *(ptr + j);
*(ptr + j) = *(ptr + j - 1);
*(ptr + j - 1) = temp;
j--;
}
i++;
}
printf("The sorted array is: ");
i = 0;
while (i < length) {
printf("%f\t", *(ptr + i));
i++;
}
printf("\n");
}
// Main method...
int main(void) {
int *lengths, outerLength, userChoiceSet = 0, userChoiceOption = 0, breakOutterLoop = 0;
float **outer;
outerLength = numOfDataSets();
outer = (float**)calloc(outerLength, sizeof(float*));
lengths = (int*)calloc(outerLength, sizeof(int));
createDataSets(outer, outerLength, lengths);
while (breakOutterLoop == 0) {
userChoiceSet = chooseDataSet();
while ((userChoiceOption != 6) || (userChoiceOption != 7)) {
userChoiceOption = getOption();
switch (userChoiceOption)
{
case 1:
minimum(*(outer + userChoiceSet), *(lengths + userChoiceSet));
break;
case 2:
maximum(*(outer + userChoiceSet), *(lengths + userChoiceSet));
break;
case 3:
sum(*(outer + userChoiceSet), *(lengths + userChoiceSet));
break;
case 4:
average(*(outer + userChoiceSet), *(lengths + userChoiceSet));
break;
case 5:
sort(*(outer + userChoiceSet), *(lengths + userChoiceSet));
break;
case 7:
breakOutterLoop = 1;
default:
break;
}
}
}
return (0);
}
The type of input to expect from the user would be something like:
2
3 1.2 2.3 3.4
4 4.5 5.6 6.7 7.8
Your main problem is this, in createDataSets():
*(inputArr + i) = (float*)&currentSet;
What this actually does is assign the address of currentSet to each element of inputArr. This address doesn't change on each iteration, so each element of inputArr gets set to the exact same value. Moreover, this address refers to a variable local to createDataSets() which will be destroyed when that function returns, so the address will be invalid. All the arrays you're dynamically creating are just being discarded, because you're not storing the addresses.
What you should have is:
inputArr[i] = currentSet;
As you mention in the comments, your compiler warned you about this, because what you were doing was trying to store a float ** in a float *, which is rarely a good idea. By adding the cast you silenced the warning, but you didn't fix the problem it was warning you about. The number of occasions in C where a cast is actually what you want to do are relatively few. None of the casts in your program are either necessary, or wise.
A few other points...
You use the wrong format specifier in many of your printf() calls. The %d here:
printf("The minimum value of the set is: %d\n", min);
for instance, should be an %f, because min is a float.
You are overusing pointer notation which makes your code very difficult to follow. That includes very difficult for you, too. For instance, your minimum() function could be much better written as so:
void minimum(float *ptr, int length) {
float min = ptr[0];
for ( int i = 0; i < length; ++i ) {
if ( ptr[i] < min ) {
min = ptr[i];
}
}
printf("The minimum value of the set is: %f\n", min);
}
Similarly, in your switch statement, something like:
average(*(outer + userChoiceSet), *(lengths + userChoiceSet));
is much more clearly written as:
average(outer[userChoiceSet], lengths[userChoiceSet]);
You are missing a call to fflush(stdout) in a few places, where you prompt for input but do not end the prompt with an '\n'. When I ran this code on my system, the prompt did not show before it sat to wait for the input. Interactive output is line-buffered by default, in C, and if you want things to be predictable, then you need to output a '\n' or call fflush(stdout) when output needs to be displayed.
You would benefit from defining your variables closer to the time of use. Restricting the scope of your variables to the minimum feasible is generally good. For instance, in your main() function, your variable userChoiceSet is never used outside of the outer while loop, so define it inside with:
while (breakOutterLoop == 0) {
int userChoiceSet = chooseDataSet();
You don't check the return from calloc() anywhere - you must do this, because the allocation might fail. malloc() and friends return NULL on failure. There's also no real point using calloc(), here - malloc() would be more normal.
You seem to use while loops in places where for loops would be much more natural.
You haven't done too bad a job with this one, but you'll find writing larger programs easier if you make each function do just one thing. For instance, your minimum() function should just calculate the minimum, but right now it calculates it and prints it. Particularly when it comes to dealing with input in the wrong format (see point 9 below) wrapping this up in a separate function will make the functions that use that input much less cluttered, and it's easy to get a function correct and to visually debug it if it's not doing a bunch of different things at once. Also, your opportunity for reusing code goes up when you do this (e.g. right now you couldn't use that minimum() function at any place where you wanted to calculate the minimum without also printing it).
Overall, having one array for your values, and a second for their lengths, is not a good approach. Far better would be to have an array of structs, each struct having a member for the array, and a member for the length, so the two related pieces of data are packaged together.
Also, your use of scanf() is potentially troublesome. If you enter input that's not expected, your program will not fail gracefully. For instance, if you enter anything other than a number in your main menu, then you'll go into an infinite loop. Generally better is to use fgets() to read in an entire line, and use sscanf() to parse its contents. At a minimum, you should check the return from scanf() to see if it successfully read a value, and if it did not, take appropriate remedial action (like reading all the characters in the input buffer and going back to ask for more input).
Overall, bearing all of the above in mind except for the last two points, your createDataSets() function would be better looking something like this:
void createDataSets(float **inputArr, const int inputLength, int *lengths) {
for ( int i = 0; i < inputLength; ++i ) {
printf("Enter the number of values in this data set, "
"followed by the values: ");
fflush(stdout);
scanf("%d", &lengths[i]);
float * currentSet = malloc(lengths[i] * sizeof *currentSet);
if ( !currentSet ) {
perror("Couldn't allocate memory in createDataSets()");
exit(EXIT_FAILURE);
}
for ( int j = 0; j < lengths[i]; ++j ) {
scanf("%f", &currentSet[j]);
}
inputArr[i] = currentSet;
}
}
Much easier to debug, easier to follow, and easier to not get wrong in the first place.
Since I've got a bit of time on my hands, here's how I'd figure it:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
/* Maximum length of input buffer */
#define MAX_LINE 1024
/* Dataset structure */
struct dataset {
float * data;
size_t length;
};
/* Gets a single integer from user */
int getInteger(const char * prompt)
{
int value;
bool first_try = true;
char buffer[MAX_LINE];
do {
printf("%s%s: ", first_try ? "" : "Try again - ", prompt);
fflush(stdout);
fgets(buffer, MAX_LINE, stdin);
first_try = false;
} while ( sscanf(buffer, "%d", &value) != 1 );
return value;
}
/* Gets a bounded integer from user */
int getBoundedInteger(const char * prompt, const int min, const int max)
{
bool bad_input;
int value;
do {
bad_input = false;
value = getInteger(prompt);
if ( value < min ) {
printf("Too low, try again - ");
bad_input = true;
}
else if ( value > max ) {
printf("Too high, try again - ");
bad_input = true;
}
} while ( bad_input );
return value;
}
/* Gets a list of floats from user - caller must free */
float * getFloats(const char * prompt, const int num)
{
float * values = malloc(num * sizeof *values);
if ( !values ) {
perror("Couldn't allocate memory in getFloats()");
exit(EXIT_FAILURE);
}
bool bad_input = false;
do {
printf("%s%s: ", bad_input ? "Try again - " : "", prompt);
fflush(stdout);
char buffer[MAX_LINE];
fgets(buffer, MAX_LINE, stdin);
char * ptr = buffer;
int num_read = 0;
bad_input = false;
while ( *ptr && num_read < num ) {
/* Skip leading whitespace */
while ( *ptr && isspace(*ptr) ) {
++ptr;
}
/* Get and check input */
char * endptr;
float val = strtof(ptr, &endptr);
if ( ptr == endptr ) {
bad_input = true;
break;
}
/* Advance ptr and store input if good */
ptr = endptr;
values[num_read++] = val;
}
if ( num_read < num ) {
bad_input = true;
}
} while ( bad_input );
return values;
}
/* Returns the number of data sets the user wants. */
int numOfDataSets(void)
{
return getInteger("Enter number of data sets");
}
/* Creates the data sets */
void createDataSets(struct dataset ** sets, const int set_length)
{
for ( int i = 0; i < set_length; ++i ) {
struct dataset * new_set = malloc(sizeof *new_set);
if ( !new_set ) {
perror("Couldn't allocate memory for dataset");
exit(EXIT_FAILURE);
}
new_set->length = getInteger("Enter number of values in set");
new_set->data = getFloats("Enter values", new_set->length);
sets[i] = new_set;
}
}
/* Gets the number of data set to choose */
int chooseDataSet(const int min, const int max)
{
return getBoundedInteger("Choose data set", min, max) - 1;
}
/* Gets a menu choice from the user */
int getOption(void)
{
printf("Enter one of the following numbers:\n");
printf("1. Find the minimum value\n");
printf("2. Find the maximum value\n");
printf("3. Calculate the sum of all the values\n");
printf("4. Calculate the average of all the values\n");
printf("5. Sort the values in ascending order\n");
printf("6. Output the data set\n");
printf("7. Select a different data set\n");
printf("8. Exit the program\n");
return getInteger("Choose option");
}
/* Returns the minimum value in a data set */
float minimum(const struct dataset * set)
{
float min = set->data[0];
for ( size_t i = 0; i < set->length; ++i ) {
if ( set->data[i] < min ) {
min = set->data[i];
}
}
return min;
}
/* Returns the maximum value in a data set */
float maximum(const struct dataset * set)
{
float max = set->data[0];
for ( size_t i = 0; i < set->length; ++i ) {
if ( set->data[i] > max ) {
max = set->data[i];
}
}
return max;
}
/* Returns the sum of the data in a dataset */
float sum(const struct dataset * set)
{
float sum = 0;
for ( size_t i = 0; i < set->length; ++i) {
sum += set->data[i];
}
return sum;
}
/* Returns the arithmetic average of the data in a dataset */
float average(const struct dataset * set)
{
float sum = 0;
for ( size_t i = 0; i < set->length; ++i ) {
sum += set->data[i];
}
return set->length > 0 ? sum / set->length : sum;
}
/* Sorts the elements of a dataset in place */
void sort(struct dataset * set)
{
for ( size_t i = 0; i < set->length; ++i ) {
for ( size_t j = i; j && set->data[j-1] > set->data[j]; --j ) {
float temp = set->data[j];
set->data[j] = set->data[j-1];
set->data[j-1] = temp;
}
}
}
/* Prints a dataset */
void print_set(const struct dataset * set) {
for ( size_t i = 0; i < set->length; ++i ) {
printf("%.4f ", set->data[i]);
}
putchar('\n');
}
/* Main function */
int main(void)
{
/* Get and initialize sets */
const int num_sets = numOfDataSets();
struct dataset ** sets = malloc(num_sets * sizeof *sets);
if ( !sets ) {
perror("Couldn't allocate memory for sets");
return EXIT_FAILURE;
}
createDataSets(sets, num_sets);
/* Main menu */
int chosen_set = chooseDataSet(1, num_sets);
bool keep_going = true;
while ( keep_going ) {
switch ( getOption() )
{
case 1:
printf("Minimum value is %f\n\n",
minimum(sets[chosen_set]));
break;
case 2:
printf("Maximum value is %f\n\n",
maximum(sets[chosen_set]));
break;
case 3:
printf("Sum of values is %f\n\n",
sum(sets[chosen_set]));
break;
case 4:
printf("Average of values is %f\n\n",
average(sets[chosen_set]));
break;
case 5:
sort(sets[chosen_set]);
break;
case 6:
print_set(sets[chosen_set]);
break;
case 7:
chosen_set = chooseDataSet(1, num_sets);
break;
case 8:
keep_going = false;
break;
default:
break;
}
}
/* Free memory for sets */
for ( int i = 0; i < num_sets; ++i ) {
free(sets[i]->data);
free(sets[i]);
}
free(sets);
return 0;
}

Resources