Code blocks, adding and storing integers through a function - c

So I'm trying to get a simple program to work by asking the user to enter numbers within 1-100 and have the program store everything entered then tell the user later on all the numbers and how much it adds up to be.
Right now all I want to know is how do I store the variables and have the program be able to tell me how many numbers were entered.
Should I make a function outside of main that does the processing for storing and adding?
#include <stdio.h>
int main () {
int number, even, odd;
char name;
printf("Enter your name")
scanf(%d, &number);
scanf (%c, &char)
printf("Enter numbers within 1-100")
printf("Enter 0 to quit")
while (number != 0) {
if (number%2 == 1) {
//This is where I don't know how to store the odd numbers
}
else {
//And the even numbers here as well
}
}
printf("%c,the numbers you have entered are broken down as follows:\n",name);
printf("You entered %d even numbers with a total value of \n", even);
printf("You entered %d odd numbers with a total value of \n", odd);
return 0;
}

Here is a sample program. Enhance as required as suggested in the previous update.
#include <stdio.h>
#include <stdlib.h>
int
main ()
{
int number, even, odd;
int *evenarr, *oddarr;
int evencount = 0, oddcount = 0;
int i;
char name;
evenarr = (int *) malloc(100 * sizeof(int));
oddarr = (int *) malloc(100 * sizeof(int));
printf ("Enter numbers within 1-100");
printf ("Enter 0 to quit");
do
{
scanf ("%d", &number);
if (number != 0)
{
if (number < 1 || number > 100)
continue;
if (number % 2 == 1)
{
//This is where I don't know how to store the odd numbers
printf ("odd\n");
oddarr[oddcount] = number;
oddcount++;
/* Realloc the arr if size exceed 100 */
}
else
{
//And the even numbers here as well
printf ("even\n");
evenarr[evencount] = number;
evencount++;
/* Realloc the arr if size exceed 100 */
}
}
}
while (number != 0);
for(i=0; i<oddcount; i++)
printf("odd : %d\n", oddarr[i]);
for(i=0; i<evencount; i++)
printf("even : %d\n", evenarr[i]);
}

Your question is a little ambiguous but it seems to me that you may need to allocate memory dynamically for storage since you don't know how many numbers will be entered during run time.
This can be done multiple ways. The first method involves using the malloc() and realloc() functions. I'll leave you to research these functions but basically malloc() allocates memory on the heap during run time and realloc() allows you to resize the memory that was given to you.
I think the best method would be to implement a linked list data structure. This way you can store the numbers as the user enters them and then later iterate through the list and count how many numbers were odd or even. And similarly you can also calculate their totals.
More information on linked list data structures:
https://en.wikipedia.org/wiki/Linked_list
http://www.cprogramming.com/tutorial/c/lesson15.html
https://www.youtube.com/watch?v=vcQIFT79_50
These are just some of the resources I used to learn linked lists. There are plenty more information about linked lists on Google.

You can use malloc(). It allocates memory on the heap. Also, using realloc() allows you to resize the memory you allocated using malloc().
See this tutorial on malloc and free.
The code #Umamahesh has given is correct, just that he is not freeing the memory allocated by the program, which might be fatal.
So you just free the pointers. The corrected code in #Umamahesh answer is:
#include <stdio.h>
#include <stdlib.h>
int
main ()
{
int number, even, odd;
int *evenarr, *oddarr;
int evencount = 0, oddcount = 0;
int i;
char name;
evenarr = (int *) malloc(100 * sizeof(int));
oddarr = (int *) malloc(100 * sizeof(int));
printf ("Enter numbers within 1-100");
printf ("Enter 0 to quit");
do
{
scanf ("%d", &number);
if (number != 0)
{
if (number < 1 || number > 100)
continue;
if (number % 2 == 1)
{
//This is where I don't know how to store the odd numbers
printf ("odd\n");
oddarr[oddcount] = number;
oddcount++;
/* Realloc the arr if size exceed 100 */
}
else
{
//And the even numbers here as well
printf ("even\n");
evenarr[evencount] = number;
evencount++;
/* Realloc the arr if size exceed 100 */
}
}
}
while (number != 0);
for(i=0; i<oddcount; i++)
printf("odd : %d\n", oddarr[i]);
for(i=0; i<evencount; i++)
printf("even : %d\n", evenarr[i]);
free (evenarr);
free (oddarr);
}
Also see: How do free and malloc work in C?.

Related

Store a given amount of numbers using pointers in C

I'm trying to learn how to use pointers, and I'm trying to make a program that asks the user for a random number of integers they'd like to write in, and then printing them back to the user. Normally I'd use an array for this, but that defeats the whole purpose of learning pointers.
#include <stdio.h>
#include <malloc.h>
int main() {
int numberAmount = 0;
int *numbers;
printf("Type the amount of numbers you are going to write: ");
scanf("%i", &numberAmount);
numbers = (int*) malloc(sizeof(numberAmount));
if (numberAmount == 0) {
printf("No numbers were given");
}
else {
for (int i = 0; i < numberAmount; i++) {
scanf("%i", numbers);
}
while (*numbers != 0) {
printf("%i ", *numbers);
numbers++;
}
}
return 0;
}
This is what I've come up with so far, but it does not work.
Any ideas?
In this part of your code
for (int i = 0; i < numberAmount; i++) {
scanf("%i", numbers);
}
you're saving the number that the user inputted in the same memory location. So the value saved in the numbers pointer keeps changing whenever the user inputs a new integer instead of adding a new integer.
You can fix this by replacing scanf("%i", numbers); with scanf("%i", (numbers + i));. This way for every new input the user provides, it will be saved in the memory location next to numbers.

How to properly free dynamically allocated memory for an array of pointers to int's

I need to know if I have used free() correctly while attempting to free dynamically allocated memory for an array of pointers to int's.
My code is modified from a code snippet out of one of my books and is the beginning of a program which requests temperature readings for three cities.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int ctr, num, num2 = 0, ctr2 = 0;
int* temps[3];
for(ctr = 0; ctr < 3; ctr++)
{
puts("how many readings for the city?");
scanf(" %d", &num);
temps[ctr] = (int*)malloc(num * sizeof(int));
num2 += num;
while(ctr2 < num2)
{
puts(" what is reading? ");
scanf(" %d", &temps[ctr][ctr2]);
printf("echo: %d ", temps[ctr][ctr2]);
ctr2++;
}
}
for(ctr = 0; ctr < 3; ctr++)
{
free(temps[ctr]);
}
getchar();
getchar();
return (0);
}
I know that a pointer which is assigned memory using malloc() may have values assigned and accessed through a combination of a loop and array indexes. Hence I have assigned values from user input using the indexes of a two dimensional array, and need to know if I used free correctly. I know this is extremely sloppy coding and I am merely seeking to understand free correctly to prevent any potential memory leaks.
it's okay since you respect the same number of loops for allocation and deallocation with the same statement:
for(ctr = 0; ctr < 3; ctr++)
Just make sure that temps can hold at least 3 elements, which is the case, and that num is not zero or undefined (test return value of scanf & value of num). You can use a sizeof formula in your case to avoid hardcoding the value, only because you have an array of pointers, not pointers on pointers.
also avoid casting return value of malloc. And use the size of the element, instead of hardcoding as int (so if type of the pointer changes, your sizes are still right). Improvement suggestion for allocation:
for(ctr = 0; ctr < (int)(sizeof(temps)/sizeof(*temps)); ctr++)
{
puts("how many readings for the city?");
if (!scanf(" %d", &num) || num <= 0) { printf("wrong number\n"); exit(1); } // or better error handling
temps[ctr] = malloc(num * sizeof(*temps[ctr]));
You may still get a segmentation fault when calling free if you corrupt the memory when filling your arrays (a comment suggests it does, since num2 grows and grows). If you get such errors, run your code with valgrind, or just perform allocations/deallocations (and not the rest) to find which part of the code causes the problem.
The proper way of freeing the dynamically allocated memory is to free it after you check if it has been allocated at the very first place or not. As your loop structure is same for allocating and freeing, there wont be any problem here as such if all the allocations are successful. Therefore I suggest you check at all the places if the allocation is successful after allocating and also check if the memory is allocated before freeing.
Following code will make sure all the cases:
scanf(" %d", &num);
/*
* check here if the value of ctr in non-negative and in the appropriate range
*/
temps[ctr] = (int*)malloc(num * sizeof(int));
if (temps[ctr] == NULL) {
printf ("Memory allocation failed\n");
/*
* appropriate error handling
*/
}
Also, check when you are freeing the memory to be on the safer side.
for(ctr = 0; ctr < 3; ctr++)
{
if(temps[ctr]) {
free(temps[ctr]);
}
}
Also there is a bug in your code where after the first iteration itself you will get memory out of bound error, as the variable ctr2 in never reinitialized.
num2 += num;
while(ctr2 < num2)
{
puts(" what is reading? ");
scanf(" %d", &temps[ctr][ctr2]);
printf("echo: %d ", temps[ctr][ctr2]);
ctr2++;
}
Here if the value of num was 20 in the first iteration, then in the second iteration you will end up taking the input starting from temps[1][20], and assuming the value of num in the second iteration to be 5, you have allocated just 5 * sizeof(int)), so obviously you are going out of bounds when you try to access temps[1][20].
Please let me know if the following code would be considered acceptable:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int ctr, num, ctr2 = 0;
int * temps[3];
for(ctr = 0; ctr < (int)(sizeof(temps)/sizeof(*temps)); ctr++)
{
puts("how many readings for the city?");
if (!scanf(" %d", &num) || num <= 0) { printf("wrong number\n"); exit(1); }
temps[ctr] = (int *) malloc(num * sizeof(*temps[ctr]));
while(ctr2 < num)
{
puts(" what is reading? ");
scanf(" %d", &temps[ctr][ctr2]);
printf("echo: %d ", temps[ctr][ctr2]);
ctr2++;
}
ctr2 = 0;
}
for(ctr = 0; ctr < (int)(sizeof(temps)/sizeof(*temps)); ctr++)
{
free(temps[ctr]);
}
getchar();
getchar();
return (0);
}

Extreme sum values calculated inside a structure

While I was learning to code in C about structure and pointers, I tried to make a program that calculate grades of students.
I thought it would work from my previous experiences for such calculation without pointers and structure. But with those, it gave me wild results in the program.
#include <stdio.h>
#include <string.h>
/*
The program will scan year, name, score of three different subjects,
and calculate the sum and the average.
Three different people (using array) will be taken into account.
*/
struct grade {
int year;
char name[20];
int score[3];
int total;
float avg;
};
void main() {
struct grade p[3];
char str = 'c';
char *pstr = NULL;
int i, j;
pstr = &str;
for (j = 0; j < 3; j++) {
printf("Year of Admission: ");
scanf("%d", &p[j].year);
printf("Name of the Student: ");
scanf("%s", pstr);
strcpy(p[j].name, pstr);
for (i = 0; i < 3; i++) {
printf("The score for Subject %d: ", i + 1);
scanf("%d", &p[j].score[i]);
p[j].total += p[j].score[i];
}
p[j].avg = p[j].total / 3.0;
}
for (j = 0; j < 3; j++) {
printf("%s's\n", p[j].name);
printf("Total score: %d\n", p[j].total);
printf("Average: %.2f\n", p[j].avg);
}
}
I could have written each of three different subjects as one variable but for an extra "challenge", I made an array inside the structure.
int score[3];
However, the program only prints out extremely small number -89541694... for both totals and averages.
I assume that this particular line inside a for-loop is a problem.
scanf("%d", &p[j].score[i]);
But I could not figure out why. I am really new to pointers and still learning them.
I hope for your generous teaching and explanations.
Thank you in advance.
Local variables are not initialized with 0, so you just need to zero it before calculating total:
p[j].total = 0;
before
for (i = 0; i < 3; i++) {
printf("The score for Subject %d: ", i + 1);
scanf("%d", &p[j].score[i]);
p[j].total += p[j].score[i];
}
The variable pstr points to a single char. A string in C needs to be at least two characters for a single-character string: The actual character, and the null terminator.
When you use e.g. scanf to read a string, the function will write at least two bytes to the memory pointed to by pstr. But since it only points to a single byte you will write out of bounds and that leads to undefined behavior.
If you want to be able to read more than a single character you need to have more space allocated for the string. And you need to limit scanf so it will not write out of bounds.
For example
char pstr[40]; // Allows for strings up to 39 character, plus terminator
// ...
scanf("%39s", pstr); // Read at most 39 characters from standard input, and write to pstr
Another problem is that local variables are not automatically initialized, their values will be indeterminate.
That means the contents of the array p is unknown and seemingly random.
When you do
p[j].total += p[j].score[i];
you use the seemingly random value of p[j].total to calculate another seemingly random number.
To initialize all structures and all their members to "zero" in the array, do e.g.
struct grad p[3] = { 0 };
Instead of making pstr a pointer you might wanted to do somehting like this
char pstr[30];
And accordingly you will scanf the string using scanf("%29s",pstr); and check it's return value.
To describe the problem a bit - you had a pointer pointing to a char which is not capable of holding an input characters and the corresponding \0 (nul terminating character). As a result this gives rise to undefined behavior. And then using it in strcpy is also an illegal code. (Undefined behavior).
Here the solution I gave simply declared an array of 30 characters and we limited the string input using scanf upto 29 characters because we need to store the terminating null.
Showing you atleast a bit of code to make you understand how to write these codes:-
if( scanf("%29s",pstr)!= 1){
fprintf(stderrm"Error in input");
exit(EXIT_FAILURE);
}
Another problem is initialize the variables - here you used p[j].total += p[j].score[i]; What is the value of p[j].total initially. It contains garbage value. In the loop make p[j].total = 0; first. That will give you the correct result.
Note: The wild results are the garbage value resulted from addition of some garbage value with p[j].score[i].
Also note that without making the changes that I said if you only change the initialization thing then also code is not guranteed to work. undefined behavior is undefined behavior - cases may arise which will simply crash the program making you wonder where you went wrong.
Illustration code may help you:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
The program will scan year, name, score of three different subjects,
and calculate the sum and the average.
Three different people (using array) will be taken into account.
*/
struct grade {
int year;
char name[20];
int score[3];
int total;
float avg;
};
int main(void) {
struct grade p[3];
char pstr[20];
int i, j;
for (j = 0; j < 3; j++) {
printf("Year of Admission: ");
if(scanf("%d", &p[j].year)!=1){
fprintf(stderr, "%s\n", "Error in input");
exit(EXIT_FAILURE);
}
printf("Name of the Student: ");
if(scanf("%19s", pstr)!=1){
fprintf(stderr, "%s\n", "Error in input");
exit(EXIT_FAILURE);
}
strcpy(p[j].name, pstr);
p[j].total = 0;
for (i = 0; i < 3; i++) {
printf("The score for Subject %d: ", i + 1);
if(scanf("%d", &p[j].score[i])!=1){
fprintf(stderr, "%s\n", "Error in input");
exit(EXIT_FAILURE);
}
if(p[j].score < 0){
fprintf(stderr, "%s\n", "Error in input");
exit(EXIT_FAILURE);
}
p[j].total += p[j].score[i];
}
p[j].avg = p[j].total / 3.0;
}
for (j = 0; j < 3; j++) {
printf("%s's\n", p[j].name);
printf("Total score: %d\n", p[j].total);
printf("Average: %.2f\n", p[j].avg);
}
return 0;
}
In fact instead of using the pstr just input the names directly in the structure variable instance itself. No need to use a temporary variable.

How do I create an array with undefined length? (In C)

I'm trying to create a program which randomly decides how many cards you have, then randomly allocates a value to each of those cards.
I have managed to randomise the amount of cards, and I know how to randomise their values using an array and a for loop, but the problem is that this method only works when I manually choose a value for the number of elements in the array, but I want the number of elements to be the random amount of cards.
How do I go about this?
Here's my code so far to show what I mean. And yes, I'm aware the code probably could be done better but this is my first C assignment and I'm a complete beginner.
Thanks :)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
int main(void)
{
system("cls"); /* Clears output to start */
srand(time(NULL)); /* Sets seed for random number generator */
int player1_amount = rand() %9 + 2; /*Generates random number for player 1's amount of cards */
int player2_amount = rand() %9 + 2; /*Generates random number for player 2's amount of cards */
int a = 1; /* For loop purposes */
while(a <= 1) /* While loop to print out each player's amount of cards once */
{
printf("Player 1 you have %d cards! \n", player1_amount);
Sleep(500);
printf("Player 2 you have %d cards! \n", player2_amount);
a++;
}
Sleep(1000); /* Delays for 1 second before printing card values */
int values[3]; /* Creates an array with 3 elements, but I want the number of elements to be player1_amount from above */
int b; /* Random variable for the loop */
int size = sizeof(values) / sizeof(values[0]); /* Gets length of array */
for (b = 0; b < size; b++) /* For loop randomises 3 values and then stops */
{
values[b] = rand() % 10 +1;
}
printf("Player 1 your cards are"); /* For loop to print out the values one after the other */
for(b = 0; b < size; b++)
{
printf(" %d, ", values[b]);
}
getch();
return 0;
}
I believe you will want to use malloc or calloc for that with a pointer.
int *values = (int *)calloc(player1_amount, sizeof(int));
Just make sure you free your allocation when done:
free(values);
C allows you to declare variable sized array. If you are not interested in using functions like malloc or calloc you can simply use variable to declare array as I've done here :
#include <stdio.h>
void main()
{
int x;
printf("\nEnter the value of x : ");
scanf("%d" , &x);
int array[x];
for(i = 0 ; i < x ; i++)
{
printf("Enter the element : ");
scanf("%d" , &array[i]);
}
for(i = 0 ; i < x ; i++)
{
printf("%d " , array[i]);
}
}
This program runs correctly without any error. So your problem is solved here itself without using malloc or calloc. But just make sure you declare your array after scanning or giving value to your variable which will represent the size of your array(here : x is the variable) and in your case I guess : player1_amount.
But still if you want to use malloc then here it goes :
#include <stdio.h>
#include <stdlib.h>
void main()
{
int x , i;
int * array;
printf("\nEnter the value of x : ");
scanf("%d" , &x);
array = (int *) malloc(x * sizeof(int));
for(i = 0 ; i < x ; i++)
{
printf("Enter the element : ");
scanf("%d" , &array[i]);
}
for(i = 0 ; i < x ; i++)
{
printf("%d " , array[i]);
}
}
Both the codes will give you same output.
A little explanation ...
Malloc will take input parameter as the amount of memory you wish to allocate to given variable(like 'array' in our case) in bytes and will output the pointer to that block of memory.
Since here we are working with integer array the return type is cast as : (int *), had it been a character array we would type cast it as : (char *).

Defining malloc array size with scanf and initialising

I'm trying to create a program that asks the user for a size of an array, then asks the user to populate it.
Whenever I launch the program, the "Element %d" printf displays the %d as a large number instead of 1.
If I continue the program after entering the value into the array, the debugger crashes. What's happening here? Did I accidentally place the address in the array position? Thanks
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int elements = 0;
printf("How many Elements will you enter?");
scanf("%d", &elements);
int* elementArray = malloc(sizeof(int) * elements);
int i = 0;
while (elementArray[i] != '\0')
{
printf("Element %d: ", elementArray[i]);
scanf("%d", &elementArray[i]);
i++;
}
free(elementArray);
return 0;
}
EDIT: Reading the comments, I meant printf("Element %d: ", elementArray[i]); was supposed to print one during the first loop. Though I should edit the code to be elementArray[i] + 1 so it doesn't print "Element 0" instead of Element 1. Apologies for the barebones code, it's half finished, I wanted to solve this problem before finishing it off. Will work on the solutions given now. Thanks for the help
EDIT2: Thanks to all of you, especially Sharuya! Here's my finished code.
void printArray(int* elemArray, int elements)
{
printf("The Array contains: ");
for (int k = 0; k < elements; k++)
{
printf("%d,\t", elemArray[k]);
}
}
int main(void)
{
int elements = 0;
printf("How many Elements will you enter?");
scanf("%d", &elements);
int* elementArray = (int *)malloc(sizeof(int) * elements);
int input = 0;
for (int j = 0; j < elements; j++)
{
printf("Element %d: ", j + 1);
scanf("%d\n", &input);
*(elementArray + j) = input;
}
printArray(elementArray, elements);
free(elementArray);
return 0;
}
Only issue now is, between the "Element 1: " and "Element 2: " printf, I get a blank line, that allows me to enter a number, upon submitting, it continues as normal. If I submit an array with 5 elements, It asks me for 6 elements, and only 5 appear... What's happening here?
while (elementArray[i] != '\0')
This check is the problem
malloc gives no guarantee that the memory initialized will be zero filled. Hence your loop may cross over the allocated memory and try to read memory that your program is not supposed to read (hence resulting in a crash)
If it's zero filled your code will never enter the loop
What you need is
while (i < elements)
Also printf should come after scanf for any meaningful result. If you want to just get the index that you are about to enter use printf("Element: %d", i) instead of elementArray[i]
A couple of questions, for you to ask:
What if the user enters a negative value?
What if the user enters 0 ?
What if the user enters a very large value?
Did the array allocation succeed?
What is in my array after it is allocated?
If my array size is 0, will elemenArray[0] be valid?
Should I use a for loop, like everyonbe else does for walking through my array?
Just asking yourself these questions will fix this program in no time, and will get you through half of the next one you'll write.
You have more problems than the fact that you print something else than the index.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int elements = 0;
printf("How many Elements will you enter? ");
if((1!=scanf("%d", &elements))||(elements<1) ) // check return value, always a good idea
{ printf("Reading number failed.\n");
return 1;
}
int* elementArray = malloc(sizeof(int) * elements);
int i = 0;
while ( (i<elements) // use the number you asked for to avoid writing beyond array
&& ((0==i) || (0 != elementArray[i-1]))) // stop when previously entered value is 0
{
printf("Element %d: ", i+1); // print the index
// instead of the non-initialised value
if(1!= scanf("%d", &elementArray[i]))
{
printf("Reading value failed!\n");
free(elementArray); // cleanup
return 1;
}
i++;
}
if (i<elements)
{
printf("Stopped early because 0 was entered.\n");
}
free(elementArray);
return 0;
}
First you need to know that malloc() function dynamically allocates memory according to the size calculated (with the help of sizeof() ) and returns the address of this memory location.
However this address is not associated with any data type i.e. only a void* pointer can store this address of an incomplete data type.
Thus instead of mentioning
int* elementArray = malloc(sizeof(int) * elements);
mention and use typecasting to it
int* elementArray = (int *)malloc(sizeof(int) * elements);
As per your code, elementArray is a pointer which will store the address of an integer
int *elementArray;
printf("Element %d: ", elementArray[i]);
Thus the above line will actually print the address pointed to by the pointer and not the index since incrementing a pointer is same as
elementArray stores the base address.
i.e elementArray++ is equal to elementArray+1 == elementArray[1] will point
to the next memory location after 4 bytes.(since integer is stored in 4 bytes)
I have modified your code correcting your mistakes
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int elements = 0;
printf("How many Elements will you enter?");
scanf("%d", &elements);
//the below statement actually allocates contiguous block of memory equal
//to no of elements and the pointer points only to first element.
//Incrementing it will point to next element
int* elementArray =(int *) malloc(sizeof(int) * elements);
//typecasting of void* pointer to int*
int i = 0,elm;
for(i=0;i<elements;i++)
//Since u know iterations will be equal to no of elements it is better to use for loop
{
printf("Element %d: ", i);
scanf("%d", &elm);
*(elementArray+i)=elm;
//Storing the data in elm and making the pointer point to next free
//dynamically allocated block of memory and using * operator the value at
//this location is accessed and storing elm value in it
}
for(i=0;i<elements;i++)
printf("%d",*(elementArray+i));
free(elementArray);
return 0;
}
This code works and I hope it make things clear !!!

Resources