adding an element to an array using realloc - c

I'm trying to use realloc to add an element to an array after inputting characters.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i, j, k;
int a = 1;
int* array = (int*) malloc(sizeof(int) * a);
int* temp;
for(i = 0;;i++)
{
scanf("%d", &j);
temp = realloc(array, (a + 1) * sizeof(int));
temp[i] = j;
if(getchar())
break;
}
for(k=0; k <= a; k++)
{
printf("%d", temp[k]);
}
}
When I run this little program, and if I enter for exemple : 2 3 4
it displays me: 20;
I know that memory hasn't been allocated properly, but I can't figure out the issue.
Thanks in advance.

Firstly:
int* array = (int*) malloc(sizeof(int) * a);
int* temp = array;
and
temp = realloc(temp, (a + 1) * sizeof(int));
because after call 'realloc' pointer passed as first argument may becomes invalid.
And of course 'realloc' called with second parameter equal 2 always.
By the way 'scanf' stops read your input string after first non-digit character. Read documentation for correctly usage functions. For example about scanf() or realloc().

Related

different ways to declare a matrix c

I don't really understand why method 1 works but not method 2. I don't really see why it works for characters and not an int.
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
/// WORK (METHODE 1)
char **string_array = malloc(sizeof(char **) * 10);
string_array[0] = "Hi there";
printf("%s\n", string_array[0]); /// -> Hi there
/// DOES NOT WORK (METHODE 2)
int **int_matrix = malloc(sizeof(int **) * 10);
int_matrix[0][0] = 1; // -> Segmentation fault
/// WORK (METHODE 3)
int **int_matrix2 = malloc(sizeof(int *));
for (int i = 0; i < 10; i++)
{
int_matrix2[i] = malloc(sizeof(int));
}
int_matrix2[0][0] = 42;
printf("%d\n", int_matrix2[0][0]); // -> 42
}
In terms of the types, you want to allocate memory for the type "one level up" from the pointer you're assigning it to. For example, an int pointer (an int*), points to one or more ints. That means, when you allocate space for it, you should allocate based on the int type:
#define NUM_INTS 10
...
int* intPtr = malloc(NUM_INTS * sizeof(int));
// ^^ // we want ints, so allocate for sizeof(int)
In one of your cases, you have a double int pointer (an int**). This must point to one or more int pointers (int*), so that's the type you need to allocate space for:
#define NUM_INT_PTRS 5
...
int** myDblIntPtr = malloc(NUM_INT_PTRS * sizeof(int*));
// ^^ "one level up" from int** is int*
However, there's an even better way to do this. You can specify the size of your object it points to rather than a type:
int* intPtr = malloc(NUM_INTS * sizeof(*intPtr));
Here, intPtr is an int* type, and the object it points to is an int, and that's exactly what *intPtr gives us. This has the added benefit of less maintenance. Pretend some time down the line, int* intPtr changes to int** intPtr. For the first way of doing things, you'd have to change code in two places:
int** intPtr = malloc(NUM_INTS * sizeof(int*));
// ^^ here ^^ and here
However, with the 2nd way, you only need to change the declaration:
int** intPtr = malloc(NUM_INTS * sizeof(*intPtr));
// ^^ still changed here ^^ nothing to change here
With the change of declaration from int* to int**, *intPtr also changed "automatically", from int to int*. This means that the paradigm:
T* myPtr = malloc(NUM_ITEMS * sizeof(*myPtr));
is preferred, since *myPtr will always refer to the correct object we need to size for the correct amount of memory, no matter what type T is.
Others have already answered most of the question, but I thought I would add some illustrations...
When you want an array-like object, i.e., a sequence of consecutive elements of a given type T, you use a pointer to T, T *, but you want to point to objects of type T, and that is what you must allocate memory for.
If you want to allocate 10 T objects, you should use malloc(10 * sizeof(T)). If you have a pointer to assign the array to, you can get the size from that
T * ptr = malloc(10 * sizeof *ptr);
Here *ptr has type T and so sizeof *ptr is the same as sizeof(T), but this syntax is safer for reasons explained in other answers.
When you use
T * ptr = malloc(10 * sizeof(T *));
you do not get memory for 10 T objects, but for 10 T * objects. If sizeof(T*) >= sizeof(T) you are fine, except that you are wasting some memory, but if sizeof(T*) < sizeof(T) you have less memory than you need.
Whether you run into this problem or not depends on your objects and the system you are on. On my system, all pointers have the same size, 8 bytes, so it doesn't really matter if I allocate
char **string_array = malloc(sizeof(char **) * 10);
or
char **string_array = malloc(sizeof(char *) * 10);
or if I allocate
int **int_matrix = malloc(sizeof(int **) * 10);
or
int **int_matrix = malloc(sizeof(int *) * 10);
but it could be on other architectures.
For your third solution, you have a different problem. When you allocate
int **int_matrix2 = malloc(sizeof(int *));
you allocate space for a single int pointer, but you immediately treat that memory as if you had 10
for (int i = 0; i < 10; i++)
{
int_matrix2[i] = malloc(sizeof(int));
}
You can safely assign to the first element, int_matrix2[0] (but there is a problem with how you do it that I get to); the following 9 addresses you write to are not yours to modify.
The next issue is that once you have allocated the first dimension of your matrix, you have an array of pointers. Those pointers are not initialised, and presumably pointing at random places in memory.
That isn't a problem yet; it doesn't do any harm that these pointers are pointing into the void. You can just point them to somewhere else. This is what you do with your char ** array. You point the first pointer in the array to a string, and it is happy to point there instead.
Once you have pointed the arrays somewhere safe, you can access the memory there. But you cannot safely dereference the pointers when they are not initialised. That is what you try to do with your integer array. At int_matrix[0] you have an uninitialised pointer. The type-system doesn't warn you about that, it can't, so you can easily compile code that modifies int_matrix[0][0], but if int_matrix[0] is pointing into the void, int_matrix[0][0] is not an address you can safely read or write. What happens if you try is undefined, but undefined is generally was way of saying that something bad will happen.
You can get what you want in several ways. The closest to what it looks like you are trying is to implement matrices as arrays of pointers to arrays of values.
There, you just have to remember to allocate the arrays for each row in your matrix as well.
#include <stdio.h>
#include <stdlib.h>
int **new_matrix(int n, int m)
{
int **matrix = malloc(n * sizeof *matrix);
for (int i = 0; i < n; i++)
{
matrix[i] = malloc(m * sizeof *matrix[i]);
}
return matrix;
}
void init_matrix(int n, int m, int **matrix)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
matrix[i][j] = 10 * i + j + 1;
}
}
}
void print_matrix(int n, int m, int **matrix)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}
int main(void)
{
int n = 3, m = 5;
int **matrix = new_matrix(n, m);
init_matrix(n, m, matrix);
print_matrix(n, m, matrix);
return 0;
}
Here, each row can lie somewhere random in memory, but you can also put the row in contiguous memory, so you allocate all the memory in a single malloc and compute indices to get at the two-dimensional matrix structure.
Row i will start at offset i*m into this flat array, and index matrix[i,j] is at index matrix[i * m + j].
#include <stdio.h>
#include <stdlib.h>
int *new_matrix(int n, int m)
{
int *matrix = malloc(n * m * sizeof *matrix);
return matrix;
}
void init_matrix(int n, int m, int *matrix)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
matrix[m * i + j] = 10 * i + j + 1;
}
}
}
void print_matrix(int n, int m, int *matrix)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
printf("%d ", matrix[m * i + j]);
}
printf("\n");
}
}
int main(void)
{
int n = 3, m = 5;
int *matrix = new_matrix(n, m);
init_matrix(n, m, matrix);
print_matrix(n, m, matrix);
return 0;
}
With the exact same memory layout, you can also use multidimensional arrays. If you declare a matrix as int matrix[n][m] you will get what amounts to an array of length n where the objects in the arrays are integer arrays of length m, exactly as on the figure above.
If you just write that expression, you are putting the matrix on the stack (it has auto scope), but you can allocate such matrices as well if you use a pointer to int [m] arrays.
#include <stdio.h>
#include <stdlib.h>
void *new_matrix(int n, int m)
{
int(*matrix)[n][m] = malloc(sizeof *matrix);
return matrix;
}
void init_matrix(int n, int m, int matrix[static n][m])
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
matrix[i][j] = 10 * i + j + 1;
}
}
}
void print_matrix(int n, int m, int matrix[static n][m])
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}
int main(void)
{
int n = 3, m = 5;
int(*matrix)[m] = new_matrix(n, m);
init_matrix(n, m, matrix);
print_matrix(n, m, matrix);
int(*matrix2)[m] = new_matrix(2 * n, 3 * m);
init_matrix(2 * n, 3 * m, matrix2);
print_matrix(2 * n, 3 * m, matrix2);
return 0;
}
The new_matrix() function returns a void * because the return type cannot depend on the runtime arguments n and m, so I cannot return the right type.
Don't let the function types fool you, here. The functions that take a matrix[n][m] argument do not check if the matrix has the right dimensions. You can get a little type checking with pointers to arrays, but pointer decay will generally limit the checking. The last solution is really only different syntax for the previous one, and the arguments n and m determines how the (flat) memory that matrix points to is interpreted.
The method 1 works only becuse you assign the char * element of the array string_array with the reference of the string literal `"Hi there". String literal is simply a char array.
Try: string_array[0][0] = 'a'; and it will fail as well as you will dereference not initialized pointer.
Same happens in method 2.
Method 3. You allocate the memory for one int value and store the reference to it in the [0] element of the array. As the pointer references the valid object you can derefence it (int_matrix2[0][0] = 42;)

C SegFault fixed by print?

I have the task to write a program in C. The program should be able to check for parameters and create arrays that are as big as the parameter I gave. I have to fill the array with random numbers. Works fine so far. Later on my task is to sort the array using pointers. First thing is I did not quite understand how pointers work but I made the sorting work so far. The only problem is, that I can only sort to a size of 4. If my parameter is bigger than 4 I get the first 4 numbers sorted and then a Segmentation fault. I cannot find the issue but the fun part is, that if I add a printf just to print my parameter again it works fine for any parameter I want! I do not know what is happening!
Here is the exact task again, because I think I didn't describe it that well:
To do this, create a dynamic pointer field of the same size and initialize it with pointers to the elements of the int field. When sorting, the pointers should now be sorted so that the first pointer points to the smallest int value, the second to the next largest value, and so on.
int main(int argc, char *argv[]) {
int *array;
int **arrpointer;
int size = atoi(argv[1]);
if (size == 0) {
fprintf(stderr, "Wrong parameter!\n");
return EXIT_FAILURE;
}
//printf("Array-Size : "); //First I had it with scanf, which works perfectly fine without a print
//scanf("%d", &size);
printf("Input%d", size); //This is the print I need somehow!
// allocate memory
array = (int *)malloc(size * sizeof(int)); // Init Array
arrpointer = (int **)malloc(size * sizeof(int)); // Init Pointer Array
//Check Pointer array
if (arrpointer != NULL) {
printf("Memory allocated\n\n");
} else {
fprintf(stderr, "\nNo free memory.\n");
return EXIT_FAILURE;
}
if (array != NULL) {
printf("Memory is allocated\n\n");
//Fill Array
for (int i = 0; i < size; i++) {
array[i] = rand() % 1000; //I know it is not random right now, will add later
int *temp = &array[i];
arrpointer[i] = temp; //Pointer fill
}
} else {
fprintf(stderr, "\nNo free memory to allocate.\n");
return EXIT_FAILURE;
}
shakersort(arrpointer, size); //Function to sort pointers
zeigeFeld(arrpointer, size); //Function to Print
free(array);
free(arrpointer);
return EXIT_SUCCESS;
}
I know its a bit confusing, I am sorry.
I will also add the code where I sort it below.
void swap(int **a, int **b) {
int ram;
ram = **a;
**a = **b;
**b = ram;
}
void shakersort(int **a, int n) {
int p, i;
for (p = 1; p <= n / 2; p++) {
for (i = p - 1; i < n - p; i++)
if (*a[i] > *a[i+1]) {
swap(&a[i], &a[i + 1]);
}
for (i = n - p - 1; i >= p; i--)
if (*a[i] < *a[i-1]) {
swap(&a[i], &a[i - 1]);
}
}
}
This is the code I tried to build for the pointers and it works fine so far.
I hope someone can help or give some input to why my print fixes the problem. I really dont understand!
Thank you for your time and help, let me know if I should add anything!
The program has undefined behavior because the allocation size is incorrect for the array:
arrpointer = (int **)malloc(size * sizeof(int));
allocates space for size integers, but it should allocate space for size pointers to int, which on 64-bit systems are larger than int. Use this instead:
arrpointer = (int **)malloc(size * sizeof(int *));
Or use the type of the destination pointer:
arrpointer = malloc(sizeof(*arrpointer) * size);
This latter syntax is much safer as it works for any non void pointer type.
Note however that this array of pointers is overkill for your purpose. You should just implement the sorting functions on arrays of int:
void swap(int *a, int *b) {
int ram = *a;
*a = *b;
*b = ram;
}
void shakersort(int *a, int n) {
int p, i;
for (p = 1; p <= n / 2; p++) {
for (i = p - 1; i < n - p; i++) {
if (a[i] > a[i + 1]) {
swap(&a[i], &a[i + 1]);
}
}
for (i = n - p - 1; i >= p; i--) {
if (a[i] < a[i - 1]) {
swap(&a[i], &a[i - 1]);
}
}
}
}
Whether the above code actually sorts the array is unclear to me, I never use shakersort.
why do you use pointers before printf??
first you need to know what the pointer is:
the pointer is some kind of variable that contains address of some another variable.
for example:
int b = 2;
int * a = &b;
a variable include the address of variable b. then if you print ((a)) it will give you hex number which is the address of b. if you print ((*a)), compiler will print what in the address that int the variable a and print the amount of number in address of cell b(that means 2).
now i guess you understand what the pointer is, look again at your code and correct the mistakes.
I updated my code from
arrpointer = (int **) malloc(size * sizeof(int));
to
arrpointer = malloc(sizeof *arrpointer * size);
And it works fine!
Thank you all for your help!

Trying to append elements to multi-dimensional array. Exception thrown when trying to run the application

int main()
{
int r;
scanf("%d", &r);
int **arr = (int *)malloc(r * r * sizeof(int));
*(*(arr + r) + r);
for (int i = 1; i <= r; i++)
{
for (int j = 1; j <= r; j++)
{
printf("Enter element %d.%d: \n", i,j);
scanf("%d", &arr[i-1][j-1]);
}
}
getch();
}
so this recently happened, basically what I want is to append matrix elements to 2d array, but it says
'Exception thrown at 0x0F1B97AE (ucrtbased.dll) in Matrix.exe: 0xC0000005: Access violation writing location 0xCDCDCDCD'
don`t know what to do :( help please
You're using a malloc'ed block of memory as a C multi-dimensional array. Instead, you need to use a single set of square brackets.
Instead of arr[i-1][j-1], you need something like arr[i * r + j].
I'm surprised that most compilers would accept this by default because you use an int * to initialize and int **.
The problem is that you don't allocate or create a "two-dimensional" array. Your memory allocation allocates one array of r * r elements.
This single array can't be used as an array of arrays.
The usual solution to create a dynamic array of arrays is to create a jagged array:
int **arr = malloc(r * sizeof(int *));
for (unsigned i = 0; i < r; ++i)
{
arr[i] = malloc(r * sizeof(int));
}
You can use a large single array in a "two-dimensional" way, but you need to use some other arithmetic to access the elements of it:
arr[i * r + j]
[Note that the above requires zero-based indexes i and j]
int **arr = (int *)malloc(r * r * sizeof(int));
You can't create a 2D array with a single allocation like that, at least not one you can access with a int **. What you have instead is space for r * r, objects of type int which can be accessed via a int * and some additional arithmetic.
When you later do this:
*(*(arr + r) + r);
The first dereference is fine, since arr points to an allocated buffer. The second one is not, however, because you read an uninitialized value from that allocated buffer and attempt to use to as a valid address. This invokes undefined behavior which in this cause results in a crash.
You need to allocate space for an array of int *, they for each of those allocate an array of int:
int **arr = malloc(r * sizeof(int *));
for (int i=0; i<r; i++) {
arr[i] = malloc(r * sizeof(int));
}
Just forget all about this int** nonsense and allocate a 2D array instead:
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int r;
scanf("%d", &r);
int (*arr)[r] = malloc( sizeof(int[r][r]) );
for (int i = 0; i<r; i++)
{
for (int j = 0; j<r; j++)
{
arr[i][j] = 1; // some sort of input here
printf("%d ", arr[i][j]);
}
printf("\n");
}
free(arr);
}
Output example with input 5:
5
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
For this to work, you need a standard-compliant C compiler from this millennium.
More information: Correctly allocating multi-dimensional arrays.

Sorting array of strings with qsort

This program takes an integer value which then determines the amount of strings that can be inputted, once the user has entered the amount of strings that they specified they may input another integer and then input those amount of strings. Once done the program sorts the strings based on their lengths in descending order. However the qsort doesn't work, it ends up outputting how the order of when the strings were originally entered.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int sort(const void * a, const void * b){
size_t fa = strlen((const char *)a);
size_t fb = strlen((const char *)b);
return (fa < fb) - (fa > fb);
}
int main(void){
char pointer[100];
int n;
scanf("%d", &n);
char** strings = malloc(n * sizeof(char*));
int i;
for (i = 0; i < n; i++){
scanf("%s", pointer);
strings[i] = malloc(sizeof(char) * (strlen(pointer) + 1));
strcpy(strings[i], pointer);
}
int m;
scanf("%d", &m);
strings = realloc(strings, (n + m) * sizeof(char*));
for (i = n; i < m + n; i++){
scanf("%s", pointer);
strings[i] = malloc(sizeof(char) * (strlen(pointer) + 1));
strcpy(strings[i], pointer);
}
int a;
int g;
int k = m + n;
qsort(strings , a, 100, sort);
for (g = 0; g < k; g++){
printf("%s", strings[g]);
printf("\n");
}
}
You're not calling qsort correctly at all.
The 2nd parameter is the number of elements in the "array" that you are sorting. You're currently passing it a which as others have pointed out isn't set to anything. Compiling your code with the "-Wall" option will show you those kinds of errors.
The 3rd parameter is the size of one of the elements in the "array", but you've confused this with the size of an unrelated variable pointer? You could write it like sizeof(strings[0]).
The finished call should look like qsort(strings,k,sizeof(strings[0]),sort);.
But that still won't work because your sort() function is being passed two pointers to elements in your "array" (char **) and you're treating them as two elements of the "array" (char *). So you'd want something like
size_t fa = strlen(*(char **)a);
Well, this:
int a;
int g;
int k = m + n;
qsort(strings , a, 100, sort);
makes no sense at all, a has no value so this is undefined behavior.
Also sort() is broken, it should just be strcmp().

C: adding elements to an array

I'm trying to test a program that creates an array with 0 elements in it, then adds elements to it (reallocating memory each time), and then printing out the elements. But, I keep getting errors when I try to run it.
int main(int argc, const char * argv[]) {
int num = 0;
int n = 10;
int **array = malloc(0);
for (int i = 0; i < n; ++i)
{
++num;
array = realloc(array, num * sizeof(int*));
array[num-1] = &i;
}
for (int j = 0; j < n; ++j)
{
printf("%d", &array[j]); // error 1
}
return 0;
}
I'm sorry I didn't include the errors with the original post. I think I fixed one of them. Here is the other:
Error 1: Format specifies type 'int' but the argument has type 'int *'
This answer is based on the assumption that you are printing a simple array, since you don't show what output you expect. You are using one more step of indirection than you need, and too many variables. Take note that indexing is different from length (often by 1).
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int i, n = 10;
int *array = NULL; // no need for double star, or fake allocation
for (i = 0; i < n; ++i)
{
array = realloc(array, (i + 1) * sizeof(int)); // remove the *, add 1 for num elements
array[i] = i;
}
for (i = 0; i < n; ++i)
{
printf("%d", array[i]); // remove the &
}
free(array); // don't forget this
return 0;
}
Program output:
0123456789
In practice, you should assign the result of realloc to another pointer variable, check it's ok, and then replace the original pointer var.
printf("%d", &array[j]); // error 1
The & is the address operator. So it is making something a pointer. Your array is already an array of pointers to integer.
By using the & you are trying to print the address of the integer pointer itself.
Try using * instead of &. * means that you want to print the value of the integer pointer.
printf("%d", *array[j]); // error 1

Resources