/*Jeremy Johnson 11-18-48
*
*The purpose of this program to to swap halves of an array. So {1 2 3 4 5 6}
*becomes {4 5 6 1 2 3} using pointer notation.
*/
#include <stdio.h>
#include <string.h>
int array[] = {1, 2, 3, 4, 5, 6}; //initialize array
void mirror(int* array, int from_index, int to_index); //prototype statment
int main() {
//define and assign pointer to array address
int *arrptr, i;
arrptr = &array[0];
//print original array
printf("Original Array: \n");
for (i = 0; i <= 5; i++) {
printf("%d", array[i]);
}
printf("\n");
//call function to swap values and mirror the array
mirror(arrptr, 0, 2);
mirror(arrptr, 3, 5);
mirror(arrptr, 0, 5);
mirror(arrptr, 1, 4);
mirror(arrptr, 2, 3);
//print final array
printf("Mirror Array: \n");
for (i = 0; i <= 5; i++) {
printf("%d", array[i]);
}
printf("\n");
return 0;
}
void mirror(int* array, int from_index, int to_index) {
//create pointer for temporary memory storage
int *temp, c[1];
temp = &c[0];
//Place to_index in temporary memory
*(temp) = *(array + to_index-1);
//Copy from_index to to_index
*(array + to_index-1) = *(array + from_index-1);
//Copy temporary value back into from_index
*(array + from_index-1) = *(temp);
return;
}
/* This code works for the function however I am not allowed to use array
notation.
c[1]=array[to_index];
array[to_index]=array[from_index];
array[from_index]=c[1]; */
I am trying to swap each half of the array; I have done so by switching the indices of the arrays by calling the mirror function 5 times and swapping the appropriate values. I was able to do so using the commented code at the bottom in place of the current function code, but now I receive and exit value 5, and I'm not sure why. (I receive no other errors within the code)
// perhaps swap the array by:
void mirror( int*, int* );
int main()
{
...
int *pSecondHalf = array[(sizeof(array)/sizeof(int))>>1];
// note: above line will not work for odd size array so:
if( array[(sizeof(array)/sizeof(int)] & 0x01 )
{
pSecondHalf++; // middle term in odd size array will not move
}
int *pFirstHalf = array;
const int *pLastHalf = array+((sizeof(array)/sizeof(int))>>1);
// note: following 'for' loop will execute one extra time
// for odd size array, but nothing will be changed
for( ; pFirstHalf < pLastHalf; pFirstHalf++, pSecondHalf++ )
{
mirror( pFirstHalf, pSecondHalf );
}
...
return(0);
}
// and in mirror()
void mirror( int *pVal1, int* pVal2)
{
int temp = *pVal1;
*pVal1 = *pVal2;
*pVal2 = temp;
}
The problem was in the mirror function. I did not move each element of the array to the temporary array using a for loop (aka counting loop). I added two loops to the function and it runs fine now.
/*Jeremy Johnson 11-18-48
*
*The purpose of this program to to swap halves of an array. So {1 2 3 4 5 6}
*becomes {4 5 6 1 2 3} using pointer notation.
*/
#include <stdio.h>
#include <string.h>
int array[] = {1, 2, 3, 4, 5, 6}; //initialize array
void mirror(int* array, int from_index, int to_index); //prototype statement
int main() {
//define and assign pointer to array address
int *arrptr, i;
arrptr = &array[0];
//print original array
printf("Original Array: \n");
for (i = 0; i <= 5; i++) {
printf("%d", array[i]);
}
printf("\n");
//call function to swap values and mirror the array
mirror(arrptr, 0, 2);
mirror(arrptr, 3, 5);
mirror(arrptr, 0, 5);
//print final array
printf("Mirror Array: \n");
for (i = 0; i <= 5; i++) {
printf("%d", array[i]);
}
printf("\n");
return 0;
}
void mirror(int* array, int from_index, int to_index) {
//create pointer for temporary memory storage
int *temp, c[6], j;
temp = &c[0];
//Place array elements in temporary memory
for (j = 0; j < 6; j++) {
*(temp + j) = *(array + j);
}
//Place mirrored halves in array respectively
for (j = 0; j <= (to_index - from_index); j++) {
*(array + from_index + j) = *(temp + to_index - j);
}
return;
}
Related
With my programm I try to change the order of numbers in the int array. To the first function, I just passed both arrays and printed the array called arraytemp with the changed order. After that I printed in the main function the same array, just to see if the array was filled too. I havented used any pointers in the first function - how did the array got filled? Does the arrays adress get passed to functions anyway?
Then I wanted to pass arrays with the same content to the second function, but this time I used pointers. I have no clue, how to get the same result printed, because I get a stack smashing error. I am kinda comfused with '*' and '&'. So, how should I pass these arrays when using pointers?
#include <stdio.h>
void switchnum (int arraytemp[6], int array[], int laenge) {
printf("\n\nAfter (in function 1):\n");
for(int i = 0 ; i<laenge ; i++) {
arraytemp[i] = array[laenge-1-i];
printf("%d ", arraytemp[i]);
}
return 0;
}
void switchnum2 (int *arraytemp2[6], int array2[], int laenge2) {
printf("\nAfter (in function2):\n");
for(int j = 0 ; j<laenge2 ; j++) {
arraytemp2[j] = array2[laenge2-1-j];
printf("%d ", arraytemp2[j]);
}
return 0;
}
int main() {
int array[] = {4,8,1,3,0,9};
int arraytemp[6];
printf("Before (main):\n");
for(int i = 0 ; i<6 ; i++) {
printf("%d ", array[i]);
}
switchnum(arraytemp, array, 6);
printf("\nAfter (in main):\n");
for(int i = 0 ; i<6 ; i++) {
printf("%d ", arraytemp[i]);
}
int array2[] = {4,8,1,3,0,9};
int arraytemp2[6];
switchnum2(arraytemp2, array2, 6);
return 0;
}
The compiler adjusts a parameter having an array type to pointer to the array element type.
So this function declaration
void switchnum (int arraytemp[6], int array[], int laenge);
is equivalent to the following declaration
void switchnum (int arraytemp[], int array[], int laenge);
and the same way is equivalent to the following declaration
void switchnum (int *arraytemp, int *array, int laenge);
As for this function declaration
void switchnum2 (int *arraytemp2[6], int array2[], int laenge2);
then it is adjusted by the compiler to the declaration
void switchnum2 (int **arraytemp2, int *array2, int laenge2);
So the used argument expression and the function parameter have incompatible pointer types.
Pay attention to that in this call
switchnum(arraytemp, array, 6);
the both arrays are converted to pointers to their first elements of the type int *.
In fact this call is equivalent to
switchnum( &arraytemp[0], &array[0], 6);
How to pass pointer of arrays to functions
In this case you are trying to pass an array of pointers to a function and not a pointer of arrays:
void switchnum2(
int* arraytemp2[6], int array2[], int laenge2)
Maybe it helps to see the output of this example program, as it shows the output of many of your cases
Example
#include <stdio.h>
void test_arr(int*[6]);
int main(void)
{
int array[] = {4, 8, 1, 3, 0, 9};
int* pArr[6] = {0}; // 6 pointers to int
printf("original vector in main(): ");
for (int i = 0; i < 6; i += 1) printf("%d ", array[i]);
printf("\n");
for (int i = 0; i < 6; i++) pArr[i] = &array[i];
test_arr(pArr);
printf("\nIn main() &array[0] = %p\n", &array[0]);
return 0;
}
void test_arr(int* pInt[6])
{
printf("In test_array(): ");
for (int i = 0; i < 6; i += 1)
printf("%d ", *pInt[i]);
printf("\n");
int* myP = *pInt;
printf("*pInt\tpoints to value %d\n", *myP);
myP = pInt[0];
printf("pInt[0]\tpoints to value %d\n", *myP);
int x = *pInt[0];
printf("*pInt[0] = %d\n", x);
printf("\ntest_array() &pInt[0] = %X\n", pInt[0]);
return;
}
output
original vector in main(): 4 8 1 3 0 9
In test_array(): 4 8 1 3 0 9
*pInt points to value 4
pInt[0] points to value 4
*pInt[0] = 4
test_array() &pInt[0] = 197BFB00
In main() &array[0] = 000000CF197BFB00
Your program with some changes in the functions
I changed some lines in your code to get the expected result
#include <stdio.h>
void switch1(const int[],int[],const int);
void switch2(const int[],int*[],const int);
void show_array(const int[6],const char*);
int main(void)
{
int arr_out[] = {0,0,0,0,0,0};
show_array(arr_out, "arr_out in main()");
// call 1st function
printf("switch1() uses int[] as output\n");
switch1((int[6]){6, 5, 4, 3, 2, 1}, arr_out, 6);
show_array(arr_out, "arr_out using 6..1 array as input and 1st function");
// for 2nd function we need an array of pointers
int* pArr[6] = {0}; // 6 pointers to int
for (int i = 0; i < 6; i++) pArr[i] = &arr_out[i];
printf("switch2() uses int*[] as output\n");
switch2((int[6]){1, 2, 3, 4, 5, 6}, pArr, 6);
show_array(arr_out, "arr_out using 1..6 array as input and 2nd function");
return 0;
}
void switch1(const int in[], int out[], const int laenge)
{
for (int i = 0; i < laenge; i++)
out[i] = in[laenge - 1 - i];
}
void switch2(const int in[], int* out[], const int laenge)
{
for (int i = 0; i < laenge; i++)
*out[i] = in[laenge - 1 - i];
}
void show_array(const int array[6], const char* msg)
{
printf("%s:\t", msg);
for (int i = 0; i < 6; i++) printf("%d ", array[i]);
printf("\n");
}
output of the modified code
arr_out in main(): 0 0 0 0 0 0
switch1() uses int[] as output
arr_out using 6..1 array as input and 1st function: 1 2 3 4 5 6
switch2() uses int*[] as output
arr_out using 1..6 array as input and 2nd function: 6 5 4 3 2 1
about the changes
void show_array(const int array[6], const char* msg)
{
printf("%s:\t", msg);
for (int i = 0; i < 6; i++) printf("%d ", array[i]);
printf("\n");
}
This function is a helper to show the array contents and accepts a title. Very convenient here
the 2 functions has no output (printf() calls)
parameters are declared const so we can build the vector at the function call
I am using shorter names and changed the order of arguments to input and then output
void switch1(const int in[], int out[], const int laenge)
{
for (int i = 0; i < laenge; i++)
out[i] = in[laenge - 1 - i];
}
void switch2(const int in[], int* out[], const int laenge)
{
for (int i = 0; i < laenge; i++)
*out[i] = in[laenge - 1 - i];
}
Here you see the difference between the 2 functions: a single asterisk.
But in order of using the second function you need to build the vector of pointers as here
// call 1st function
printf("switch1() uses int[] as output\n");
switch1((int[6]){6, 5, 4, 3, 2, 1}, arr_out, 6);
show_array(arr_out, "arr_out using 6..1 array as input and 1st function");
// for 2nd function we need an array of pointers
int* pArr[6] = {0}; // 6 pointers to int
for (int i = 0; i < 6; i++) pArr[i] = &arr_out[i];
printf("switch2() uses int*[] as output\n");
switch2((int[6]){1, 2, 3, 4, 5, 6}, pArr, 6);
show_array(arr_out, "arr_out using 1..6 array as input and 2nd function");
Context
I created this simple code where I store various arrays in my_arrays() function and different functions (in my example the main()) can get the hard-coded arrays via the function my_arrays().
See the code here:
#include <stdio.h>
int my_arrays(int *size, int **arrays) {
size[0] = 3;
int array_1[3] = {1, 2, 3};
arrays[0] = array_1;
size[1] = 5;
int array_2[5] = {2, 3, -5, 7, 11};
arrays[1] = array_2;
}
int main() {
int num_of_arrays = 2;
int sizes[2];
int *arrays[2];
my_arrays(sizes, arrays);
for (int i=0; i < num_of_arrays; i++) {
int *array = arrays[i]; // point to sub-array
int size = sizes[i];
printf("array[%d]: {", i);
for (int x=0; x < size; x++) {
printf(" %d", array[x]);
}
printf(" }\n", i);
}
return 0;
}
In the main() I then loop through the sub-arrays and loop through each individual number and print it out.
What I expect the code above to print out is:
array[0]: { 1 2 3 }
array[1]: { 2 3 -5 7 11 }
But when compiling and running I get this:
array[0]: { 1993067712 1617605192 -2 }
array[1]: { 3936256 8 6422188 7 6422476 }
Why?
In my_arrays, array_1 and array_2 are local arrays on the stack. They will be invalid as soon as you return from my_array. Now arrays[0] and arrays[1] hold pointers to invalid or "stale" memory. Accessing that is undefined behaviour.
(The garbage values you see shows you that your arrays have been overwritten by other uses of the stack space, probably by calls to printf.)
If you want to create arrays, you can allocate memory on the heap:
int my_arrays(int *size, int **arrays)
{
size[0] = 3;
arrays[0] = malloc(3 * sizeof(int));
arrays[0][0] = 1;
arrays[0][1] = 2;
arrays[0][2] = 3;
// ... initialize other arrays ...
return 0;
}
You should explicitly free it after you're done using it:
// at the end of main
for (int i=0; i < num_of_arrays; i++) {
free(arrays[i]);
}
#include <stdio.h>
#include <stdlib.h>
int ** letters (int*arr, int nr_elem)
{
char **mat=(char**)malloc( nr_elem * sizeof(char*));
int max =0;
for (int i =0; i<nr_elem;i++)
{
if( *(arr + i) > max)
max = *(arr + i);
}
for (int i=0; i<nr_elem; i++)
{
*mat=(char*)malloc((*(arr+i))*sizeof(char));
}
for(int i=0; i<nr_elem;i++)
{
for(int j=0; j<(*(arr+i)); j++)
{
mat[i][j] = 'a'+ (*(arr+i))-1;
printf("mat[%d][%d] = %c\n", i, j, mat[i][j]);
}
}
}
int main()
{
int a[] = {3, 4, 5, 2, 3};
int n = 5;
letters(a, n);
return 0;
}
My final goal is to make the function print a matrix with 5 rows on which it will print the corresponding letter from array a, that same amount of times. For example line 1, will have letter 'c' printed 3 times, line 2 will have 'd' printed 4 times etc.
For now I just want to print the matrix (i know the rest is not completely implemented, but I want to see what i have so far). it will show me that :
m[0][0] = 'c'
m[0][1] = 'c'
m[0][2] = 'c'
m[1][0] = 'd'
m[1][1] = 'd'
m[1][2] = 'd'
m[1][3] = 'd'
but then it cracks. Why?
You have an error in the second for loop inside your letters function, where you should be allocating a char* pointer to each element of mat:
for (int i=0; i<nr_elem; i++)
{
// *mat=(char*)malloc((*(arr+i))*sizeof(char)); // *mat keeps getting overwritten!
mat[i] = malloc((*(arr+i))*sizeof(char)); // Allocates new block for each loop
}
In your code, your only ever assign the return from malloc to the first element of the mat array - each loop just overwrites the previously assigned value (i.e. *mat is the same as mat[0]).
Also, please see this post on (not) casting the return value of malloc: Do I cast the result of malloc?
I have an arrFillRandom function which fill an array with random numbers and prints it out. Here it is:
void arrFillRandom(int *arrayPtr, int sizeRow, int sizeColumn, int randomRange) {
int i, j;
arrayPtr = malloc(sizeof(int) * sizeRow * sizeColumn);
for (i = 0; i < sizeRow; i++)
for (j = 0; j < sizeColumn; j++)
(arrayPtr + i)[j] = (rand() % randomRange);
for (i = 0; i < sizeRow; i++) {
printf("\n");
for (j = 0; j < sizeColumn; j++)
printf("%d\t", (arrayPtr + i)[j]);
}
}
And here is my main:
int main() {
void arrFillRandom(int *arrayPtr, int sizeRow, int sizeColumn, int randomRange);
int matrix1[2][3];
int matrix2[3][2];
int *ptr1, *ptr2;
ptr1 = &matrix1[0][0];
ptr2 = &matrix2[0][0];
arrFillRandom(ptr1, 2, 3, 10);
arrFillRandom(ptr2, 3, 2, 10);
printf("\n%d", ptr1[0]);
return 0;
}
My problem is that ptr1 or ptr2 doesn't point to array which arrFillRandom filled before.
In arrFillRandom function, I print out the matrix with random numbers. For example:
1, 0, 9 // first row of first matrix
0, 9, 4 // second row of first matrix
8, 2 // first row of second matrix
2, 5 // second row of second matrix
5, 5 // third row of second matrix
But in main, when I want to print first element of this matrix:
printf("\n%d", ptr1[0]);
This line should print 1, but it prints irrelevant number such as 4096.
So why I couldn't store that matrix in this array?
Your void arrFillRandom() function allocates new memory and fills that with
random numbers. arrayPtr is a local variable inside the function, and assigning a new value to it
does not change the passed arguments ptr1 or ptr2.
To fill the arrays whose addresses are passed to the function, simply remove the line
arrayPtr = malloc(sizeof(int) * sizeRow * sizeColumn);
You also have to change
(arrayPtr + i)[j]
to
arrayPtr[sizeColumn * i + j]
inside that function.
I'm having an array, that has arrays in every cell. For example, the big array is called arr:
int a[3] = {3, 2, 1};
int b[2] = {2, 1};
int *arr[2] = {a, b}
Now the problem is, if I want to print the small arrs, inside the big array.
Here is my code:
#include <stdio.h>
void printArr(int arr [], int n)
{
for (int i = 0 ; i < n ; i++)
{
printf("%d ", *(arr + i));
}
printf("\n");
}
int main()
{
int a[5] = {1, 8, 4, 2, 0};
int b[3] = {1, 4, 2};
int *arr [2] = {a, b};
int n = 0;
for (int i = 0 ; i < 2 ; i++)
{
printArr(*(arr + i), n);
}
}
The output is supposed to be something like this:
1 8 4 2 0
1 4 2
But I can't get the size of each array, since sizeof(*(arr + i) gives me 4, which is the size of the pointer (the name of the array), and not all the array it self.
So what can I do?
Thanks!
The Problem:
The C language only provides a way of finding the size of types.
This gives the subtle differences between applying sizeof to:
1) An array of a type such as:
int a[3];
sizeof(a); // => 3 * sizeof(int)
2) A pointer to the type:
int *ptr;
sizeof(ptr); // => sizeof(int *)
or
int a[3] = {3, 2, 1};
int b[2] = {2, 1};
int *arr[2] = {a, b};
sizeof(arr[1]); // => sizeof(int *)
Some solutions:
Store the size
As jfly proposes store the size of the arrays.
Makes finding the size a constant time operation.
Append an end marker
Adding a end marker like '\0' as used for c-style strings.
You might use INT_MAX or INT_MIN in this case.
The printArr implementation would need to change to:
void printArr(int *arr)
{
int *it = arr;
while(arr != INT_MIN);
{
printf("%d ", *it);
}
printf("\n");
}
Disadvantages:
Finding the size of the array requires iterating over the full array.
Gives the risk of an actual value colliding with the end marker value.
Advantages:
The varying sized array can be passed as a single argument.
Using iterators
Store the pointer to the first and one past the last value.
void printArr(int *begin, int *end)
{
for (int *it = begin; it != end; it++)
{
printf("%d ", *it);
}
printf("\n");
}
int *end_arr[2] = {a + 3, b + 2};
for (int i = 0 ; i < 2 ; i++)
{
printArr(arr[i], end_arr[i]);
}
Can be extended to other data structures.
Since arr is an array of pointers, so you can't get the size of array from the pointer which points to an array, you need additional size info:
int size_arr[2] = {sizeof(a) / sizeof(int), sizeof(b) / sizeof(int)};
for (int i = 0 ; i < 2 ; i++)
{
printArr(arr[i], size_arr[i]);
}