How initialize array dynamically using function in C - c

SS4SS of 3rd Problem
I want to create the program to take the input from user until he presses 1.
I'm using dynamic memory allocation using function and after running this code, this program takes only 4 input and it does not show any output
output
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
void input(int **arr)
{
int n=1,i=0;
*arr=(int *)malloc(sizeof(int));
int ch;
do
{
printf("\nEnter '1' To Enter A Value in array or else enter '0'");
scanf("%d",&ch);
if (ch==1)
{
if (!*arr)
{
printf("\nInsufficient Memory!");
return;
}
printf("\nEnter the value\t:\t");
scanf("%d", arr[i]);
*arr=realloc(*arr,sizeof(int)*(++n));
*arr[++i]=INT_MIN;
}
else if (ch!=1&&ch!=0)
{
printf("\nInvalid input!");
continue;
}
} while(ch!=0);
free(arr);
}
void display(int **arr)
{
for (int i = 0; i < 3; i++)
printf("\n%d", **(arr+i));
free(arr);
}
int main()
{
int *arr;
input(&arr);
display(&arr);
free(arr);
return 0;
}

First question
With !*arr[i] you are checking the logical value contained in *arr[i], which can have a random value before you assign a value to it. In your case, the value contained in *arr[i] is 0, triggering the condition !*arr[i].
The correct way of checking if realoc() was succesful, is checkin it's returned value. If it's null, the request failed. In your case, it would be replacing
if(!*arr[i])
by
if(!*arr)
Second question
In this line *arr[++i]=INT_MIN; the index [] operator has precedence over pointer * operator. You have to write parenthesis:
(*arr)[++i]=INT_MIN;
And also here
scanf("%d", arr[i]);
you are saying that arr is an array, when it is a pointer to an array. You should replace it with:
scanf("%d", *arr + i);
Third question
You are also doing free() before you access the values in the array, which triggers the error. You should remove the free() calls at the end of input() and display() and leave only the one of the end of main().
You have still to replace the printf() in display with
printf("\n%d", (*arr)[i]));

Related

Segmentation fault in C program using pointers as parameters

Im trying to understand pointers as function parameters, and in one of the programs there is a segmentation error I can't fix. Firstly, why to use pointers in function arguments? and Why is this error showing?
#include <stdio.h>
void square_it(int* a)
{
printf("The final value is: %d\n", *a * *a);
}
int main()
{
int* input;
puts("This program squares the input integer number");
puts("Please put the number:");
scanf("%d", &input);
square_it(input);
return 0;
}
int* input; does not allocate memory for an int. It mearly makes it possible to make input point at an int (allocated elsewhere). Currently, by dereferencing it (like you do with *a), you make your program have undefined behavior. If you really want an intermediate pointer variable for this, this example shows how it could be done:
#include <stdio.h>
void square_it(int *a) {
*a *= *a; // same as *a = *a * *a;
}
int main() {
int data;
int* input = &data; // now `input` points at an `int`
puts("This program squares the input integer number");
puts("Please put the number:");
// check that `scanf` succeeds:
if(scanf("%d", input) == 1) { // don't take its address, it's a pointer already
square_it(input);
// since `input` is pointing at `data`, it's actually the value of `data`
// that is affected by `scanf` and `square_it`, which makes the below work:
printf("The final value is: %d\n", data);
}
}
Without an intermediate pointer variable:
#include <stdio.h>
void square_it(int *a) {
*a *= *a;
}
int main() {
int input; // note that it's not a pointer here
puts("This program squares the input integer number");
puts("Please put the number:");
if(scanf("%d", &input) == 1) { // here, taking the address of `input` makes sense
square_it(&input); // and here too
printf("The final value is: %d\n", input);
}
}
Without any pointers at all, it could look like this:
#include <stdio.h>
int square_it(int a) {
return a * a;
}
int main() {
int input;
puts("This program squares the input integer number");
puts("Please put the number:");
if(scanf("%d", &input) == 1) { // here, taking the address of `input` makes sense
int result = square_it(input);
printf("The final value is: %d\n", result);
}
}
This is the working code:
#include <stdio.h>
void square_it(int* a)
{
printf("The final value is: %d\n", *a * *a);
}
int main()
{
int i = 0;
int* input = &i;
puts("This program squares the input integer number");
puts("Please put the number:");
scanf("%d", input);
square_it(input);
return 0;
}
There are some errors in the original code:
According to the man-pages to scanf, it takes a format string and then the address of where to store the input.
You gave it the address of a pointer (eg. an int**), which is not what scanf expects.
Also you need to provide memory to store the input in. The scanf string tells that you want an integer as input. In the above code snippet that is i.
input points to i, so i can give the int*, that is input to scanf. scanf will then write into i. We can then go ahead and put the address of i into the sqare_it function.
Since we did not use the heap, we don't need to worry about memory management.

C - random numbers array function [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 5 years ago.
I'm trying to create a function that creates an array in size n with random numbers stored inside, I've been trying several option but once i use the array in main, only the first number shows up correctly.
I'm using CodeBlock by the way.
static int *arr;
int i, num;
printf("enter the length of the array: ");
scanf("%d/n", &num);
arr = get_random_arr(num);
for(i=0;i<num;i++)
{
printf("outside the function: %d\n", *(arr+i));
}
return 0;
int *get_random_arr(int num)
{
int temp_arr[num];
int i;
srand((unsigned)time(NULL));
for (i=0;i<num;i++)
{
temp_arr[i] = rand() % 1001 ;
printf("inside the function: %d\n",temp_arr[i]);
}
return temp_arr;
}
and this is the code that compiles:
enter the length of the array: 3
inside the function: 224
inside the function: 774
inside the function: 60
outside the function: 224
outside the function: 2686648
outside the function: 1977872892
Thank's to "coderredoc" his answer was the solution i was looking for
scanf("%d/n", &num);
You have to enter the number followed by / and n. This is not what you want. You wanted this
scanf("%d\n", &num);
But here the scanf reads the number in num but then the reading continues until nonwhitespace character followed by \n is found. You don't need the \n here.
Also returning return temp_arr; and using it outside it's scope is UB.
The array temp_arr has automatic storage duration meaning its lifetime will end after the function ends. Accessing it outside its scope is undefined behavior which is precisely what you did.
Something like this
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int *get_random_arr(int num)
{
if( num <= 0){
fprintf(stderr, "%s\n", "Error in the number: num >= 1");
exit(1);
}
int *temp_arr = (int*)malloc( sizeof *temp_arr *num);
if( !temp_arr ){
fprintf(stderr, "%s\n", "Error in malloc");
exit(1);
}
srand((unsigned)time(NULL));
for(size_t i=0;i<num;i++)
{
temp_arr[i] = rand() % 1001 ;
printf("inside the function: %d\n",temp_arr[i]);
}
return temp_arr;
}
int main(){
static int *arr;
int num;
printf("enter the length of the array: ");
if( scanf("%d", &num) != 1){
fprintf(stderr, "%s\n","Error in input" );
exit(1);
}
arr = get_random_arr(num);
for(size_t i=0;i<num;i++)
{
printf("outside the function: %d\n", *(arr+i));
}
free(arr);
return 0;
}
The code tries to show a possible way to achieve what you wanted. Dynamically allocated memories lifetimes extends beyond the scope of the function. That's why it works. Note the free() - which is used to free the dynamically allocated memory.
The first and foremost, in your code, temp_arr is local to the function get_random_arr(). Once the function finishes, the returned address is not valid anymore!
The moment you try to use the returned value, it causes undefined behavior, as the accessed memory is invalid in the context of the caller.
That said, not checking the return value of scanf() also posses a problem. In case scanf() fails, you'll be end up using an unitialized value.

error while using array of pointers instead of 2 dimensional array

the following code crashes if i give array of pointer here is there any other way to accept value through array of pointers or did i do somethong wrong here
the run this program after compiling you should type
objectname -numberoflines
//program to print first n lines of string using command line arguement
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>
int less(int x,int y);`enter code here`
int main(int argc,char* argv[])
{
int i,j,n,num;
char *lines[100];/*if I use two dimensional array here the code compiles
char nu[6];
// the whole for loop is for checking error in n
for(i=1,n=strlen(argv[1]);i<n;i++)
{
if(argv[1][i]=='.')
{
printf("your input was not correct \n");
return 0;
}
if(argv[1][i]=='-')
{
printf("your input was not correct \n");
return 0;
}
if(isalpha(argv[1][i])!=0)
{
printf("your input was not correct indeed");
return 0;
}
}
printf("\t\t application to print number of last n lines \n\n\n");
printf("enter the number of lines\n");
scanf("%d",&n);
printf("enter your lines \n");
for(j=0;(n<100)&&(j<=n);j++)
{
gets(lines[j]);
}
strcpy(nu,argv[1]);
nu[0]=' ';
num=atoi(nu);
num=(less(num,n));
for(i=0;i<=num;i++)
{
printf("%s",lines[i]);
}
return 0;
}
int less(int x,int y)
{
int z;
return (z=(x>y?y,printf("your input lines are less\n"):x));
}
The main problem is that when you write
char *lines[100];
You create an array of 100 char* pointers. These pointers have no memory allocated for them and they point to a random location. Writing to that location(using gets in your program) invokes Undefined Behavior.
To fix it, allocate memory for each pointer using
for(i=0 ; i<100 ; i++)
lines[i]=malloc(AMOUNT_OF_BYTES_TO_ALLOCATE);
And later, after the use is over, free the allocated memory using
for(i=0 ; i<100 ; i++)
free(lines[i]);
The reason that it worked when you used a two dimensional array is that you create an array of array of char for which memory is automatically allocated in the stack.

Endless loop in C; for loop seems valid

I am a student trying to learn c coming from c++. I wrote the following code and it compiles fine; however, when I execute it I get an endless loop when calling the print function. I looked over the code and it seems to be valid to me, so why is it printing an endless loop?
#include <stdio.h>
#include <stdlib.h>
struct student
{
int id;
int score;
};
void generate(struct student *students, int n)
{
int randomId = rand () % n + 1;
int randomTestScore = rand() % 100 + 1;
students->id = randomId;
students->score = randomTestScore;
}
void sort(struct student *students, int n)
{
/*using insertion sort*/
for (unsigned int i = 1; i < n; ++i)
{
int next = students[i].score;
int j = i;
while(j > 0 && students[j-1].score > next)
{
students[j].score = students[j-1].score;
j--;
}
students[j].score = next;
}
}
void print(struct student *students, int n)
{
for (unsigned int i = 0; i < n; i++)
{
printf("Student at position No: %d Test Score: %d\n", i+1, students[i].score);
}
}
int main()
{
/*user enters num of students to create scores for*/
int num_students;
printf("Enter Num of students\n");
scanf("%d", num_students);
/*allocate memory for the amount of students user wants*/
struct student *userStudents = malloc(num_students*sizeof(struct student));
printf("Randomly filling students IDs & Test Scores...\n");
for (unsigned int i = 0; i < num_students; ++i)
{
generate(&userStudents[i], num_students);
}
printf("Array of students before sorting:\n");
print(userStudents, num_students);
printf("\nNow, sorting students by test scores...\n\n");
sort(userStudents, num_students);
printf("Array of students after sorting:\n");
print(userStudents, num_students);
return 0;
}
To use scanf() correctly it needs to alter the passed variable in place, and since there is no pass by refrence in c, you need to pass the address of the variable, so scanf() is able to modify it though a pointer, hence you need to use the & operator, but that is not enough.
The scanf() family of functions, return a value that must be checked before you can access the scanned values, you should never ignore that value, under any circumstances you should check for it.
What your code is doing is called undefined behavior, it's interpreting the passed integer as if it was a pointer, which is undefined behavior.
To prevent that you can activate compiler warnings, many compilers know what kind of parameter the *f functions expect, i.e. the functions which take a string as a format to be parsed and to allow the function to correctly grab the rest of the parameters passed via variable arguments to it.
The correct way to call scanf() in your program is
if (scanf("%d", &num_students) != 1)
return 1;
that is, from main() and hence it's ending the program, because you can't continue after that condition was true, in that case what actually happens is that num_students is not initialized, that would once again cause undefined behavior.
Change the call to scanf to:
/*
* correct way of calling scanf, passing the address of the wanted variable
*/
scanf("%d", &num_students);
^
This elliminates segmentation faults and makes the code runs OK on my machine.
I had a previous hint that you'd need to change your declaration of userStudents to a pointer to pointers, however I was incorrect. You are clearly correctly allocating enough contiguous memory to hold all of your structs pointed by *userStudents.

Can I use malloc this way?

I want to find the minimum number and summary from a dynamic integer table. I do not know why results not shown. Have I done something wrong on the malloc ? May I use realloc too ?
#include <stdlib.h>
#include <stdio.h>
int main()
{
int n,i,min,sum,xronos;
int* array;
printf("Give me how many numbers does the table will have: \n");
scanf("%d",&n);
array=(int*)malloc(n*sizeof(int));
for(i=1;i<=n;i++)
{
printf("Give the number %d",i);
printf("\n");
scanf("%d",&array[i]);
}
for(i=1;i<=n;i++)
{
sum=sum+array[i];
if (i=1)
{
min=array[i];
}
else
{
if (array[i]<min)
{
min=array[i];
}
}
}
printf("%d",sum);
printf("\n The answer is :",(n-2)*min+(sum-min));
getch();
return 0;
}
Yes, that is almost exactly how you are supposed to use malloc, except for three small things and one big thing:
Do not cast malloc result in C,
Use indexes from zero to n-1, inclusive (your code goes from one to n, inclusive)
Add a call free(array) to avoid a memory leak.
The big thing is that you do not need malloc in order to solve this problem: you can calculate the sum and the min as you go, without saving the individual items to an array.
You can replace the chain of ifs in the loop with this check:
if (i == 0 || array[i] < min) {
min=array[i];
}
This covers both the assignment of the first element, and comparison of elements other than the first one.
Finally, you can rewrite this
sum=sum+array[i];
as
sum += array[i];
using a composite assignment operator. Don't forget to initialize the sum to zero!
#include <stdlib.h>
#include <stdio.h>
#include <errno.h> /* Defines: ENOMEM */
int main()
{
Added rCode to assist in error handling.
int rCode=0;
Removed xronos as it is not used.
int n,i,min;
Initialized sum to 0;
int sum=0;
Initialize array pointer to NULL so cleanup is easier.
int *array = NULL;
printf("Give me how many numbers does the table will have: \n");
scanf("%d",&n);
There is nothing inherently wrong with casting the output of malloc to (int *). In some situations, it is a good coding practice. (good job).
array=(int*)malloc(n*sizeof(int));
You should always test that you actually got memory from malloc.
if(NULL == array)
{
rCode=ENOMEM;
fprintf(stderr, "malloc() failed.");
goto CLEANUP;
}
The array element index is in the range of 0 through (n-1). Start indexing at zero, and be sure to stop at (n-1).
for(i=0;i<n;i++)
{
printf("Give the number %d",i);
printf("\n");
scanf("%d",&array[i]);
}
Again, the array element index is in the range of 0 through (n-1). Start indexing at zero, and be sure to stop at (n-1).
for(i=0;i<n;i++)
{
sum=sum+array[i];
if(1 == i)
min=array[i];
else
{
if(array[i] < min)
min=array[i];
}
}
printf("%d",sum);
printf("\n The answer is :",(n-2)*min+(sum-min));
getch();
CLEANUP:
From my early years, my father would tell me: 'When you bring your toys to the sandbox, always remember to put them away when you are finished.'
if(array)
free(array);
return(rCode);
}
Line 22, need
if (i=1)
set to
if (i==1)
Right now you're setting i equal to 1

Resources