Malloc Realloc Free - c

Hello I for an exercise at University i need to malloc an array with this way. The array at stars has 1 slot. If the inputs are more than one then the array is doubled. If the inputs are more than 2 then it is doubled again etc. After this I have to crop the array to fit to the number of inputs. For example if I have 5 inputs then the array will have 8 slots and I must make it to have 5 slots which I cannot figure out how. Here is my code so far:
nameInfoT* ReadNames(int* size){
nameInfoT* names ;
int array_size=1;
int entries=0;
char input[length];
names=(nameInfoT*) malloc(sizeof(nameInfoT)*array_size);
do{
scanf("%s",input);
if(!strcmp(input,"END")) break;
if(entries==array_size){
array_size=array_size*2;
names= (nameInfoT*) realloc(names,sizeof(nameInfoT)*array_size);
}
names[entries].name=(char*)malloc(sizeof(char)*strlen(input));
strcpy(names[entries].name,input);
entries++;
}while(1);
printf("there are %d free spaces \n",array_size-entries);
*size=entries;
printf("there are %d entries \n",*size);
int i;
for(i=array_size;i>entries;i--){
free(names[i]);//here it won't compile
}
return names;
}

You can only free the result of malloc/calloc/realloc. You cannot free individual elements. So in the end you can simply realloc again to the desired final size.

You have a couple of other problems:
1) when you allocate space for the input string, you need to add 1 to keep the trailing '\0'
2) before your realloc, you should have a switch statement which will take the array_size and use that to determine the new size. If I understand your problem, you want to go from 1 -> 2 -> 4 -> n (where n is the next number). Your realloc code just doubles each time. You need to change that.
3) when you free the entries, you need to be careful since you don't seem to be freeing the 'name' member of the class/struct.
4) after freeing the members in the loop, then do one free on the names class/struct.
I could look into it more carefully later.

Related

2-D Array in C storing user inputs

total C newbie here. Thanks for any help beforehand.
I am required to write a code which has the following properties:
Asking user to input the number of rows and columns they would like in their 2-D array
creates a 2-D array with that many rows and columns for storing integers
fills the array with random numbers between 1 and 1000
outputs the largest number in the array
This is where I could go for now:
#include <stdio.h>
int main(){
int rows;
int columns;
scanf("%d", &rows);
scanf("%d", &columns);
}
What should I do?
Sorry for the very open question, I am stuck and don't know what to do. A guideline will be perfect. Thanks :)
EDIT:
Thanks for the guideline, here is how I solved it:
SOLUTION:
#include <stdio.h>
#include <time.h>
int main () {
//Declare variables
int a,b,k,l,big,z[100][100];
//Ask user input
printf("ENTER ROWS & COLUMNS\n");
scanf("%d\n%d", &a, &b);
//Randomize array values
srand(time(NULL));
big = 1;
for (k=0;k<a;k++){
for(l=0;l<b;l++){
z[k][l]=rand()%1000 + 1;
if(z[k][l]>big) big=z[k][l];
printf("%d\t", z[k][l]);
}
printf("\n");
}
//Print biggest number
printf("\nBIGGEST NUMBER IN THE ARRAY: %d", big);
return 0;
}
A guideline will be perfect.
okay... let's go...
Asking user to input the number of rows and columns they would like in their 2-D array
Use scanf or better fgets followed by sscanf
creates a 2-D array with that many rows and columns for storing integers
Use malloc (search the net for "how to correctly malloc a 2D array" or simply see Correctly allocating multi-dimensional arrays)
fills the array with random numbers between 1 and 1000
Use srand, rand and the % operator
outputs the largest number in the array
Iterate all elements of the array and compare against a running max.
C does not support natively 2D arrays, you need to allocate an array of arrays. You don't know the size in advance, so you need to allocate the arrays memory dynamically using malloc.
For generating random numbers, you could use rand, but you need to set a seed first for the sequence of the pseudo-random integers using srand to get (possibly) a different number on every execution, or you can use rand_r to do the both operation with one function. Note that rand generate a random number between 0 and RAND_MAX, you need to use a trick with the modulus operator % to generate a random number in a specific range [min, max].
min + (rand() % (max - min + 1))
You can iterate over the arrays with two loops, to get the maximum number.
To know how to use these function, you can read the man pages: malloc rand
As a side note, you don't really need the 2D array to get the maximum number, you can calculate it directly with allocating any additional memory.
Your solution will work, but it's limited to 100 columns and 100 rows. If for instance the user enters higher numbers, your code will mostly crash. One solution is to validate the input and refuse numbers above 100 if you don't want to handle dynamic memory allocation, but in real world that is very much rare and dynamic memory allocation is a necessary.
You shouldn't name your variables with one-character names, especially if they live long. A good descriptive name like columnsNumber is preferred.

How do i determine the size of an array from a character read from a file?

I have to allocate a dynamic array and i know how many columns there will be on the array but i don't know how many rows, all i have is a number on a .txt file. I have tried the following code but i am not sure it will work:
int x = (int)fgetc(file)-48;
Since the ascii value of 0 is 48, i assumned that i needed to cast the character read from the file in order to be able to use it as my rows number.
I assume i should be able to allocate the array the 2D array as it follows:
m = (int **)malloc(x*sizeof(int*));
for (i=0;i<x;i++)
{
m[i] = (int*)malloc(10*sizeof(int));
}
Am i correct? Any help will be highly apretiated.
You can design a list and dynamically insert your rows.
First off fgetc() returns an integer, so casting it as an int will do nothing. Second you're only reading in one integer at a time with fgetc() so you will have a 1 digit number in x.
Your array allocation looks correct, but you can also allocate the columns as an array of int * on the stack and then allocate the rows dynamically as m[i] = (int*)malloc(x*sizeof(int)); from i = 0->9
Do I understand correctly that your file looks like
327 // number of lines
1 2 3 // line 1
33 44 55 // line 2
... repeats until 327 lines have been printed, all with 3 elements? Note that the line breaks would be optional and could be any whitespace.
The canonical way to read a number from text in C is using scanf. scanf uses, like printf, a weird looking format string as the fist parameter. Each basic type has a letter associated with it, for integers it's d or, more intuitively, i. These letters are prefixed with a %. So to read an integer, you would write scanf("%d", &lines); if lines is an int holding the number of lines. (Do rather not use x, for readability).
The way you allocate your array is correct (provided x holds the number of lines and 10 is the known line length). One style issue is that the 10 should be #defined as a macro so that you can use e.g. malloc(LINE_LEN*sizeof(int)). That helps later when that number should ever change and you have (in a real world program) scattered references to m over several source files.
If this is just a little program and the array isnt't inordinately large and does not need to live longer than the function call (which, in the case of main(), may be long enough in any case), the easiest would be to use a variable size array in C; provided you use a modestly modern compiler:
#define LINE_LEN 10
int lineCount;
scanf("%d", &lineCount);
int m[lineCount][LINE_LEN];
// fill from file
If you compile with gcc you'll probably need to specify "-std=c99" as a command line option for that.

Get all the divisors for a number in C

I'm trying to build a function that takes 1 param: the number as char[] and returns a char** with the divisors as strings.
I have come up with the following function, which works only for some numbers.
char** calc_div(char nr[100])
{
int nri,i,ct=0;
char **a = (char**)malloc(sizeof(char*));
nri = atoi(nr);
for(i=0;i<sizeof(char*);i++)
a[i] = (char*)malloc(sizeof(char));
for(i=1;i<=nri;i++)
if(nri % i == 0)
{
sprintf(a[ct++],"%d",i);
}
return a;
}
This works for numbers like 22, 33, 77 but not for 66 or 88 (it just gets stuck somewhere). Could anyone help me?
So many problems in such a small space...oh dear!
Let's think about the interface first...how does the calling code know how many values are returned? Presumably, there must be a null pointer at the end of the array of pointers. Also, for each number bigger than 1, we know that 1 and the number itself will be divisors, so we are going to need an array of at least 3 pointers returned. If a number is not prime or one, then there will be more values to push into the array. Therefore, one of the things we'll need to do is keep tabs on how many values are in the array. Also, the memory release code will need to step through the returned array, releasing each string before releasing the array overall.
So, we get some ideas about what the code should do. How does your code fare against this?
char** calc_div(char nr[100])
{
int nri,i,ct=0;
char **a = (char**)malloc(sizeof(char*));
This allocates one entry in the return array. We now know we need at least 3 times as much space, and we also have to keep a record of how much space was allocated.
nri = atoi(nr);
for(i=0;i<sizeof(char*);i++)
a[i] = (char*)malloc(sizeof(char));
This allocates 4 or 8 strings of size 1 byte each, assigning them to successive elements of the array of size 1 previously allocated. This is a guaranteed buffer overflow on the array a. Plus, because the strings are only big enough to hold the null at the end of string, you can't put any answers in there. You should probably be allocating strlen(nr)+1 bytes since nr is one of the numbers you'll need. It is not remotely clear that numbers are limited to either 3 or 7 factors (since you also need to allow for the terminating null pointer).
for(i=1;i<=nri;i++)
if(nri % i == 0)
{
sprintf(a[ct++],"%d",i);
}
The code inside the body of the if statement will have to be ready to do memory allocation for the new factor and for the array as and when necessary.
return a;
}
After
char **a = (char**)malloc(sizeof(char*));
a has space for 1 pointer to char ...
for(i=0;i<sizeof(char*);i++)
a[i] = (char*)malloc(sizeof(char));
but you try to write to more than that single element (unless sizeof(char*) happens to be 1).

Remove element from c array

I need to remove a specific element from an array, that array is dynamically resized in order to store an unknown number of elements with realloc.
To control the allocated memory and defined elements, I have two other variables:
double *arr = NULL;
int elements = 0;
int allocated = 0;
After some elements being placed in the array, I may need to remove some of them. All texts that I've found says to use memmove and reduce the variables by the number of elements removed.
My doubt is if this method is secure and efficient.
I think this is the most efficient function you can use (memcpy is not an option) regarding secured - you will need to make sure that the parameters are OK, otherwise bad things will happen :)
Using memmove is certainly efficient, and not significantly less secure than iterating over the array. To know how secure the implementation actually is, we'd need to see the code, specifically the memmove call and how return results from realloc are being checked.
If you get your memmove wrong, or don't check any realloc returns, expect a crash.
In principle, assuming you calculate your addresses and lengths correctly, you can use memmove, but note that if you overwrite one or more elements with the elements at higher indexes, and these overwritten elements were structs that contained pointers to allocated memory, you could produce leaks.
IOW, you must first take care of properly disposing the elements you are overwriting before you can use memmove. How you dispose them depends on what they represent. If they are merely structs that contain pointers into other structures, but they don't "own" the allocated memory, nothing happens. If the pointers "own" the memory, it must be deallocated first.
The performance of memmove() and realloc() can be increased by data partitioning. By data partitioning I mean to use multiple array chunk rather than one big array.
Apart from memmove(), I found memory swaping is efficient way. But there is drawback. The array order may be changed in this way.
int remove_element(int*from, int total, int index) {
if(index != (total-1))
from[index] = from[total-1];
return total-1; // return the number of elements
}
Interestingly array is randomly accessible by the index. And removing randomly an element may impact the indexes of other elements as well. If this remove is done in a loop traversal on the array, then the reordering may case unexpected results.
One way to fix that is to use a is_blank mask array and defer removal.
int remove_element(int*from, int total, int*is_valid, int index) {
is_blank[index] = 1;
return total; // **DO NOT DECREASE** the total here
}
It may create a sparse array. But it is also possible to fill it up as new elements are added in the blank positions.
Again, it is possible to make the array compact in the following efficient swap algorithm.
int sparse_to_compact(int*arr, int total, int*is_valid) {
int i = 0;
int last = total - 1;
// trim the last blank elements
for(; last >= 0 && is_blank[last]; last--); // trim blank elements from last
// now we keep swapping the blank with last valid element
for(i=0; i < last; i++) {
if(!is_blank[i])
continue;
arr[i] = arr[last]; // swap blank with the last valid
last--;
for(; last >= 0 && is_blank[last]; last--); // trim blank elements
}
return last+1; // return the compact length of the array
}
Note that the algorithm above uses swap and it changes the element order. May be it is preferred/safe to be used outside of some loop operation on the array. And if the indices of the elements are saved somewhere, they need to be updated/rebuilt as well.

Escaping loop whilst adding to dynamic array - C

Currently my program allows the user to enter 5 integers which are used to create an average number. This is set to five as after the fifth number is entered the loop is broken.
I am trying to implement a method which will let the user continue to add as many numbers as they like to an array from which i can then use to create an average without a limit on the amount of numbers that can be entered.
I have come across a few problems, firstly i cannot create an array which is dyamic as i have no idea how many numbers the user may wish to enter which means i can't give it a definitive size.
Secondly the way my program currently creates the average is by looping through the elements in the array and adding the consecutively to an integer, from which the the average is made. I cannot specify the limit for the loop to continue running if i cannot determine the array.
Hopefully my example explains this better.
#include <stdio.h>
#include <string.h>
void main()
{
int i = 0;
int arrayNum[5];
int temp = 1;
int anotherTemp = 0;
int answer = 0;
printf("Enter as many numbers as you like, when finished enter a negative number\n");
for(i = 0; i < 5; i++)
{
scanf("%d", &temp);
arrayNum[i] = temp;
anotherTemp = anotherTemp + arrayNum[i];
}
answer = anotherTemp / 5;
printf("Average of %d,%d,%d,%d,%d = %d",arrayNum[0],arrayNum[1],arrayNum[2],arrayNum[3],arrayNum[4],answer);
}
Although this may not be the best way to implement it, it does work when the amount of numbers are specified beforehand.
What would be the best way to get around this and allow the user to enter as many number as necessary?
Edit: Although i needed to use an array I have decided that it is not necessary as the solution is much simpler without being restricted to it.
In terms of code simplicity, you might want to check out the realloc() function; you can allocate an initial array of some size, and if the user enters too many numbers call realloc() to get yourself a bigger array and continue from there.
You don't, however, actually need to keep the numbers as you go along at all, at least if you only care about the average:
int input;
int sum = 0;
int count = 0;
int average;
while (1) {
scanf("%d", &input);
if (input < 0) {
break;
}
sum += input;
count++;
}
average = sum / count;
If you're trying to compute an average, then you don't need to save the numbers. Save yourself the work of worrying about the array. Simply accumulate (add) each number to a single total, count each number, then divide when you're done. Two variables are all that you need.
With this method, you aren't in any risk of overflowing your array, so you can use a while loop... while (temp != -1)
Basically you start with a dynamically allocated array with a fixed size, and then allocate a new array that is bigger (say, twice as big as initial size) and copy the stuff from the old array to the new one whenever you run out of space.
For the second part of the problem, keep a counter of the number of items the user entered and use it when averaging.
Something like this.
Use a dynamic array data structure, like Vector in Java (java.util.Vector).
You can implement such a dynamic array yourself easily:
allocate array of size N
as soon as you need more elements than N, allocate a new bigger array (e.g. with size N+10), copy the content of the old array into the new array and set your working reference to the new array and your array size variable N to the new size (e.g. N+10). Free the old array.

Resources