what is wrong with this realloc use - c

I'm trying to get unlimited input from user, using realloc. this is what i've done so far:
int getCharactersFromUser(char* arr,char terminator)
{
char c = getch();
int length =0;
while(c!=terminator)
{
arr = realloc(arr, sizeof (arr)*(++length));
arr[length-1]=c;
c = getch();
}
return length;
}
i call this method with an arr like this: char *unknownArr = calloc(0,sizeof *unknownArr);
int length = getCharactersFromUser(&unknownArr,TEMINATOR_FOR_LIST);
here TEMINATOR_FOR_LIST is eof

If you want to change the caller's copy of arr, you need to pass a pointer to a pointer.
Also, sizeof (arr) gives you the size of char*; your code appears to be assuming sizeof(char). This is guaranteed to be 1, allowing your memory size calculation to be simplified.
int getCharactersFromUser(char** arr,char terminator)
{
*arr = NULL; // first call to realloc will crash if `*arr` is uninitialised in caller
char c = getch();
int length =0;
while(c!=terminator)
{
*arr = realloc(*arr, ++length);
(*arr)[length-1]=c;
c = getch();
}
return length;
}

Related

Passing Character Array to Function and Return Character Array [duplicate]

is that even possible?
Let's say that I want to return an array of two characters
char arr[2];
arr[0] = 'c';
arr[1] = 'a';
from a function. What type do I even use for the function? Is my only choice to use pointers and void the function? So far I've tried having a char* function or a char[]. Apparently you can only have functions of char(*[]). The only reason I want to avoid using pointers is the fact that the function has to end when it encounters a "return something;" because the value of "something" is a character array (not a string!) that might change size depending on the values I pass into the function through the main function. Thanks to anyone who responds in advance.
You've got several options:
1) Allocate your array on the heap using malloc(), and return a pointer to it. You'll also need to keep track of the length yourself:
void give_me_some_chars(char **arr, size_t *arr_len)
{
/* This function knows the array will be of length 2 */
char *result = malloc(2);
if (result) {
result[0] = 'c';
result[1] = 'a';
}
/* Set output parameters */
*arr = result;
*arr_len = 2;
}
void test(void)
{
char *ar;
size_t ar_len;
int i;
give_me_some_chars(&ar, &ar_len);
if (ar) {
printf("Array:\n");
for (i=0; i<ar_len; i++) {
printf(" [%d] = %c\n", i, ar[i]);
}
free(ar);
}
}
2) Allocate space for the array on the stack of the caller, and let the called function populate it:
#define ARRAY_LEN(x) (sizeof(x) / sizeof(x[0]))
/* Returns the number of items populated, or -1 if not enough space */
int give_me_some_chars(char *arr, int arr_len)
{
if (arr_len < 2)
return -1;
arr[0] = 'c';
arr[1] = 'a';
return 2;
}
void test(void)
{
char ar[2];
int num_items;
num_items = give_me_some_chars(ar, ARRAY_LEN(ar));
printf("Array:\n");
for (i=0; i<num_items; i++) {
printf(" [%d] = %c\n", i, ar[i]);
}
}
DO NOT TRY TO DO THIS
char* bad_bad_bad_bad(void)
{
char result[2]; /* This is allocated on the stack of this function
and is no longer valid after this function returns */
result[0] = 'c';
result[1] = 'a';
return result; /* BAD! */
}
void test(void)
{
char *arr = bad_bad_bad_bad();
/* arr is an invalid pointer! */
}
Since you have a predetermined size of you array you can in-fact return the array if you wrap it with a struct:
struct wrap
{
char a[2] ;
} ;
struct wrap Get( void )
{
struct wrap w = { 0 } ;
w.a[0] = 'c';
w.a[1] = 'a';
return w ;
}
You can return a pointer for the array from a function, however you can't return pointers to local arrays, the reference will be lost.
So you have 3 options:
Use a global variable:
char arr[2];
char * my_func(void){
arr[0] = 'c';
arr[1] = 'a';
return arr;
}
Use dynamic allocation (the caller will have the responsibility to free the pointer after using it; make that clear in your documentation)
char * my_func(void){
char *arr;
arr = malloc(2);
arr[0] = 'c';
arr[1] = 'a';
return arr;
}
Make the caller allocate the array and use it as a reference (my recommendation)
void my_func(char * arr){
arr[0] = 'c';
arr[1] = 'a';
}
If you really need the function to return the array, you can return the same reference as:
char * my_func(char * arr){
arr[0] = 'c';
arr[1] = 'a';
return arr;
}
You can pass the array to the function and let the function modify it, like this
void function(char *array)
{
array[0] = 'c';
array[1] = 'a';
}
and then
char array[2];
function(array);
printf("%c%c\n", array[0], array[1]);
If you want it as a return value, you should use dynamic memroy allocation,
char *function(void)
{
char *array;
array = malloc(2);
if (array == NULL)
return NULL;
array[0] = 'c';
array[1] = 'a';
return array;
}
then
char *array = function();
printf("%c%c\n", array[0], array[1]);
/* done using `array' so free it because you `malloc'ed it*/
free(array);
Important Note:
You should be aware of the fact that the array as filled above is not a string, so you can't for instance do this
printf("%s\n", array);
because the "%s" expects a matching string to be passed, and in c an array is not a string unless it's last character is '\0', so for a 2 character string you need to allocate space for 3 characters and set the last one to '\0'.
char* getCharArray()
{
return "ca";
}
This works perfecly:
int comm_read_data(int file_i2c, unsigned char** buffer)
{
*buffer = malloc(BUFFER_SIZE);
if (i2c_read_bytes(file_i2c, *buffer, BUFFER_SIZE) != 0)
{
return -1;
}
return BUFFER_SIZE;
}
And then call the function:
unsigned char* buffer;
int length = comm_read_data(file_i2c, &buffer);
/* parse the buffer here */
free(buffer);

If I use a while loop to iterate through the contents of a pointer to an array, how do I return back to the first element in the array?

Say for example I have a function called from main that returns a pointer:
EDIT
: I was a little unclear, sorry! Let's say I used a scanf in the main() and then I passed this into the function, and I wanted to copy the argument into a new pointer then return that one.
main(void)
{
char *word = malloc(50);
scanf("%s", word);
printf("%s", function(word));
}
char *function(char *array)
{
char *a = malloc(50);
while (*array)
{
*a = *array;
a++;
array++;
}
return a;
}
In this case, if I tried to return the pointer array to main, the pointer would be pointing to the memory location 1 space past where my values are held.
How would I make so I can return the pointer to the first value again?
Thanks!
The best way is to not increment your pointers at all:
char *function(char *array)
{
const size_t maxLength = 49;
char * a = malloc(maxLength + 1);
if ( !a ) {
perror("couldn't allocate memory");
exit(EXIT_FAILURE);
}
size_t i;
for ( i = 0; array[i] && i < maxLength; ++i ) {
a[i] = array[i];
}
a[i] = '\0';
return a;
}
Your original code does not null-terminate a, yet you pass it to printf() as if it's a string. Also, you're leaking memory, since you don't store the pointer you're returning, so you can never free() it.
The basic approach is to use a temporary variable to hold the pointer value you want to keep.
Assuming the only one you care about in your example is a.
char *function(char *array)
{
char *a, *t;
t = a = malloc(50);
while (*array)
{
*t = *array;
++t;
++array;
}
*t = '\0'; /* since the caller passes returned pointer to printf() */
return a; /* a unchanged, so return it */
}
Note that the above will have undefined behaviour if strlen(array) >= 50.
In your example, array is passed by value, so changes to it (repeated incrementing) do not propagate to the caller - there is no need to reset array back to its original value.
The best way would be to not use the parameter to the function, but a copy of it inside the function.
char* pTmp = array;
Also it's better to do ++pTmp rather than array++ because for non-POD types it can be quicker.

How to send 2D char pointer to a function for memory allocation?

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
void createDynamicArrayForChar(int dimension, char **ptr)
{
ptr = (char**)malloc(dimension*sizeof(char*));
for (int i = 0; i < dimension; i++)
{
ptr[i] = (char*)malloc(20 * sizeof(char));
ptr[i] = "value";
}
}
int main()
{
char **ptrArray;
createDynamicArrayForChar(5, ptrArray);
printf("%s", ptrArray[3]);
getchar(); getchar();
return 0;
}
It gives some errors when I try to compile this codes. How can I solve this problem? How to send 2D char pointer to a function in C?
Firstly, as per the present code, I see two issues.
You're passing ptrArray to the function and trying to allocate memory inside the function. Please be aware, C uses pass by value for function argument passing, so, if you want to allocate memory to ptrArray and expect that to be refeclted back to the caller, without returning, you'll be needing to pass a pointer to that `ptrArray.
in the code
ptr[i] = (char*)malloc(20 * sizeof(char));
ptr[i] = "value";
You're leaking memory. Once you've allocated memory using malloc(), you should use strcpy() to copy the data into the allocated memory.
That said, some advice:
Please see why not to cast the return value of malloc() and family in C.
sizeof(char) is guaranteed to be 1 in C. Using that as a multiplier is not required.
Always check the success of malloc() before using the returned pointer.
You probably need this (no error checking and not debugged code):
void createDynamicArrayForChar(int dimension, char ***ptr)
{
*ptr = (char**)malloc(dimension*sizeof(char*));
for (int i = 0; i < dimension; i++)
{
(*ptr)[i] = (char*)malloc(20 * sizeof(char));
strcpy((*ptr)[i],"value");
}
}
or
char **createDynamicArrayForChar(int dimension)
{
char **ptr = (char**)malloc(dimension*sizeof(char*));
for (int i = 0; i < dimension; i++)
{
ptr[i] = (char*)malloc(20 * sizeof(char));
strcpy(ptr[i],"value");
}
return ptr;
}
int main()
{
char **ptrArray;
ptrArray = createDynamicArrayForChar(5);
...
Read also Sourav Ghosh's answer.

Return array from function in C [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Declaring a C function to return an array
I am new to C, and need to your thoughts to help me to return the result array from the following function:
void getBase(int n, int b)
{
const size_t SIZE = 32;
char arr[32+1]={0}; int digits=SIZE, i;
char* ptr = arr;
while (n > 0)
{
int t = n%b;
n/=b;
arr[--digits] = numbers[t];
}
while ( *ptr == '\0') ptr++;
// NEED To return a ref to `ptr`
}
My solution:
void getBase(int n, int b, /*send some array as a parameter*/ char* str)
{
const size_t SIZE = 32;
char arr[32+1]={0}; int digits=SIZE, i;
char* ptr = arr;
while (n > 0)
{
int t = n%b;
n/=b;
arr[--digits] = numbers[t];
}
while ( *ptr == '\0') ptr++;
/* and use strcpy ... perhaps memcpy if non-string )*/
strcpy(str, ptr);
}
I need further ideas....
Thanks.
Your solution looks fine.
Instead, you don't even need the local arr array at all. You can just write directly into str:
EDIT : Cleaned up and working version.
const char numbers[] = "0123456789abcdef";
void getBase(int n, int b, char* str)
{
const size_t SIZE = 32;
int digits=SIZE;
while (n > 0)
{
int t = n%b;
n/=b;
str[--digits] = numbers[t];
}
int length = SIZE - digits;
memmove(str,str + digits,length);
str[length] = '\0';
}
You just have to make sure that your str is large enough to avoid an array-overrun.
int main(){
char str[33];
getBase(684719851,10,str);
printf(str);
return 0;
}
Output:
684719851
As other mention, the common solution is to allocate an array, an return a pointer to it. Be sure that you free it in the caller function.
If you know (at compilation time) the size of the array, you can make a struct that contain an array, and return the struct. note that it will push the array to the stack, and may slow the program. If it's a really big array you even may get a stack overflow.
If you want to return an array of length n, you should first create the array with malloc, and then you can return a pointer. E.g.
char *arr = malloc(n*sizeof(char));
//now arr points to an array, use it as you like
return arr;
be sure to set the return type of your function to char*. You can do the same thing for any type of array - just be sure to update all the types accordingly.

how to return a string array from a function

char * myFunction () {
char sub_str[10][20];
return sub_str;
}
void main () {
char *str;
str = myFunction();
}
error:return from incompatible pointer type
thanks
A string array in C can be used either with char** or with char*[]. However, you cannot return values stored on the stack, as in your function. If you want to return the string array, you have to reserve it dynamically:
char** myFunction() {
char ** sub_str = malloc(10 * sizeof(char*));
for (int i =0 ; i < 10; ++i)
sub_str[i] = malloc(20 * sizeof(char));
/* Fill the sub_str strings */
return sub_str;
}
Then, main can get the string array like this:
char** str = myFunction();
printf("%s", str[0]); /* Prints the first string. */
EDIT: Since we allocated sub_str, we now return a memory address that can be accessed in the main
To programmers just starting out, the concept of a "stack" or the "heap" might be a little confusing, especially if you have started programming in a higher level language like Ruby, Java, Python, etc.
Consider:
char **get_me_some_strings() {
char *ary[] = {"ABC", "BCD", NULL};
return ary;
}
The compiler will rightfully issue a complaint about trying to return address of a local variable, and you will most certainly get a segmentation fault trying to use the returned pointer.
and:
char **get_me_some_strings() {
char *ary[] = {"ABC", "BCD", NULL};
char **strings = ary;
return strings;
}
will shut the compiler up, while still getting the same nasty segmentation fault.
To keep everyone but the zealots happy, you would do something a little more elaborate:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **get_me_some_strings() {
char *ary[] = { "ABC", "BCD", NULL };
char **strings = ary; // a pointer to a pointer, for easy iteration
char **to_be_returned = malloc(sizeof(char*) * 3);
int i = 0;
while(*strings) {
to_be_returned[i] = malloc( sizeof(char) * strlen( *strings ) );
strcpy( to_be_returned[i++], *strings);
strings++;
}
return to_be_returned;
}
now use it:
void i_need_me_some_strings() {
char **strings = get_me_some_strings();
while(*strings) {
printf("a fine string that says: %s", *strings);
strings++;
}
}
Just remember to free the allocated memory when you are done, cuz nobody will do it for you. That goes for all the pointers, not just the pointer to the pointers! (i think).
To make more sense of it all, you might also want to read this: What and where are the stack and heap?
Reason:
you need the return type to be char(*)[20]. But even in this case you don't want to return a pointer to a local object from the function.
Do:
Use malloc to allocate sub_str, and return char**.
The cause of your compiler error is simple, but not the answer to what you really want to do. You are declaring that the function returns a char *, while returning a char **.
Without knowing the details of what you're doing, I'm going to assume one of two things are true:
1) The purpose of the function is to create and return an array of strings.
2) The function performs some operation(s) on an array of strings.
If #1 is true, you need several malloc calls to make this work (It can really be done with only two, but for purposes of simplicity, I'll use several).
If you don't know how large the array is supposed to be, your function declaration should look like this:
char ** allocateStrings ( int numberOfStrings, int strLength );
The reason for this is because you're essentially returning a pointer to an array of pointers and you need to know how many strings and how long each string is.
char ** allocateStrings ( int numberOfStrings, int strLength )
{
int i;
//The first line is allocating an array of pointers to chars, not actually allocating any strings itself
char ** retVal = ( char ** ) malloc ( sizeof ( char * ) * numberOfStrings );
//For each string, we need to malloc strLength chars
for ( i = 0; i < numberOfStrings; i ++ )
{
//Allocate one extra char for the null pointer at the end
retVal [ i ] = ( char * ) malloc ( sizeof ( char ) * ( strLength + 1 ) );
}
return retVal;
}
As somebody else pointed out, it's best practice to have whatever does the allocating also do the deallocating. So a cleanup function is needed.
void cleanupStrings ( char ** strArray, int numberOfStrings )
{
int i;
for ( i = 0; i < numberOfStrings; i ++ )
{
//Should be checking to see if this is a null pointer.
free ( strArray [ i ] );
}
//Once the strings themselves are freed, free the actual array itself.
free ( strArray );
}
Now, keep in mind that once the cleanup function is called, you no longer have access to the array. Trying to still use it will most likely cause your application to crash.
If #2 is true, then you want to allocate the strings, process the strings, and clean them up. You should use the two functions above to allocate/deallocate your strings, then a third function to do whatever with them.
void processStrings ( char ** strArray, int numberOfStrings, int strLength );
As others have said, you cannot return a local char array to the caller, and have to use heap memory for this.
However, I would not advise using malloc() within the function.
Good practice is that, whoever allocates memory, also deallocates it (and handles the error condition if malloc() returns NULL).
Since your myFunction() does not have control over the memory it allocated once it returned, have the caller provide the memory in which to store the result, and pass a pointer to that memory.
That way, the caller of your function can de-allocate or re-use the memory (e.g. for subsequent calls to myFunction()) however he sees fit.
Be careful, though, to either agree on a fixed size for such calls (through a global constant), or to pass the maximum size as additional parameter, lest you end up overwriting buffer limits.
As others correctly said you should use dynamic memory allocation by malloc to store your array inside heap and return a pointer to its first element.
Also I find it useful to write a simple array of string implementation which has a minimal API for data manipulation.
Type and API:
typedef struct {
char **array_ptr;
int array_len;
int string_len;
} array_t;
array_t* array_string_new(int array_len, int string_len);
int array_string_set(array_t *array, int index, char *string);
char* array_string_get(array_t *array, int index);
int array_string_len(array_t *array);
Usage:
It creates an array with 4 dimensions that can store strings with 4 characters length. If the string length goes beyond the specified length, just its first 4 characters will be stored.
int main()
{
int i;
array_t *array = array_string_new(4, 4);
array_string_set(array, 0, "foo");
array_string_set(array, 1, "bar");
array_string_set(array, 2, "bat");
array_string_set(array, 3, ".... overflowed string");
for(i = 0; i < array_string_len(array); i++)
printf("index: %d - value: %s\n", i, array_string_get(array, i));
/* output:
index: 0 - value: foo
index: 1 - value: bar
index: 2 - value: bat
index: 3 - value: ...
*/
array_string_free(array);
return 0;
}
Implementation:
array_t*
array_string_new(int array_len, int string_len)
{
int i;
char **array_ptr = (char**) malloc(array_len * sizeof(char**));
for(i = 0; i < array_len; i++) {
array_ptr[i] = (char*) malloc(string_len * sizeof(char));
}
array_t *array = (array_t*) malloc(sizeof(array_t*));
array->array_ptr = array_ptr;
array->array_len = array_len;
array->string_len = string_len;
return array;
}
int
array_string_set(array_t *array, int index, char *string)
{
strncpy(array->array_ptr[index], string, array->string_len);
return 0;
}
char*
array_string_get(array_t *array, int index)
{
return array->array_ptr[index];
}
int
array_string_len(array_t *array)
{
return array->array_len;
}
int
array_string_free(array_t *array)
{
int i;
for(i = 0; i < array->array_len; i++) {
free(array->array_ptr[i]);
}
free(array->array_ptr);
return 0;
}
Notice that it is just a simple implementation with no error checking.
i use that function to split a string to string array
char ** split(char *str, char *delimiter)
{
char *temp=strtok(str,delimiter);
char *arr[]={temp};
int i=0;
while(true)
{
elm=strtok (NULL, delimiter);
if(!temp) break;
arr[++i]=temp;
}
return arr;
}
first of all You can not return a string variable which is stored in stack you need use malloc to allocate memory dynamicaly here is given datails with the example
Go https://nxtspace.blogspot.com/2018/09/return-array-of-string-and-taking-in-c.html
get a proper answer
char *f()
{
static char str[10][20];
// ......
return (char *)str;
}
int main()
{
char *str;
str = f();
printf( "%s\n", str );
return 0;
}
You can use static instead of malloc. It's your choice.

Resources