Modifying a array in a function in C - c

#include <stdio.h>
#include <stdlib.h>
void array_tester(int *array);
int main(int argc,char *argv[])
{
int test[] = {1,1,1,1};
int print;
for(print = 0; print < sizeof(test) / sizeof(int); print++)
{
printf("%d\n",test[print] );
}
array_tester(test);
for(print = 0;print < sizeof(test)/sizeof(int);print++)
{
printf("%d\n",test[print] );
}
return EXIT_SUCCESS;
}
void array_tester(int array[])
{
int i ;
for(i = 0; i < sizeof(array) / sizeof(int); i++)
{
array[i] = i;
}
}
The problem is I want to modify the the array in the array_tester function but I'm unable to do so. What do I use inside sizeof()?

You have to manually pass the information about the size of the array.
void array_tester( int* array , int size ) ;
And then call it:
array_tester( test , sizeof(test)/sizeof(*test) ) ;
The reason behind this is that array passed to a function will decay to a pointer and the sizeof will return the size of pointer not the original array.

Related

C how to return arrays from multiple functions?

I am trying to make a program that first creates an array in another function, returns it and then calls another function that shuffles the contents of the array and returns it. However I am struggling to do this in C since I do not quite understand the array pointer system that has to be used here.
So far my code doesnt return the values 1-20 from makeArray() but instead returns an array full of 0s and I have a feeling it has to do with the c's array pointer system.
Any help would greatly be appreciated! Thank you in advance
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int arrShuffle();
int arrShuffle(int * arr) {
int arr[21];
// shuffle array
for(int j=0; j<20; j++) {
int randInd = (rand() % 20) + 1;
int temp = arr[j];
arr[j] = arr[randInd];
arr[randInd] = temp;
}
return arr;
}
int makeArray() {
int arr[21];
// make array of 1-20
for(int i=0; i < 20; i++) {
arr[i] = i + 1;
}
return arr;
}
void main() {
int *orgArr;
int *modArr;
srand(time(NULL));
orgArr = makeArray();
for(int i=0; i < 20; i++) {
printf("OrgArr: %d\n", orgArr);
}
modArr = arrShuffle(orgArr);
}
You cannot use variables with automatic storage (aka local ones). You must allocate the array so the memory remains valid after the function ends:
int* makeArray() {
int *arr = calloc(21, sizeof *a);
// make array of 1-20
for(int i=0; i < 20; i++) {
arr[i] = i + 1;
}
return arr;
}
Remember to release the array when it is no longer used:
int main() {
int *orgArr;
...
orgArr = makeArray();
...
free(orgArr);
}
As tstanisl pointed out in their answer, a possible solution is to use dynamic memory allocation. My answer, instead, will give you yet another solution: using an array passed by the caller.
NOTE: both solutions are valid and their usefulness depends on the specific needs of your program. There's no "right" universal solution.
void makeArray(int arr[], size_t len) {
for (size_t i = 0; i < len; i += 1) {
arr[i] = (int) (i + 1);
}
}
void cloneAndModifyArray(const int orig[], int new[], size_t len) {
for (size_t i = 0; i < len; i += 1) {
new[i] = orig[i] * 2; // or some other modification
}
}
And you use it like this:
#define ARR_LEN (100)
int main(void) {
int arr[ARR_LEN];
makeArray(arr, ARR_LEN);
int modified_arr[ARR_LEN];
cloneAndModifyArray(arr, modified_arr, ARR_LEN);
return 0;
}

Dynamic array of array of int in C

How can an array of array of int be declared outside the main, then build inside the main once we know the length of the array of array we want to build, if one dimension is already known.
For example, if the array should be array[numberofargs][2], where the dimension 2 is already known but not numberofargs before execution of main.
One way is just to declare for example a pointer in a file scope like
int ( *array )[2] = NULL;
and then in one of functions allocate a memory for the array.
For example
#include <stdlib.h>
int (*array)[2] = NULL;
int main(void)
{
int numberofargs = 5;
array = malloc( sizeof( int[numberofargs][2] ) );
//...
free( array );
return 0;
}
Or the following way
#include <stdlib.h>
int **array = NULL;
int main(void)
{
int numberofargs = 5;
array = malloc( numberofargs * sizeof( *array ) );
for ( int i = 0; i < numberofargs; i++ )
{
array[i] = malloc( sizeof( *array[i] ) );
}
//...
for ( int i = 0; i < numberofargs; i++ )
{
free( array[i] );
}
free( array );
return 0;
}
Unfortunately, I do not know how to create an array where only the second dimension is known. What you can do is the following:
#include <stdlib.h>
#include <stdio.h>
#define SECOND_DIM 2
int *array;
// returns array[x][y]
int foo(int *array, int x, int y) {
return *(array+x*SECOND_DIM+y);
}
int main(int args, char *argv[]) {
if(!argv[0]) return 0;
array = malloc(args*SECOND_DIM*sizeof(int));
for(int i=0;i<args; i++) {
for(int j=0;j<SECOND_DIM; j++)
*(array+(i*SECOND_DIM)+j) = (i+1)*100+j;
}
printf("array[0][0]: %d\n", foo(array,0,0)); // array[0][0]
printf("array[0][1]: %d\n", foo(array,0,1)); // array[0][1]
free(array);
}
int (*array)[2] = malloc(sizeof(int[numberofargs][2]));
And then when you're finished with it:
free(array);

use of undeclared identifier 'arr'

I'm trying to have some practice with C using Xcode, but got stock with some error.
The code is as follows:
#include <stdio.h>
#include <stdlib.h>
/* move previous elements down until insertion point reached */
void shift_element (unsigned int i ) {
int ivalue;
// guard against going outside array
for (ivalue = arr[i]; i && arr[i-1] > ivalue; i--) {
arr[i] =arr[i-1]; // move element down
arr[i] = ivalue; // insert element
}
}
int main(int argc, const char * argv[]) {
unsigned int arr[5] = {2,4,5,3,6};
shift_element(3);
// print arr
int i;
for (i=0;i < (sizeof (arr) /sizeof (arr[0]));i++) {
printf("%d\n",arr[i]);
}
return 0;
}
But it results in an error saying 'use of undeclared identifier 'arr''
I searched previous questions with the same subject but could not find a proper answer that would solve my problem.
I would be so happy if somebody can help.
Cheers
The arr variable isn't in scope of the shift function. You have to pass it in as a parameter.
You forgot to declare your 'arr'.
Here is a very good answer explaining the various way do to that : How to initialize all members of an array to the same value?
EDIT : Didn't see you declared it in the function below. As the other answer says, you have to pass it as a parameter tho.
Your problem lies in variable accessibility. When you define a variable in the main function it is only accessible in the function in which it was defined. You to try access the array in the shift_elements function which is causing your issue.
To fix this you can either make the arr variable global or pass it in as an argument to your shift_elements(function). I coded a quick correction doing the later because its good practice to avoid global variables when possible.
#include <stdio.h>
#include <stdlib.h>
/* move previous elements down until insertion point reached */
void shift_element (unsigned int i, int[] arr) {
int ivalue;
// guard against going outside array
for (ivalue = arr[i]; i && arr[i-1] > ivalue; i--) {
arr[i] =arr[i-1]; // move element down
arr[i] = ivalue; // insert element
}
}
int main(int argc, const char * argv[]) {
unsigned int arr[5] = {2,4,5,3,6};
shift_element(3, arr);
// print arr
int i;
for (i=0;i < (sizeof (arr) /sizeof (arr[0]));i++) {
printf("%d\n",arr[i]);
}
return 0;
}
For more information on types of variables look here: http://www.mathcs.emory.edu/~cheung/Courses/255/Syllabus/1-C-intro/kinds-vars.html
Just to share with those future possible readers, the correct code would be:
#include <stdio.h>
#include <stdlib.h>
/* move previous elements down until insertion point reached */
void shift_element (unsigned int i, unsigned int *arr ) {
int ivalue;
// guard against going outside array
for (ivalue = arr[i]; i && arr[i-1] > ivalue; i--)
arr[i] = arr[i-1]; // move element down
arr[i] = ivalue; // insert element
}
int main(int argc, const char * argv[]) {
unsigned int arr[5] = {2,4,5,3,6};
// print arr
int i;
for (i=0;i < (sizeof (arr) /sizeof (arr[0]));i++) {
printf("%d\n",arr[i]);
}
shift_element(3, arr);
// print arr
for (i=0;i < (sizeof (arr) /sizeof (arr[0]));i++) {
printf("%d\n",arr[i]);
}
return 0;
}

Pass char pointer array to function

I'm trying to pass an initialized char pointer array to a function. I can't seem to figure out why the function will only print out the numeric digits of each element in the array.
Does anyone know how I can print each string element from the passed in pointer array?
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
void sort(char *);
int main()
{
char *states[4] = {"Florida", "Oregon", "California", "Georgia"};
sort(*states);
return 0;
}
void sort(char *states)
{
int x;
for (x = 0; x < 4; x++) {
printf("\nState: %d\n", states[x]); //only this will compile
//printf("\nState: %s\n", states[x]); //need to print this.
}
}
Your sort function must accept the array of pointers if you wish to print the contents of the array.
void sort (char *states[], size_t num_states) {
int x;
for (x = 0; x < num_states; ++x) {
printf("\nState: %s\n", states[x]); /* Note %s instead of %d */
}
}
And, you must pass the array to the function.
sort(states, 4);
You need to parse an array of pointers to char to sort (instead of just pointer to char).
As jhx pointed out, you need to pass the size of the array as well. You can use sizeof so as to not hard-coding 4. Also omit the array size when initialize it.
void sort( char *states[], int arr_size )
{
int x;
for (x = 0; x < arr_size; x++)
{
printf( "\nState: %s\n", states[x] );
}
}
int main()
{
char *states[] = {"Florida", "Oregon", "California", "Georgia"}; // array of pointers to char
sort( states, sizeof( states ) / sizeof( char * ) );
return 0;
}
You need to pass the char pointer array to the function:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
void sort(char *args[], int n);
int main()
{
char *states[4] = {"Florida", "Oregon", "California", "Georgia"};
sort(states, 4);
return 0;
}
void sort(char *states[], const int N)
{
int x;
for (x = 0; x < N; x++) {
printf("\nState: %s\n", states[x]);
}
}
The reason that only numeric values you are getting is that only pointer to first element of string states[0] of the array states is passed, i.e. you are passing &states[0][0]. So, the statement
printf("\nState: %d\n", states[x]);
will only print the numeric value of first 4 characters of string "Florida".
You need to pass the pointer to first element of array states, i.e. &states[0].
This can be done by changing the declarator of function sort to
void sort(char **, size_t size); // You need to pass the size of array too.
and call it as
sort(states, sizeof(states)/sizeof(char *));
You're sending states which is an array of pointers. So you need to send the base address of that array to the function
sort(*states);
And then receive it in an array of pointer only
void sort(char* states[])
{
int x;
for (x = 0; x < 4; x++) {
printf("\nState: %s\n", states[x]);
}
}
Hardcoding the size if also not a good idea, so better add another parameter size to the function call.
sort(states, sizeof(states)/sizeof(char*));
and later use that to iterate over the array
void sort(char* states[], int size)
{
int x;
for (x = 0; x < size; x++) {
printf("\nState: %s\n", states[x]);
}
}

Passing Array By Reference To Function in C

I'm having a real difficult time getting this code to work. I'm trying to pass an array by reference to a function, in order to modify it in that function. Then I need the modifications to be handed back to the original caller function.
I have searched here for a similar problem, but couldn't find anything that can run successfully like the way I want to do it.
Here's my code, I would really appreciate any help. Thanks a lot:
#include <stdio.h>
#include <stdlib.h>
#define SIZE_OF_VALUES 5
#define SIZE_OF_STRING 100
void set_values(char **values);
void set_values(char **values)
{
*values = malloc(sizeof(char)*SIZE_OF_VALUES);
for (int i = 0; i < (sizeof(char)*SIZE_OF_VALUES); i++) {
values[i] = malloc(sizeof(char)*SIZE_OF_STRING);
values[i] = "Hello";
//puts(values[i]); //It works fine here.
}
}
int main (int argc, const char * argv[])
{
char *values;
set_values(&values);
for (int i = 0; i < (sizeof(char)*SIZE_OF_VALUES); i++) {
puts(values[i]); //It does not work!
}
return 0;
}
There are several problems with your code:
You should have three-level pointers - void set_values(char ***values), read it as a "a reference (first *) to an array (second *) of char* (third *)"
Each element in *values should be a pointer (char*) not char, so you need:
*values = malloc(sizeof(char*)*SIZE_OF_VALUES);
You are leaking memory, first mallocing then assigning literal, and additionally not dereferencing values, you need either:
(*values)[i] = "Hello";
or
(*values)[i] = strdup("Hello"); // you will have to free it later
or
(*values)[i] = malloc(sizeof(char)*SIZE_OF_STRING); // you will have to free this as well
strcpy((*values)[i], "Hello");
In your main, you should declare char **values; as it is a pointer to an array of char* (character string/array).
In you loop you are incorrectly multiplying indices by sizeof, index is counted in elements not in bytes. Thus, you need:
for (int i = 0; i < SIZE_OF_VALUES; i++)
Don't forget to free the memory at the end.
Use a char *** type for your parameter of your set_values function:
#include <stdio.h>
#include <stdlib.h>
#define SIZE_OF_VALUES 5
void set_values(char ***values)
{
*values = malloc(sizeof (char *) * SIZE_OF_VALUES);
for (int i = 0; i < SIZE_OF_VALUES; i++) {
(*values)[i] = "Hello";
}
}
int main (int argc, char *argv[])
{
char **values;
set_values(&values);
for (int i = 0; i < SIZE_OF_VALUES; i++) {
puts(values[i]);
}
return 0;
}
Of course you have to check for malloc return value and free allocated memory before exit of main.
Here is the solution.
void set_values(char ***values)
{
int i;
char ** val;
val = *values = (char**)malloc(sizeof(char*)*SIZE_OF_VALUES);
for (i = 0; i < (sizeof(char)*SIZE_OF_VALUES); i++)
val[i] = "Hello";
}
int main (int argc, const char * argv[])
{
char **values;
int i;
set_values(&values);
for (i = 0; i < (sizeof(char)*SIZE_OF_VALUES); i++)
puts(values[i]);
return 0;
}
char * is a one dimensional array of char. but you want your code in set_values sets values to a two dimensional array.
In order to make this work, define:
values as char **values;
set_values as void set_values(char ***values)
allocate the pointers for the char arrays as:
*values = malloc(sizeof(char*)*SIZE_OF_VALUES);
Besides that your loop is a bit strange:
for (int i = 0; i < (sizeof(char)*SIZE_OF_VALUES); i++) {
should be replaced with
for (int i = 0; i < SIZE_OF_VALUES; i++) {
and finally, if you want to copy a string into your now allocated array use
strncpy((*values)[i], "Hello", SIZE_OF_STRING-1);
(*values)[i][SIZE_OF_STRING-1] = '\0';
so in total:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE_OF_VALUES 5
#define SIZE_OF_STRING 100
void set_values(char ***values);
void set_values(char ***values)
{
const char * content = "Hello";
*values = malloc(sizeof(char*)*SIZE_OF_VALUES);
for (int i = 0; i < SIZE_OF_VALUES; i++) {
(*values)[i] = malloc(sizeof(char)*SIZE_OF_STRING);
strncpy((*values)[i], content, SIZE_OF_STRING-1);
(*values)[i][SIZE_OF_STRING-1] = '\0';
if(strlen(content) >= SIZE_OF_STRING){
fprintf(stderr,"Warning content string did not fit into buffer!\n");
}
}
}
int main (int argc, const char * argv[])
{
char **values;
set_values(&values);
for (int i = 0; i < SIZE_OF_VALUES; i++) {
printf("%s\n", values[i]);
}
for (int i = 0; i < SIZE_OF_VALUES; i++) {
free(values[i]);
}
free(values);
return 0;
}
You have an extra * in this line:
*values = malloc(sizeof(char)*SIZE_OF_VALUES);
Which should be:
values = malloc(sizeof(char)*SIZE_OF_VALUES);
Also you have considerable problem in your main, char* values should be char** values, passing your char* values by reference (set_values(&values);) may cause segmentation fault I suspect.
For affecting the outer array, it's already being affected because when passing to the function you are only copying a pointer that points to the same place, so the modifications will affect the same memory blocks.

Resources