Pointer in C gives all zero values - c

I made a number guessing game and want to print out all of the numbers that the user guessed while playing the game. However, when I run the program, it always prints out zero for all the values.
Your Tries: 0, 0, 0, 0, 0, %
It may be something wrong with the way I assigned the pointer value? Any help would be appreciated
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
int arr_size = 0;
int main()
{
// Initialize random number with seed 2021.
// Do not change this line, and do not call srand again.
srand(2022);
// the next line generate a random number between 1 to 100
int n = (rand() % 100) + 1;
int *p = malloc(sizeof(int) * arr_size);
while(1){
int guess;
scanf("%d", &guess);
arr_size ++;
p = realloc(p, sizeof(int) * arr_size);
p[arr_size-1] = guess;
if(n > guess){
printf("The Number is greater than %d\n", guess);
}else if(n < guess){
printf("The Number is less than %d\n", guess);
}else{
printf("You win. The Number is %d\n", guess);
break;
}
if(guess == -1){
printf("You input wrong number\nYou lose. The Number is %d", n);
break;
}
}
printf("Your Tries: ");
for(int i = 0; i < arr_size; i ++){
printf("%d, ", p[arr_size]);
}
return 0;
}

int *p = malloc(sizeof(int) * arr_size);
Allocating zero bytes isn't safe, the compiler can either return a null pointer or a pointer pointing at weird stuff, which may or may not be reallocatable(?). Replace this with int *p = NULL; to get deterministic, portable behavior instead.
p = realloc(p, sizeof(int) * arr_size); There is no guarantee that p is pointing at the reallocated data after this. Correct use of realloc is:
int* tmp = realloc(p, sizeof(int) * arr_size);
if(tmp == NULL) { /* handle errors */ }
p = tmp;
You never free(p).
There is no need to use dynamic allocation to begin with here, all you achieve with it is needless complexity, bloat and a much slower program. Just use int p[100]; and watch all your problems go away, while at the same time massively improving execution speed.
printf("%d, ", p[arr_size]); is nonsense and out of bounds, use p[i].

Related

What does int i do inside of the for loop(in scanf and sum) in this particular program?

Isn't i in scanf and in sum useless? It doesn't change anything, even when I print &ptr it doesn't show me any difference in memory values.
#include <stdio.h>
#include <stdlib.h>
int main() {
int n, *ptr, sum = 0;
printf("Enter number of elements: ");
scanf("%d", &n);
ptr = (int *)malloc(n * sizeof(int));
// if memory cannot be allocated
if (ptr == NULL) {
printf("Error! memory not allocated.");
exit(0);
}
printf("Enter elements: ");
for (int i = 0; i < n; ++i) {
scanf("%d", ptr + i);
sum = sum + *(ptr + i);
}
printf("Sum = %d", sum);
// deallocating the memory
free(ptr);
return 0;
}
The 'i' isn't supposed to change the pointer. It is used to access the i'th element of the array that PTR points to. Without the I it would scan for the same element in this array, the first element
If you don't use 'i' in both sum and scanf, there won't be any effect on sum because it will take input in the first index of the dynamic memory and overwrite it. This 'i' is helping to store inputs in the dynamic memory.
'i' isn't a useless value, it is used to offset the pointer to access the correct element of the dynamic array.
It is the same as using
for (int i = 0; i < n; ++i) {
scanf("%d", &ptr[i]);
sum = sum + ptr[i];
}
The purpose of the index i in the for is twofold:
ensure n numbers are read and cumulated in sum.
store each converted number into a separate entry in the array pointed to by ptr.
Given what the program does, it is not required to store the numbers into an array, or even necessary to allocate this array.
Here is a simpler version:
#include <stdio.h>
int main() {
int n, v, sum = 0;
printf("Enter number of elements: ");
if (scanf("%d", &n) != 1)
return 1;
printf("Enter elements: ");
for (int i = 0; i < n; i++) {
if (scanf("%d", &v) != 1) {
printf("input error\n");
break;
}
sum = sum + v;
}
printf("Sum = %d\n", sum);
return 0;
}
"What does int i do inside of the for loop?"
i is used for the pointer offset to access subsequent int objects of the dynamically allocated memory.
It works as:
(value of ptr [address of pointed object by ptr] + (i * sizeof(pointed object by ptr))).
Maybe take a look at this Stack Overflow question.
Note: The purpose is just to dereference and modify pointed to objects, not the pointer itself. ptr won´t get changed because of this pointer arithmetics.
"It doesn't change anything, even when I print &ptr it doesn't show me any difference in memory values."
Probably it doesn´t show different values because you print the address of the pointer itself, which doesn´t change by using offsets to the pointer.
I say "probably" because I don´t see how you actually print the address of ptr in particular. Maybe you even have some kind of kind of undefined behavior.

Assignment to expression with array type error

in this program I try to sort customer savings descendingly. And I've tried to compile the code. And I'm still not to understand about pointer. There is an error with message "Assignment to expression with array type error". The target output of this program is tend to be the sorted customers(with their names, and account numbers). I've search in the internet about that error. But I still don't get the solution. Can someone help me to solve the error? Thanks.
#include <stdio.h>
#include <stdlib.h>
struct Data
{
long long int Savings[100], AccNo[100];
char Name[100];
};
int main ()
{
struct Data *ptr;
int n, i, j, swap = 1, x, y;
long long int max, min, temp;
printf ("Enter number of customer(s) : ");
scanf ("%d", &n);
ptr = (struct Data *) malloc (n * sizeof (struct Data));
for (i = 0; i < n; i++)
{
printf ("Enter customer %d", i + 1);
printf ("\nName : ");
getchar ();
scanf ("%[^\n]s", &(ptr + i)->Name);
printf ("Savings : ");
scanf ("%d", &(ptr + i)->Savings);
printf ("Account Number : ");
scanf ("%d", &(ptr + i)->AccNo);
printf ("\n");
}
//Sorting bubblesort
for (x = 0; x < n; x++)
{
for (y = 0; y < (n - x - 1); y++)
{
if ((ptr + y)->Savings > (ptr + y + 1)->Savings)
{
temp = (ptr + y)->Savings;
(ptr + y)->Savings = (ptr + y + 1)->Savings;
(ptr + y + 1)->Savings = temp;
}
}
}
//Print sorted
printf ("\n Sorted customers are (:\n");
for (i = 0; i < n; ++i)
{
printf ("%s\n", (ptr + i)->Name);
printf ("%d\n", (ptr + i)->Savings);
}
free (ptr);
return 0;
}
You need to compile your code with warnings enabled, the will guide
you through debugging step by step. Try to eliminate one, and
compile again. In GCC for example, you would use -Wall flag.
The numerical fields of your struct should be just numbers, not
arrays. Moreover, having their type as long long int seems a bit
too much, but I leave that on you.
Having (ptr + y)->Savings to access the y-th element of an array
of structs and the its field names Savings is technically correct,
but it's much more cleaner (thus increases readability and
maintainability) to write ptr[y].Savings. That is a general rule,
applying to the rest of your code.
I believe the above led you to make two syntactical errors when you
were reading the numerical data of the customers with scanf(),
since you know that an integer in general needs the & operator. If
you had used the clean approach from the start, you wouldn't made
those, I believe.
For long long int use the %lld format specifier, not just %d.
In Bubblesort, when you find elements that need to be swapped, then
swap the whole elements, not just their Savingss. I recommend
creating a function to do that.
scanf("%[^\n]s" doesn't make much sense, I would change it to
scanf("%99s", where 99 is the maximum size of your string, minus
one. Read more in the 2nd paragraph in scanf(“%[^\n]s”,a) question.
Putting everything together, we get:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Data {
long long int Savings, AccNo; // these should be numbers, not arrays
char Name[100];
};
void swap(struct Data* a, struct Data* b) {
struct Data tmp;
tmp.Savings = a->Savings;
tmp.AccNo = a->AccNo;
strcpy(tmp.Name, a->Name);
a->Savings = b->Savings;
a->AccNo = b->AccNo;
strcpy(a->Name, b->Name);
b->Savings = tmp.Savings;
b->AccNo = tmp.AccNo;
strcpy(b->Name, tmp.Name);
}
int main() {
struct Data *ptr;
int n, i, x, y;
printf("Enter number of customer(s) : ");
scanf("%d", &n);
ptr = malloc (n * sizeof(struct Data)); // do not cast malloc
for(i=0; i<n; i++) {
printf("Enter customer %d", i+1);
printf("\nName : ");
getchar();
scanf("%99s", ptr[i].Name); // ptr is a pointer, but now you want to actually use it as an array, so use '.'
printf("Savings : ");
scanf("%lld", &ptr[i].Savings); // needs &, just like you did for 'n'. USe `%lld' for long lont int as the format specifier.
printf("Account Number : ");
scanf("%lld", &ptr[i].AccNo); // needs &, just like you did for 'n'. USe `%lld' for long lont int as the format specifier.
printf("\n");
}
//Sorting bubblesort
for (x = 0; x < n; x++)
{
for (y = 0; y < n - x - 1; y++) // you don't need paranetheses in the stop condition
{
if (ptr[y].Savings > ptr[y + 1].Savings)
{
swap(&ptr[y], &ptr[y + 1]); // swap the whole element, not just its savings
}
}
}
//Print sorted
printf("\nSorted customers are:\n");
for(i=0; i<n; ++i)
{
printf("%s\n", (ptr+i)->Name);
printf("%lld\n", (ptr+i)->Savings);
}
free(ptr);
return 0;
}
Output (with relevant input):
Sorted customers are:
George
1
Babis
3
Theodor
20
PS: Do I cast the result of malloc? No!

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);
}

Code blocks, adding and storing integers through a function

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?.

A simple recursion function prints weird stuff

So I need to code a recursive function that validates if the number is a prime number.
The algorithm is pretty simple and works correctly, it's just that when I print the function rather than showing 1 or 0 it shows random crap (maybe addresses?) and I couldn't find out why.
The code:
int isPrimal(int n, int p) {
if (p == 1) {
return 1;
}
if (n % p == 0) {
return 0;
}
isPrimal(n, p - 1);
printf("n = %d i = %d\n", n, p);
}
int main() {
int numcase, *A, sizeA = 0, i = 0, cnt3dig = 0, n, p;
printf("Enter a number to check for primality\n");
scanf("%d", &n);
p = (n - 1);
printf("The result is 1 if the number is a prime, 0 otherwise\n");
isPrimal(n, p);
printf("The result is %d\n", isPrimal);
}
You are printing the address of the isPrimal() function, you should change it to
printf("The result is %d\n", isPrimal(n, p));
and don't forget to check scanf()'s return value.
The printf in main invokes undefined behavior because you pass the address of the function isPrimal instead of its result: change printf("The result is %d\n", isPrimal); to
printf("The result is %d\n", isPrimal(n, p));
Furthermore, your algorithm is very inefficient. Function isPrimal calls itself recursively n-2 times. If you remove the printf statement, the compiler notices the tail call to itself and turns this recursion into a loop. When you have the printf statement it cannot do this and for large values of n you probably recurse too deep and cause a Stackoverflow.
There are 2 changes that are necessary
1. In main, While printing the output make a function call -not a reference to the location of the function.
2. In isPrimal, Call the isprimal recursively after the print statement.
#include<stdio.h>
#include<stdlib.h>
int isPrimal(int n, int p) {
if (p == 1) {
return 1;
}
if (n % p == 0) {
return 0;
}
printf("n = %d i = %d\n", n, p);
isPrimal(n, p - 1);
}
int main() {
int numcase, *A, sizeA = 0, i = 0, cnt3dig = 0, n, p;
printf("Enter a number to check for primality\n");
scanf("%d", &n);
p = (n - 1);
printf("The result is 1 if the number is a prime, 0 otherwise\n");
printf("The result is %d\n", isPrimal(n, p));
return 1;
}

Resources