C Reading list of numbers into multiple arrays - c

So I am trying to write a program that prompts the user to input how many data sets the user wishes to have, aka how many arrays there are going to be. It then prompts the user to input how many values will be in each data set and what the values are. Finally it gives the user a list of options to run on a desired data set.
When I run my code and select which data set I want to use, it seems to always come up with the last data set and doesn't seem to have all of the values in the set. I was just wondering if someone could let me know what I'm doing wrong or at the very least put me on the right track. I've gone through the code multiple times and can't figure it out.
#include <stdio.h>
int main()
{
unsigned short int num_sets, set_size, set_desired, command = 0;
printf("Enter the number of data sets you would like to store: ");
scanf(" %hu", &num_sets);
int i = 1, j, sets[1][num_sets], sum, a;
while(i <= num_sets)
{
j = 1;
printf("Enter the number of elements in data set %hu: ", i);
scanf(" %hu", &set_size);
printf("Enter the data for set %hu: ", i);
while(j < set_size)
{
scanf(" %d", &sets[i - 1][j - 1]);
j++;
}
i++;
}
printf("Which set would you like to use?: ");
scanf(" %hu", &set_desired);
while(set_desired > num_sets){
printf("There aren't that many data sets, try again: ");
scanf(" %hu", &set_desired);
}
printf("Set #%hu: %hu\n", num_sets, *sets[num_sets - 1]);
while(command != 7){
printf("Choose what you would like to do:\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. Select a different data set.\n");
printf("7. Exit the program.\n");
scanf(" %hu", &command);
if(command == 1){
printf("You picked 1!");
}
if(command == 2){
printf("You picked 2!");
}
if(command == 3){
/*printf("You picked 3!");
for(a = 0; a < set_size; a++){
sum = sum + *sets[a];
}
printf("%d\n", sum);*/
printf("You picked 3!");
}
if(command == 4){
printf("You picked 4!");
}
if(command == 5){
printf("You picked 5!");
}
if(command == 6){
printf("You picked 6!");
}
if(command == 7){
break;
}
}
}

If you are trying to store values in different sets than you need to maintain the number of items in each set separately as you don't know how many elements are there is each set.
The design should be such that:
Set 1 : Number of Elements : Actual values in the array.(Here I am storing the number of items in the set as part of the same array. It will be the first element in each set)
The memory allocation can be done dynamically as you are giving the option to the user to set the number of items per set.
#include <stdio.h>
#include<stdlib.h>
int main()
{
unsigned short int num_sets, set_size, set_desired, command = 0;
printf("Enter the number of data sets you would like to store: \n");
scanf(" %hu", &num_sets);
int *sets[num_sets];
int i = 0, k=0,j,sum, a;
while(i < num_sets)
{
j = 1;
printf("Enter the number of elements in data set %hu: \n", i+1);
scanf(" %hu", &set_size);
sets[i] = (int *) malloc((sizeof(int)*set_size));
*sets[i] = set_size;
printf("Enter the values for set %hu\n", i+1);
while(j <= set_size)
{
scanf(" %d", &sets[i][j]);
j++;
}
i++;
}
printf("Which set would you like to use?: \n");
scanf(" %hu", &set_desired);
while(set_desired > num_sets){
printf("There aren't that many data sets, try again: \n");
scanf(" %hu", &set_desired);
}
for(k=1;k<=(*sets[set_desired-1]);k++)
{
printf("Set #%hu: %hu \n", set_desired, *(sets[set_desired-1] + k));
}
while(command != 7){
printf("Choose what you would like to do:\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. Select a different data set.\n");
printf("7. Exit the program.\n");
scanf(" %hu", &command);
if(command == 1){
printf("You picked 1!");
}
if(command == 2){
printf("You picked 2!");
}
if(command == 3){
/*printf("You picked 3!");
* for(a = 0; a < set_size; a++){
* sum = sum + *sets[a];
* }
* printf("%d\n", sum);*/
printf("You picked 3!");
}
if(command == 4){
printf("You picked 4!");
}
if(command == 5){
printf("You picked 5!");
}
if(command == 6){
printf("You picked 6!");
}
if(command == 7){
break;
}
}
return 0;
}

You have undefined behaviour in your code. In this line:
int i = 1, j, sets[1][num_sets], sum, a;
you allocate enough space for one element in each of num_sets sets of data. This isn't really what you need. You probably want the num_sets as the first index, and you need a larger value for the other index.
You are likely to need to do dynamic memory allocation. Failing that, you'll need to set an upper bound (maybe 100) on the size of the arrays, and reject attempts to create bigger arrays. You'd then use:
enum { MAX_ARR_SIZE = 100 };
int sets[num_sets][MAX_ARR_SIZE];
for the variable. Your data entry loop already assumes this method of indexing. You probably need to keep a record of how many entries there are in each row somewhere, so as to avoid using uninitialized data.
int set_size[num_sets];

Related

How can I modify program to set array range from 0 to 100 in program below

I need the code below to recognize if the grades entered is below 1 or greater than 100. If it is not within the parameters, I want to let the user know and allow them to enter another grade without exiting the program or losing grades they have already entered. I don't want the program to quit until the user enters q and I want to ensure all of the valid grades entered print at that time. I have tried numerous methods and am not getting the right results. I think I probably need some other else if statement, but I haven't been able to find the right one to work. Any information you can share to get me on the right track would be greatly appreciated.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char choice;
int gradeArray[100];
int grades;
int gCount=0,i;
for(gCount=0; gCount<100; gCount++)
{
//for loop to read the grades till array size
printf("******Enter Choice Selection in Parenthesis******\n Add grades(a)\n Quit(q) \n");
scanf("%c",&choice);
if(choice == 'a' || 'A')
{
//if user choice is a, then read the grade
printf( "Enter grade: ");
scanf("%d", &grades);
getchar();
gradeArray[gCount] = grades; //add the grade to array
}
if(choice == 'q') //if the user choice is q, then exit the loop
{
break;
}
}
printf("Grades are:\n");
for(i=0; i<gCount; i++)
{
printf(" %d%%\n", gradeArray[i]); //print grades
}
return 0;
}
You can do a while loop to verify the user input. With a while you'll be able to force the user to enter the right grade.
if(choice == 'A' || choice == 'a'){
printf("Enter grade:");
scanf("%d", &grades);
getchar();
while(grade < 1 || grade > 100){
printf("You entered a wrong number\n");
printf("Enter a grade between 1 and 100: ");
scanf("%d", &grades);
getchar();
}
gradeArray[gCount] = grades;
}
your solution is almost aligned with what you had in mind. Here is how you can do it differently.
#include <stdio.h>
int main()
{
char choice;
int arraySize = 100; //change this to any number you wish
int gradeScore = 0;
int gradeArray[arraySize];
int gCount = 0;
int showCount = 0;
while(choice != 'q')
{
//to ask for user's input every time
printf("What do you want to do? Enter\n");
printf("'a' to add grades\n");
printf("'q' to quit\n");
scanf(" %c", &choice); //space is entered to ensure the compiler does not read whitespaces
//your implementation should check for user input before proceeding
if(choice != 'a')
{
//in this condition, 'q' is technically an incorrect input but your design states that 'q' is for quitting
//thus, do not alert the user here if 'q' is entered
if(choice != 'q')
{
//a condition to warn the user for incorrect input
printf("Incorrect input. Please enter only 'a' or 'q'\n");
}
}
else if(choice == 'a')
{
printf("Enter grade: \n");
scanf(" %d", &gradeScore);
//to check for user input if the grades entered are less than 1 or more than 100
if(gradeScore < 1 || gradeScore >100)
{
//print a warning message
printf("The grade you entered is invalid. Please enter a grade from 1 - 100\n");
}
//for all correct inputs, store them in an array
else
{
printf("Grade entered\n");
gradeArray[gCount] = gradeScore;
gCount++;
}
}
}
//prints grade when 'q' is entered
if(choice == 'q')
{
printf("Grades are: \n");
for(showCount = 0; showCount < gCount ; showCount++)
{
printf("%d\n", gradeArray[showCount]);
}
}
}
To sum up the important parts, be sure to check for the user grade input to be in range of 1 - 100. Store the grade in the array if it is within range and be sure to increase the array counter, otherwise it will always store it in gradeArray[0] for the subsequent grades. Hope this helps
Use a do-while loop to keep the program looping back to get another choice unless a valid choice has been entered. Use fgetc to read a single character - fewer problems. Only print grades if at least one grade has been entered.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char choice;
int gradeArray[100];
int grades;
int gCount=0,i;
for(gCount=0; gCount<100; gCount++)
{
//for loop to read the grades till array size
printf("******Enter Choice Selection******\n Add grades(a)\n Quit(q) \n");
do
{
choice = fgetc(stdin);
if(choice == 'a' || choice == 'A')
{
//if user choice is a, then read the grade
printf( "Enter grade: ");
scanf("%d", &grades);
getchar();
gradeArray[gCount] = grades; //add the grade to array
}
else if(choice != 'q')
printf("Invalid choice - try again\n");
} while (choice != 'a' && choice != 'A' && choice != 'q');
if(choice == 'q') //if the user choice is q, then exit the loop
break;
}
if(gCount > 0)
{
printf("Grades are:\n");
for(i=0; i<gCount; i++)
printf(" %d%%\n", gradeArray[i]); //print grades
}
return 0;
}

C for loop, How do I continuously prompt the user?

I am learning about loops such as for and while loops, so I decided to put myself to the test and write a program which you can see the code for below. The program gives the user a range of options to enter an option, but the problem I have is that i want to be able to continuously ask the user to "Enter a command" after an operation has completed.
For example, if I entered 1, the necessary code would be executed but then the whole program just ends. How can I enhance this program so it continuously asks the user to enter new commands until the user forcibly exits by entering 0?
#include <stdio.h>
int main()
{
int n;
int credit = 0;
int YN;
printf("Welcome to Cash booking software Version 2.145\n");
printf("--------------------------------------------------------\n");
printf("Use the following options:\n");
printf("0 -- Exit\n");
printf("1 -- Display Credit\n");
printf("2 -- Change Credit\n");
printf("3 -- Remove Credit\n");
printf("\n");
for ( ; ; )
{
printf("Enter a command: ");
scanf("%d", &n);
if (n == 0)
{
return 0;
}
else if (n == 1)
{
printf("Your credit is £%d", credit);
}
else if (n == 2)
{
printf("Enter a new credit value: \n");
scanf("%d", &credit);
printf("Your new credit value is %d", credit);
}
else if (n == 3)
{
printf("Are you sure you want to remove your Credit value? (Y=1/N=2)");
scanf("%d", &YN);
if (YN == 1)
{
credit = 0;
}
else
;
}
return 0;
}
}
As other users explained return 0; inside of the loop is what is causing the problem and moving it out would solve it, But since you're learning about loops I think this is a great example to teach you something.
Usually you should only use a for loop when you have some parameter that defines de number of times the loop will be executed. The fact that you just used for( ; ; ) is a huge red flag for ther is a betther way to do this.
For example the proper way to write an infinite loop in c is while(1){//code in the loop}. So you could change your for loop with this and it will work fine (relocating return 0; in the correct location).
But since in this code you dont really want an infinite loop (usually they're a bad idea), but you want the loop to run until is pressed 0, the best solution is to use a do{} while(); loop where inside of do you check if either 1, 2 or 3 is pressed and perform their functionality, and then in the while condition you check if 0 has been pressed, and only in that case the program exits.
This is how the code would look like:
do{
printf("Enter a command: ");
scanf("%d", &n);
if (n == 1){
printf("Your credit is £%d\n", credit); // \n added
}
else if (n == 2){
printf("Enter a new credit value: \n");
scanf("%d", &credit);
printf("Your new credit value is %d\n", credit); // \n added
}
else if (n == 3){
printf("Are you sure you want to remove your Credit value? (Y=1/N=2):");
scanf("%d", &YN);
if (YN == 1){
credit = 0;
}
}
} while(n != 0);
return 0;
Also note that I added \n in some printf() commands for better visualization.
use continue statement at the end of each condition , and you can use break statement instead of return 0, so the code will be :
if (n == 0)
{
break;
}
else if (n == 1)
{
printf("Your credit is £%d ", credit);
continue;
}
else if (n == 2)
{
printf("Enter a new credit value: \n");
scanf("%d", &credit);
printf("Your new credit value is %d ", credit);
continue;
}
else if (n == 3)
{
printf("Are you sure you want to remove your Credit value? (Y=1/N=2) : ");
scanf("%d", &YN);
if (YN == 1)
{
credit = 0;
continue;
}
else {
continue;
}

Can someone tell how make user input the element in array and to insert element at the last position?

/*ARRAY INSERTION AT THE END*/
#include<stdio.h>
#include<conio.h>
int main()
{
int i,n,insrt;
char option;
int array[100];
printf("\nWHAT IS THE TOTAL NUMBER OF ARRAY YO WANT ?\n");
scanf(" %d", &n);
for(i=0;i<n;i++)
{
printf("\nENTER THE NO FOR YOUR ARRAY:\t");
scanf(" %d", &array[i]);
}
printf("\nYOU HAVE FOLLOWING NO IN THE LIST:\n");
for(i=0;i<n;i++)
{
printf(" %d==>", array[i]);
}printf("NULL");
do
{
printf("\nENTER THE VALUE TO BE INSERTED AT THE END:\t");
scanf(" %d", &insrt);
for(i=0 ;i<n;i++)
{
if (array[i] == 0)
{
array[i] = insrt;
printf("\nINSERTION SUCCESSFULL!!\n");
break;
}
else
{
printf("\nTHE ARRAY IS FULL.\n");
break;
}
}
printf("\nDO YOU WANT TO CONTINUE ? TYPE (Y FOR YES AND N FOR NO):\t");
scanf(" %c", &option);
}while(option == 'Y' || option == 'y');
printf("\nYOU HAVE FOLLOWING NO IN THE LIST:\n");
for(i=0;i<n;i++)
{
printf(" %d==>", array[i]);
}
printf("NULL");
getch();
}
Insertion at the end of the array is not working, tried everything I know but it is still not working and instead of insertion it only prints that array is full.
I know that there is a fault in loop statement but I am unable to fix it.
https://i.stack.imgur.com/xO6Jz.png
1st mistake:
You are taking input n after defining the array. It should be:
scanf(" %d", &n);
int array[n];
2nd mistake:
else
{
printf("\nTHE ARRAY IS FULL.\n");
break;
}
for i=0, a[i] = 432 this is not equal to zero, so it will go to else, and print "The Array is Full".
Just keep track of the number of elements inserted in array, if no_elem == n-1, then print "Array is full" and break;.

GPA scores program

I am supposed to write a program where the user is asked how many students there are in a class. Then, it asks for the GPA of each of those students. In the end, it is supposed to display number of students with each GPA score. So far this is what i have, but it doesn't seem to count properly.
#include <stdio.h>
int main(void){
int cnt1, cnt2, cnt3, cnt4, student, numofsdts, GPA, GPAFreq[4];
printf("Enter number of students: ");
scanf("%d", &numofsdts);
student = 1;
while(student <= numofsdts){
printf("GPA of student number %d: ", student);
scanf("%d", &GPA);
if(GPA < 1 || GPA > 4){
printf("invalid number \n");
}
else{
student++;
}
if(student == numofsdts + 1)
break;
if(GPAFreq[1])
cnt1++;
else if(GPAFreq[2])
cnt2++;
else if(GPAFreq[3])
cnt3++;
else if(GPAFreq[4])
cnt4++;
}
printf("GPA 1: %d students \n", cnt1);
printf("GPA 2: %d students \n", cnt2);
printf("GPA 3: %d students \n", cnt3);
printf("GPA 4: %d students \n", cnt4);
}
Set int cnt1 = 0, cnt2 = 0 etc. (they are not nullified by default, just have some garbage [like a rented room not cleaned explicitly...]).
Also:
if(GPA < 1 || GPA > 4){
printf("invalid number \n");
continue; // skip the rest of the loop body
}
Or a slightly cleaner approach (in full):
#include <stdio.h>
int main(void){
int cnt1 = 0, cnt2 = 0, cnt3 = 0, cnt4 = 0;
int numofsdts, GPA;
printf("Enter number of students: ");
scanf("%d", &numofsdts);
students = 0;
while(students <= numofsdts){
printf("GPA of student number %d: ", students + 1);
scanf("%d", &GPA);
if(GPA < 1 || GPA > 4){
printf("invalid number \n");
continue;
}
if(GPA == 1)
cnt1++;
else if(GPA == 2)
cnt2++;
else if(GPA == 3)
cnt3++;
else if(GPA == 4)
cnt4++;
students++;
}
printf("GPA 1: %d students \n", cnt1);
printf("GPA 2: %d students \n", cnt2);
printf("GPA 3: %d students \n", cnt3);
printf("GPA 4: %d students \n", cnt4);
}
There are multiple errors here. The first is that cnt1-4 have to be initialized prior to being added to. The second is that C uses zero indexing, so GPAFreq[4] is not accessing the fourth element of your array (which would be GPAFreq[3].
The third is that your if statement isn't doing what you think it is. It is evaluating the values inside of your array as boolean variables, i.e. 0 is false, anything else is true. A better approach is to do this:
GPAFreq[GPA - 1] += 1;
This will be counting the frequencies in each of the indices of the array. Then to print them, you just access GPAFreq and no longer need the cnt variables.

Converting an array to use malloc

Currently I have set up an array to hold 50 packets created by the program. However I would like to change this array to use malloc instead along with the use of storing a maximum of 50 pieces of information just as the current array does.
Here's the current code used to set up the array used under int main
struct packet create[50];
int countpackets = 0;
And the array is incremented within another function within the code as so
int add(struct packet *create, int countpackets){
char inputDest[10],inputType[4],inputPort[2],inputData[50],inputSource[10];
if (countpackets == 50){
puts("Too many packets already entered.");
}else{
printf("\n\n");
int i = 0;
printf("\t Source - Must be 1024 or below >\t");
scanf("%s", inputSource);
create[countpackets].source = atoi(inputSource);
for (i = 0; i < strlen(inputSource); i++){
while(isdigit(inputSource[i])== 0 || create[countpackets].source > 1024){
printf("************************************************** \n");
puts("Invalid input, numbers only or number too big\n");
printf("\t please re-enter your Source >");
scanf("%s", inputSource); //rescans if it's a letter
create[countpackets].source = atoi(inputSource);
}
}
printf("\t Destination - Must be 1024 or below >\t");
scanf("%s", inputDest);
create[countpackets].destination = atoi(inputDest);
for (i = 0; i < strlen(inputDest); i++)
{
while(isdigit(inputDest[i])== 0 || create[countpackets].destination > 1024){
printf("************************************************** \n");
puts("Invalid input, numbers only or number too big\n");
printf("\t please re-enter your Destination >");
scanf("%s", inputDest); //rescans if it's a letter
create[countpackets].destination = atoi(inputDest);
}
}
printf("\t Type - Must be 10 or below >\t");
scanf("%s", inputType);
create[countpackets].type = atoi(inputType);
for (i = 0; i < strlen(inputType); i++){
while(isdigit(inputType[i])== 0 || create[countpackets].type > 10){
printf("************************************************** \n");
puts("Invalid input, numbers only or number too big \t \n");
printf("\t please re-enter your Type >");
scanf("%s", inputType); //rescans if it's a letter
create[countpackets].type = atoi(inputType);
}
}
printf("\t Port - Must be 1024 or below >\t");
scanf("%s", inputPort);
create[countpackets].port = atoi(inputPort);
for (i = 0; i < strlen(inputPort); i++)
{
while(isdigit(inputPort[i])== 0 || create[countpackets].port > 1024){
printf("************************************************** \n");
puts("Invalid input, numbers only or number too big \t \n");
printf("\t please re-enter your Type >");
scanf("%s", inputPort); //rescans if it's a letter
create[countpackets].port = atoi(inputPort);
}
}
printf("\t Data have less than 50 characters >\t");
scanf("%s", inputData);
for (i = 0; i < strlen(inputData); i++){
while(isdigit(inputData[i])== 0){ //checks if it's a letter
printf("************************************************** \n");
puts("Invalid input, numbers only or number too big \t \n");
printf("\t please re-enter your Type >");
scanf("%s", inputData); //rescans if it's a letter
}
strcpy(create[countpackets].data, inputData);
}
}
countpackets++;
return countpackets;
}
I'm pretty new to C and I do believe that is all the code I need to show, however if need be I will put up my full program. Any help would be much appreciated.
If you want to declare this...
struct packet create[50];
...with malloc, you'll have to do this...
struct packet *pCreate = malloc(50 * sizeof(struct packet));
You can use it the same.
create[0] = pCreate[0]; // First element
create[49] = pCreate[49]; // Last element

Resources