Copying first half of dynamic array into second half failed in C? - c

I wanted to copy the first half of my dynamic array into the second half of the same array, but the output here is from ptr[100] to ptr[200] 9.90. I think I coded everything fine but I dont know where the problme is. Can you help me?
#include <stdio.h>
#include <stdlib.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char *argv[]) {
int i;
int j;
double * ptr = calloc(100, sizeof(double));
if (ptr == NULL)
return 0;
for(i = 0; i < 100; i++) {
ptr [i] = i / 10.0;
}
for(i = 0; i < 100; i++) {
printf("ptr[%d] = %.2f\n", i, ptr[i]);
}
if (realloc(ptr, 200) == NULL)
return 0;
for (i = 0; i < 100; i++)
for (j = 100; j < 201; j++)
ptr [j] = ptr[i];
for (j = 100; j < 201; j++)
printf("ptr[%d] = %.2f\n", j, ptr[j]);
return 0;
}

You are underallocating on the realloc. You didn't make enough space for 200 doubles, so attempting to access ptr[x] is undefined behavior for values of x > 99. Also, realloc may move the memory, so you need to assign the new value back to ptr. For example:
ptr = realloc(ptr, 200 * sizeof *ptr);
if( ptr == NULL ){
perror("realloc");
exit(1);
}
And after this, accessing ptr[200] is undefined behavior. You need to reduce the scope of the loop index to for( j = 100; j < 200; j++ )

You are overwriting for every copy
for (i = 0; i < 100; i++) // for every item in the first half
for (j = 100; j < 201; j++) // into every cell
ptr [j] = ptr[i];
shoud be
for (i = 0; i < 100; i++)
ptr [i+100] = ptr[i];
and issue 2:
you didn't raallocate enough memory : change realloc(ptr, 200) to realloc(ptr, 200 * sizeof(double))

Related

Reallocing and manipulating a 2d-array inside a function

I am trying to reallocate both elements of a 2D-array and also manipulate the values in the 2D-array within the same function. But I just can't seem to get it to work. On compiling the code doesn't show any errors, but when running it will only ever print the amount of lines I specified as the initial_size at the beginning of the main function.
So it seems that the inner realloc is working fine, as it always prints an entire row once it gets started. But the outer realloc is not working, as it will only print a couple of rows.
Note: The real code takes input of unknown size, from getchar() / scanf(). That is why the realloc functions are inside loops in the function.
Simplified version of the function, with error handling omitted:
void func(int ***A) {
int i, j;
int len = 2;
int len2 = 2;
for (i = 0; i < 10; i++) {
// Check to see if a realloc is needed.
if (i >= len) {
len *= 2;
int **tmp = realloc(*A, len * sizeof(int*));
*A = tmp;
printf("Len1 = %d\n", len);
}
len2 = 2;
for (j = 0; j < 20; j++) {
// Check to see if a realloc is needed.
if (j >= len2) {
len2 *= 2;
int *new_row = realloc((*A)[i], len2 * sizeof(int));
(*A)[i] = new_row;
}
// Assign value.
(*A)[i][j] = i * j;
}
}
}
int main() {
int i, j;
int initial_size = 2;
int **A;
// Malloc with a starting size of 2 (could be any size).
A = malloc(initial_size * sizeof(int*));
for (i = 0; i < initial_size; i++) {
A[i] = malloc(initial_size * sizeof(int));
}
// Call function.
func(&A);
// Print the results, row by row.
for (i = 0; i < 10; i++) {
for (j = 0; j < 20; j++) {
printf("%d, ", A[i][j]);
}
printf("\n");
}
return 0;
}
I have been stuck for a while now, so any help is greatly appreciated :)
When you realloc in the outer loop, you increase the numbers of pointers from two (those created in main) to four.
The value of the two pointers from main are copied to the new memory area.
The value of the two new pointers are indeterminate and that's your problem. You never initialize them by allocating memory - yet you use them in the other loop.
Further, it seems that you realloc the inner array dimensions individually but you only track one length (i.e. len2). That's also a problem.
And the line len2 = 2 between the loops are wrong as you loose information about previously allocated memory.
There are multiple problems in your code:
you reallocate the pointer array but do not initialize the pointers in the newly allocated portion
you only reallocate the first int array pointed to by the pointer array
you do not initialize the newly allocated area in this int array.
Note that 2D-matrices are more idiomatic in C as arrays of arrays, but it is difficult to manipulate such arrays when the outer dimension is not fixed at compile time.
You should use a reallocation function with specified dimensions for the current and target sizes and deal with reallocating and freeing the blocks appropriately. Also avoid triple pointers: just return the potentially reallocated outer array.
#include <stdio.h>
#include <stdlib.h>
int **func(int **A, int rows, int cols, int new_rows, int new_cols) {
int i, j;
/* free the rows that are discarded */
if (new_rows < rows) {
for (i = new_rows; i < rows; i++) {
free(A[i]);
}
}
/* free the outer array if new rows is zero */
if (new_rows == 0) {
free(A);
return NULL;
}
/* reallocate the outer array if required */
if (new_rows != rows) {
A = realloc(A, sizeof(*A) * new_rows);
}
/* reallocate the existing rows */
if (new_cols != cols) {
for (i = 0; i < rows; i++) {
A[i] = realloc(A[i], sizeof(int) * new_cols);
if (new_cols > cols) {
for (j = cols; j < new_cols; j++)
A[i][j] = 0;
}
}
}
/* allocate the new rows (initialized to 0) */
for (i = rows; i < new_rows; i++) {
A[i] = calloc(sizeof(int), new_cols);
}
return A;
}
int main() {
int **A = NULL;
/* reallocate to 10x20 */
A = func(A, 0, 0, 10, 20);
// Print the results, row by row.
for (i = 0; i < 10; i++) {
for (j = 0; j < 20; j++) {
printf("%d, ", A[i][j]);
}
printf("\n");
}
/* reallocate to 0x0 (free the matrix) */
func(A, 10, 20, 0, 0);
return 0;
}
Note that the above code does not check for memory allocation failure. To deal with this possibility, it would be much simpler to allocate a new array and copy the current values, then free the previous matrix if no allocation error occurred. It would also be more efficient to allocate all rows as a single block of memory. Below is an example of this approach:
#include <stdio.h>
#include <stdlib.h>
int **func(int **A, int rows, int cols, int new_rows, int new_cols) {
int i, j;
int **B = NULL;
if (new_rows == rows && new_cols == cols)
return A;
if (new_rows != 0 && new_cols != 0) {
/* allocate the new matrix */
B = malloc(sizeof(*B) * new_rows);
if (B == NULL)
return NULL;
B[0] = calloc(sizeof(int) * new_cols, new_rows);
if (B[0] == NULL) {
free(B);
return NULL;
}
/* initialize the row pointers */
for (i = 1; i < new_rows; i++) {
B[i] = B[i - 1] + new_cols;
}
/* copy the current data */
for (i = 0; i < new_rows && i < rows; i++) {
for (j = 0; j < new_cols && j < cols; i++) {
B[i][j] = A[i][j];
}
}
}
/* free the previous matrix */
if (A != NULL) {
free(A[0]);
free(A);
}
return B;
}
int main() {
int **A = NULL;
int i, j;
/* reallocate to 10x20 */
A = func(A, 0, 0, 10, 20);
if (A == NULL) {
printf("Matrix reallocation failed\n");
return 1;
}
// Print the results, row by row.
for (i = 0; i < 10; i++) {
for (j = 0; j < 20; j++) {
printf("%d, ", A[i][j]);
}
printf("\n");
}
/* reallocate to 0x0 (free the matrix) */
func(A, 10, 20, 0, 0);
return 0;
}

Segmentation fault error with my minesweeper code in C

So I have been trying to solve this problem where I have to write a code that counts the number of mines that are around a certain point on a imaginary minefield. Here is the code:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int row;
int col;
int count;
int mineCount = 0;
int i;
int j;
// allocating memory
scanf("%d %d", &row, &col);
char **m = malloc(sizeof(char* ) * row);
for(i = 0; i < row; i ++)
{
m[i] = malloc(sizeof(char) * (col + 1)); //empty minefield
}
//planting mines
for(count = 0; count < row; count ++)
{
scanf("%s", m[count]);
}
// counting mines
for(i = 0; i < row; i ++)
{
for(j = 0; j < (col + 1); j ++)
{
if(m[i][j] != 42)
{
if(m[i-1][j] == 42)
mineCount += 1;
if(m[i+1][j] == 42)
mineCount += 1;
if(m[i][j+1] == 42)
mineCount += 1;
if(m[i][j-1] == 42)
mineCount += 1;
if(mineCount > 0)
m[i][j] = mineCount;
}
}
}
//printing out the minefield
for(i = 0; i < row; i ++)
{
for(j = 0; j < col; j ++)
printf("%c", m[i][j]);
printf("\n");
}
return 0;
}
I put '5 5' for the first input, and for the minefield, my input would be something like this:
*....
..*..
...*..
.*...
....*
at the end though, I get this 'segmentation fault (Core dumped)' error. I have been searching around for answers and found out that this happens when I try to access something that I have no access to. Any help would be appreciated. Thanks.
if(m[i-1][j] == 42)
if(m[i][j-1] == 42)
For these statements you need to have checks if i and j are not 0, otherwise you are accessing invalid memory
Third input of ...*.. // 6 char long will make
//planting mines
for(count = 0; count < row; count ++)
{
scanf("%s", m[count]);
}
to buffer overflow and write an extra . to out-of-bound memory.
Also, I don't see any free, assuming you must have implemented that.
Have a look at if(m[i+1][j]). If i=row-1 this will be equal to row. But as you only allocated row values and the addressing starts at 0 row-1 is the highest value, which you are able to address.
And also at if (m[i-1][j]) and if(m[i][j-1]) when i or j is zero respectively.

C pointers 2 dimensional move to top

I'm quite new to pointers and C in general.
void moveUpToTop(int num, int dim, int index) {
int i,j;
double *temp = w[index];
double *zero = w[0];
for(i = index; i > 0; i--) {
double *ptrA = w[i];
double *ptrB = w[i - 1];
for(j = 0; j < dim; j++) {
*(ptrA + j) = *(ptrB + j);
}
}
for(j = 0; j < dim; j++) {
*(zero + j) = *(temp + j);
}
}
Having this with a 2-dimensional array w, defined as double **w. I'd like to move some array value with index "index" up to the top of the array using pointers because that is the exercise we've got to do.
first of all, I'm saving one of the array locations, then I'm moving all array locations one level up.
What am I doing wrong?
Given to me is the following code in what I have to design the sort function.
double **w;
int main (void) {
int dim, num;
int i, j;
scanf ("%d %d", &dim, &num);
w = calloc (num, sizeof (double *));
for (i = 0; i < num; i++) {
w[i] = calloc (dim + 1, sizeof (double));
int sum = 0;
for (j = 0; j < dim; j++) {
scanf ("%le", &w[i][j]);
sum += w[i][j] * w[i][j];
}
w[i][dim] = sqrt(sum);
}
sort(num, dim);
for(i = 0; i < num; i++) {
for(j = 0; j < dim; j++) {
printf("%e ", w[i][j]);
}
printf("\n");
}
return 0;
}
Your problem is that you save a pointer to the original data but you don't save the data itself.
double *temp = w[index]; // Here you save the pointer
but in the first loop you overwrite data:
for(i = index; i > 0; i--) {
double *ptrA = w[i]; // Same as w[index] in first loop
double *ptrB = w[i - 1];
for(j = 0; j < dim; j++) {
*(ptrA + j) = *(ptrB + j); // The data pointed to by w[index] is overwritten
// in the first loop
So this code is no copying the original data at index:
for(j = 0; j < dim; j++) {
*(zero + j) = *(temp + j); // Data at index have been overwritten
// so this doesn't do what you want
}
To fix this, it is not sufficient to save a pointer to index(i.e. double *temp = w[index];). Instead you need to save all data that double *temp = w[index]; points to.
So you need to malloc some data to hold a copy. Then copy the data in a for-loop and use the copied data when restoring to zero.
BTW: Also notice that the code given to you uses a very ugly construct. It is allocating dim + 1 to save an extra double. Your move function therefore also need to use dim + 1 instead of just dim

C malloc (Segmentation fault: 11)

I'm trying to understand malloc but I keep getting "Segmentation fault: 11" with this piece of code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i = 0, j = 0;
char ** ptr = (char **) malloc(sizeof(char*));
for(i = 0; i < 5; i++)
{
for(j = 0; j < 10; j++)
ptr[i][j] = 'a';
printf("%s\n", ptr[i]);
}
return 0;
}
I thought there wasn't enough bytes being allocated so I did malloc(sizeof(char*) * 100, but gives me the same error. What am I not understanding here?
When you allocate a 2D array, you need to allocate the individual sub-arrays as well. In addition, you need to say how many elements you wish to have. For that you multiply the desired count by the number of elements, like this:
char ** ptr = (char **) malloc(5*sizeof(char*));
// Size=5 ---------------------^
for(int i = 0; i < 5; i++) {
ptr[i] = malloc(11*sizeof(char));
// sizeof(char) is always 1, so the multiplication above is redundant.
// You need 11 elements for ten characters
for(int j = 0; j < 10; j++) {
ptr[i][j] = 'a';
}
// don't forget to null-terminate the string:
ptr[i][10] = '\0';
printf("%s\n", ptr[i]);
}
Your code is totally messed up in every aspect!
1) you allocated memory for exactly 1 Pointer to it. This means you can access ptr[0], but not ptr[1] ... ptr[4] as you are trying to do.
2) you never allocate anything for the elements in ptr[i].
3) you try to print a string a ptr[i] which is (even if your allocation would be right) never terminated.
4) although this is obviously only a beginners test, never forget to free your memory!!!!
To reach something CLOSE to what your sampel code is describing you could do:
int main()
{
int i,j;
char ** ptr = malloc( 5 * sizeof(char*) ); /* an array of 5 elements of type char* */
for(i = 0; i < 5; i++)
{
ptr[i] = malloc( 11*sizeof(char) ); /* The element i of the array is an array of 11 chars (10 for the 'a' character, one for the null-termination */
for(j = 0; j < 10; j++)
ptr[i][j] = 'a';
ptr[i][10] = '\0'; /* strings need to be null terminated */
printf("%s\n", ptr[i]);
}
// free your memory!
for (i=0; i<5; i++ )
{
free(ptr[i]);
}
free(ptr);
return 0;
Another way to allocate the memory is:
char (*ptr)[11] = malloc( sizeof(char[5][11]) );
for(i = 0; i < 5; i++)
{
for(j = 0; j < 10; j++)
ptr[i][j] = 'a';
ptr[i][10] = 0;
printf("%s\n", ptr[i]);
}
free(ptr);
It seems less hassle to use a single allocation than to use a lot of allocations, unless you have a pressing reason to do the latter.

Allocating dynamic 2D char array

gcc 4.6.2 c89
Allocating memory for a 2D array and filling with characters.
However, I don't seem to be filling as when I print nothing is displayed.
Am I doing something wrong here?
char **attributes = NULL;
/* TODO: Check for memory being allocated */
attributes = malloc(3 * sizeof(char*));
int i = 0;
int k = 0;
for(i = 0; i < 3; i++) {
for(k = 0; k < 5; k++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
sdp_attributes[i][k] = k;
}
}
for(i = 0; i < 3; i++) {
for(k = 0; k < 5; k++) {
printf("attributes[i][k] [ %c ]\n", attributes[i][k]);
}
}
Many thanks for any advice,
Two major issues:
First Issue:
for(i = 0; i < 3; i++) {
for(k = 0; k < 5; k++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
You are reallocating sdp_attributes[i] at each iteration of the inner loop - thereby overwriting it each time. You probably wanted this instead:
for(i = 0; i < 3; i++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
for(k = 0; k < 5; k++) {
Second Issue:
sdp_attributes[i][k] = k;
You are basically writing the lower ascii characters. Most of them are not printable.
Something like this might do what you want:
sdp_attributes[i][k] = k + '0';
You probably want:
for (i = 0; i < 3; i++)
{
attributes[i] = malloc(5 * sizeof(char));
for (k = 0; k < 5; k++)
{
attributes[i][k] = k;
}
}
This ignores error checking on the allocation.
It also fixes the name of the array to match the declaration, but your code either wasn't compiling (don't post non-compiling code unless your question is about why it doesn't compile!) or you have another variable called sdp_attributes declared somewhere which you weren't showing us.
Your code was leaking a lot of memory. Each time around the k-loop, you allocated a new array of 5 characters and stored the pointer in attributes[i] (or sdp_attributes[i]), storing the new pointer over what was there before, so you overwrote the value of the first 4 pointers. You could not possibly free the first four items - they were lost irretrievably. Also, on the last iteration, you initialized the 5th element of the final array, but the previous 4 were not initialized and therefore contained indeterminate garbage.
Also, in your printing loop, the values in the array are control characters ^#, ^A, ^B, ^C and ^D; these do not necessarily print well with %c (especially not ^#, which is also known as NUL or '\0'). The printf() statement might be better written as:
printf("attributes[%d][%d] [ %d ]\n", i, k, attributes[i][k]);
This prints the array indexes (rather than simply the characters [i][k] for each entry), and prints the control characters as integers (since the char values are promoted to int when passed to printf()) rather than as control characters.
(It's also more conventional to use i and j for a pair of nested loops, and i, j, and k for triply nested loops, etc. However, that's a very minor issue.)
for(i = 0; i < 3; i++) {
for(k = 0; k < 5; k++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
sdp_attributes[i][k] = k;
}
}
Your erasing the allocated memory every time you loop in the inner most loop.
Here is a correct version.
for(i = 0; i < 3; i++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
for(k = 0; k < 5; k++) {
sdp_attributes[i][k] = k;
}
}
And you should fix your declaration:
attributes = malloc(3 * sizeof(char*));
to
sdp_attributes = malloc(3 * sizeof(char*));
Don't forget to free up all the memory allocated
for(i = 0; i < 3; i++)
{
free(sdp_attributes[i]);
}
free(sdp_attributes);
The correct way to allocate and assign elements to 2d array is as follows (but this is a int array, you can try and change it for char array):
One thing to note: As mentioned by #Mysticial, you should add/subtract '0' to your int value to get the char value when using ASCII character set (remember our itoa() functions!).
#include <stdio.h>
#include <stdlib.h>
int main()
{
int row, column;
int **matrix;
int i, j, val;
printf("Enter rows: ");
scanf("%d", &row);
printf("Enter columns: ");
scanf("%d", &column);
matrix = (int **) malloc (sizeof(int *) * row);
for (i=0 ; i<row ; i++)
matrix[i] = (int *) malloc (sizeof(int) * column);
val=1;
for (i=0 ; i<row ; i++) {
for (j=0 ; j<column; j++) {
matrix[i][j] = val++;
}
}
for (i=0 ; i<row ; i++) {
for (j=0 ; j<column; j++) {
printf("%3d ", matrix[i][j]);
}
printf("\n");
}
for (i=0 ; i<row ; i++)
free(matrix[i]);
free(matrix);
return 0;
}
Few points to note:
error handling should be added for malloc()
malloc()'ed memory must be free()'ed

Resources