I know how to modify an array of pointers in main, but don't know how to do it when my function need to modify it.
The code between ** is how I do it in main without using a function. I know how to print the array of pointer of pointer out. My question is, suppose I want to move these lines ** into function(), what do I need to modify?
code:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void function(char *array[], int size);
void function_print(char *array[], int size);
int main()
{
char *array[] = {0};
char word[20];
**scanf("%s", word);
int len = strlen(word) + 1;
array[size] = (char *)malloc(sizeof(len));
strlcpy(array[size], word, sizeof(array[size]));**
function(array, 0);
return 0;
}
void function(char *array[], int size)
{
}
void function_print(char *array[], int size)
{
for(int x = 0; x < size; x ++)
{
printf("%s", *array);
(array)++;
}
}
~
~
I made some edit and realized your function will do the same. So go on, and read the EDIT if you don't know how it works.
Besides I think there's something wrong in your main(). First, array[size] = (char *)malloc(sizeof(len)); tends to report an error because no size is defined here. Second, if by size you mean the number of elements in array, then array[size] would cause an overflow. Third, the argument of malloc should be sizeof(char)*len, not sizeof(len), since the latter equals sizeof(int).
Change your function to
void function(char **, int);
And call it by
function(array, 0);
EDIT
I think by "modify it" you mean to change the pointers stored in the array. Since every element is a char*, a char** will do the job.
When you pass array as an argument, actually you're passing the address of the first element. Then in the function you receive it with a char** parray. Since you have also passed the size, you can use it as a char* parray[], and the address of every element is exactly the same with array in main(). Thus, any modification you do with parray will change array. Is that what you want?
You are doing no mistake in calling the function and passing the array of char pointers. This is a right way. Your program did not compile for me, so made some small changes. It works.
#include<stdio.h>
#include<string.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
void function(char *array[], int size);
int main()
{
char *array[] = {0};
char word[20];
scanf("%s", word);
int len = strlen(word) + 1;
array[0] = (char *)malloc(sizeof(len)); //that how I do it in main without using a function.
strcpy(array[0], word);
function(array, 0);
return 0;
}
void function(char *array[], int size)
{
char * temp = new char[strlen(array[0])+1];
strcpy(temp, array[0]);
printf(temp, 's');
}
Writing this :
void function(char *array[], int size)
and this:
void function(char **array, int size)
are same in this context.
If you define a function like this then its not necessary to declare it like the same , you can declare it like :
void function(char **, int );
declaration only describes the return type and arguments' type of a function.Now, some other recommendations:
Do not use scanf like this :
scanf("%s", word);// you need to specify field width in case of strings otherwise it will overwrite buffer in case of large strings therefore, do it like this :
scanf("%19s",word);
size is not defined in your main, instead I would rather prefer to do this way :
size_t len = sizeof(word) + 1;// yes, try to use size_t when returning number of bytes
*array = (char*)malloc(sizeof len);// casting malloc is not recommended though.
strncpy(*array, word,len);
Try doing :
void function(char *array, int size)();
And instead of:
function(array,0);
because array itself it is a memroy address.
Related
In the main function, I use malloc() to create an unsigned char array:
int main()
{
int length = 64;
unsigned char *array = (unsigned char *)malloc(length * sizeof(unsigned char));
...
change_size(array, length);
}
change_size() defined in .h:
void change_size(unsigned char* arr, int len);
In the change_size function, I will use realloc() to increase the array size:
void change size(unsigned char* arr, int len)
{
printf("%d\n", len);
len = len + 16;
printf("%d\n", len);
arr = (unsigned char *)realloc(arr, len * sizeof(unsigned char));
int new_len = sizeof(arr)/sizeof(arr[0]);
printf("%d\n", new_len);
}
The printf() show me:
64
80
8
The array size in the main() also needs to be updated.
Then how to change this array size correctly?
You need to pass your parameters as pointers if you want to change their value back in the caller. That also means you pass your array pointer as a pointer, because realloc might change it:
int change_size(unsigned char **arr, int *len)
{
int new_len = *len + 16;
unsigned char *new_arr = realloc(*arr, new_len);
if (new_arr) {
*len = new_len;
*arr = new_arr;
}
return new_arr != NULL;
}
Here I've modified change_size to suit, and also added a return value to indicate success, since realloc can fail to resize the memory. For clarity, I removed the printf calls. Oh, and I also removed the cast, since that is not valid in C.
Example usage:
if (!change_size(&array, &len))
{
perror("change_size failed");
}
One final note is that you can use your change_size function for the first allocation too, rather than calling malloc. If the first argument to realloc is NULL, it does the same thing as malloc.
First C is not babysitter language,
You only need basic things then you can do everything,
Just try hard to totally understand basic.
#include <stdio.h>
#include <stdlib.h>
int main(){
int G1_Len=20;
int G2_Len=40;
char* G1=(char*)malloc(sizeof(char)*G1_Len);
char* G2=(char*)malloc(sizeof(char)*G2_Len);
printf("This is G1's Size:%d,Becuz G1 is Pointer\n",sizeof(G1));
printf("%d\n",sizeof(G2));
printf("This is what you need just add a variable remainber your size\n%d\n",G1_Len);
printf("%d\n",G2_Len);
/*alloc and free is a pair of memory control you need,remember least function thinking more is tip of C*/
/*if you need alot of function but you cant control all try c++*/
/*and if in c++ using new and delete dont use malloc free*/
free(G1);
free(G2);
G1=NULL;
G2=NULL;
G1_Len=22;
G1=(char*)malloc(sizeof(char)*G1_Len);
//Now you have 22 bytes of char array
free(G1);
return 0;
}
Okay I answer it. #Chipster
#include <stdio.h>
#include <stdlib.h>
int change_size(char** arr, int len)
{
char* nar=(char*)malloc(sizeof(char)*(len+16));
if(nar){
free(* arr);
*arr=nar;
nar[10]='K';//this will let you know its right
return len+16;
}
return len;
}
int main(){
int G1_Len=20;
int G2_Len=40;
char* G1=(char*)malloc(sizeof(char)*G1_Len);
char* G2=(char*)malloc(sizeof(char)*G2_Len);
printf("This is G1's Size:%d,Becuz G1 is Pointer\n",sizeof(G1));
printf("%d\n",sizeof(G2));
printf("This is what you need just add a variable remainber your size\n%d\n",G1_Len);
printf("%d\n",G2_Len);
/*alloc and free is a pair of memory control you need,remember least function thinking more is tip of C*/
/*if you need alot of function but you cant control all try c++*/
/*and if in c++ using new and delete dont use malloc free*/
free(G1);
free(G2);
G1=NULL;
G2=NULL;
G1_Len=22;
G1=(char*)malloc(sizeof(char)*G1_Len);
//Now you have 22 bytes of char array
printf("%d\n",G1);
G1_Len=change_size(&G1,G1_Len);
printf("%c\n",G1[10]);
printf("%d\n",G1);
printf("%d\n",G1_Len);
free(G1);
return 0;
}
This question already has answers here:
How do I modify a pointer that has been passed into a function in C?
(7 answers)
Closed 4 years ago.
I'm trying to create an array of a structure in an external function "add", and print it's fields, but when I get back to the main function "arr" it is still NULL.
I'm confused because I've been creating arrays in external functions many times and it worked.. probably this time the dynamic memory allocation is messing the things up. Can I please get an advice on this matter?
Thanks!
typedef struct {
char* id;
char gender;
char *name;
}Member;
void add(Member arr[], int size);
void print(Member arr[], int *size);
int main()
{
char temp[100];
int size=0;
Member *arr = NULL;
Member *data = (Member*)malloc(sizeof(Member));
//scan fields
gets(temp);
data->id = (char*)malloc((strlen(temp) + 1) * sizeof(char));
strcpy(data->id, temp);
gets(temp);
data->gender = temp;
gets(temp);
data->name = (char*)malloc((strlen(temp) + 1) * sizeof(char));
strcpy(data->name, temp);
add(data, &arr, &size);
print(arr, &size);
return 0;
}
void add(Member *data, Member arr[], int *size)
{
arr = (Member*)realloc(arr, (*size + 1) * sizeof(Member));
arr[*size] = *data;
}
void print(Member arr[], int *size)
{
for (int i = 0;i < *size;i++)
{
puts(arr->id);
puts(arr->gender);
puts(arr->name);
}
}
Imagine code like this:
#include <stdio.h>
void f(int i){
i++;
}
int main(){
int i = 3;
f(3);
printf("%d\n", i);
}
We all know that f() incremented its local copy of i, not the variable that was passed into f() to initially set that value. With that having been said, let's take another look at your add():
void add(Member *data, Member arr[], int *size)
{
arr = (Member*)realloc(arr, (*size + 1) * sizeof(Member));
arr[*size] = *data;
}
When arr is passed into the function, it contains a memory address of the current arr, which starts as NULL. But just like when we change the local value of i in f() above, setting arr to a new value within add() only changes the local value; it does not change main()'s arr.
We also know that if we pass a function an address of data we want it to change, the function can then change the data at that address and the data at that address will reflect the change in the calling function:
#include <stdio.h>
void f(int * i){
*i = *i + 1;
}
int main(){
int i = 3;
f(&i);
printf("%d\n", i);
}
The same logic applies ( though it gets more confusing) when you want to change a pointer's value; send that pointer's address! Let's start with a very simple case:
#include <stdio.h>
#include <stdlib.h>
void f(int** i){
*i = (int*)malloc(sizeof(int));
**i = 99;
}
int main(){
int *i = NULL;
f(&i);
printf("%d\n", *i);
}
Here we create a pointer to an int in main, and initialize it to NULL. Then we send the address of that pointer (that is, the address we stored the NULL) to f(), which (like in your program) allocates some memory and puts the address of the newly allocated pointer _at the address of main's i. Now, the data stored at &i has changed, and dereferencing i from main() will dereference the newly allocated address.
In your code, just as in mine, you'll have to change the way you're passing arr to add() as well as how you interact with it - an exercise you'll get the most out of thinking through yourself. But in short, something like this should get you started:
pass add arr's address, not the address it stores.
Store new address of reallocated memory back to the same address, that is, &arr
make sure to update add() to dereference the pointer to a pointer twice to set the member at the address stored at the address &arr.
Im writing a function in c and here is my code:
char* makeMoves(char oldBoard[], int moveType, int empties, char player){
int oldBoardLength;
oldBoardLength = sizeof(oldBoard) / sizeof(oldBoard[0]);
char result[oldBoardLength];
copyBoard(oldBoard, result);
}
I think that this line has a problem:
char result[oldBoardLength];
how can i create this array with length=oldBoardLength?
In java is something like this:
char[] result = new char[oldBoard.length];
but in c i don;t know how to create this. Can anyone help me?
In C, you have to allocate dynamic storage in such cases.
char *result = malloc(oldBoardLength);
copyBoard(oldBoard, result);
free(result);
However, you have to pass oldBoardLength into the function, because an argument like arr[] or arr[8] will always decay to a pointer. Taking sizeof on a pointer is not what you have intended. Have a look at the output of this example:
#include <stdio.h>
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
long int test(char array[16]) {
return COUNT_OF(array);
}
void main(void) {
char a[16];
printf("%ld\n", COUNT_OF(a)); // prints 16
printf("%ld\n", test(a)); // prints 8 or 4 for 64bit or 32bit systems
}
First I would use char *oldBoard instead of char oldBoard[] There the same but I think char *oldBoard is clearer. Second you don't wan't to use sizeof as that will not return the correct length, you would just get the size of a pointer. sizeof(oldBoard) / sizeof(oldBoard[0]); only works on statically allocated arrays or at least that is what this says How do I find the length/number of items present for an array? . Use a another variable to keep track of the array length. Finally use dynamic allocation aka malloc() so that the values don't become garbage when you pass them between functions. I'm not quite sure what you are trying to do but here is a example of what I think your trying to do.
char *makeMoves(char *oldBoard, int len, int moveType, int empties, char player)
{
char *result;
result = malloc(len);
if(result == NULL)
{
return NULL;
}
copyBoard(oldBoard, result);
return result;
}
int main(void)
{
char *board, *result;
int len = 10;
int moveType, empties;
char player;
board = malloc(len);
if(board == NULL)
{
return -1;
}
result = makeMoves(board, len, moveType, empties, player);
if(result == NULL)
{
return -1;
}
free(board);
free(result);
return 0;
}
In C, the most often used idiom is passing the expected number of elements your pointer parameter points to as a separate parameter. Should be something like this:
char* makeMoves(char *oldBoard, int oldBoardLength, int moveType, int empties, char player) {
/* ... */
}
This way, the caller of your function is repsonsible for passing in the correct length.
Am sorting an array of strings (case insensitive).
qsort causes segmentation fault, probably my casting isn't proper.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare(const void *string1, const void *string2) {
char *a = (char*)(string1);
char *b = (char*)(string2);
printf("comparing %s AND %s\n", a, b);
return strcasecmp(a,b);
}
void sortListName(char **fileList, int noOfFiles) {
printf("Sorting\n");
qsort(fileList, noOfFiles, 260*sizeof(char), compare);
return;
}
**fileList = array of strings (filenames)
P.S. main() is obvious and works fine.
If this is all the code you have related to the qsort, it looks like you declared the comparePtr function pointer, but it's still not initialized; it's not pointing to your compare function (which is what I assume you wanted it to point to).
After that, a few more things:
1) comparePtr has the correct types, but compare does not. It needs to take in two const void*, but you have two const void**.
2) Once you fix the types, you could just pass compare to qsort, instead of making a function pointer and passing that.
3) I'm not convinced the first argument to qsort is correct. You want to be passing in the pointer to the first element in the array, which ought to just be fileList (I'm assuming it points to the first string in your array).
4) The third argument isn't correct either. fileList is a char**, meaning you're passing in an array of char *s, and hence the third argument should just be sizeof(char*), not the strlens of the strings.
I would adjust things so that you're just sorting a simple array, in this case of pointers to char - qsort will arrange for you to get pointers to two elements in that array (that is, char ** pointers), and some basic dereferencing is needed to get you to the "pointers to char" comparable via strcasecmp. #Mark likely has sussed out the source of the 260 in your unseen calling code, but I'm not a big fan of those kinds of 2d arrays in C.
The following functions for me, with an example main() to exercise it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare(const void *v1, const void *v2){
char *a = *(char **)v1;
char *b = *(char **)v2;
printf("comparing %s to %s\n", a, b);
return strcasecmp(a,b);
}
void sortListName(char **fileList, int noOfFiles){
printf("Sorting\n");
qsort(fileList, noOfFiles, sizeof(*fileList), compare);
return;
}
int
main(void)
{
char *filenames[] = {
"/var/www/icons/comp.gray.png",
"/var/www/error/HTTP_SERVICE_UNAVAILABLE.html.var",
"/var/www/icons/right.gif",
"/var/www/error/HTTP_NOT_IMPLEMENTED.html.var",
"/var/www/icons/pie3.png",
"/var/www/icons/pie2.png",
"/var/www/htdocs/manual/mod/mod_proxy_balancer.html",
"/var/www/htdocs/manual/programs/rotatelogs.html",
"/var/www/htdocs/manual/vhosts/mass.html",
"/var/www/icons/movie.png",
"/var/www/htdocs/manual/images/caching_fig1.png",
"/var/www/htdocs/htdig/search.html",
"/var/www/icons/generic.gif",
"/var/www/htdocs/manual/mod/quickreference.html",
"/var/www/icons/small/blank.png",
"/var/www/icons/image2.gif"
};
int i, nf = (int) (sizeof(filenames) / sizeof(filenames[0]));
puts("Unsorted:");
for (i = 0; i < nf; i++) {
puts(filenames[i]);
}
sortListName(filenames, nf);
puts("Sorted:");
for (i = 0; i < nf; i++) {
puts(filenames[i]);
}
return 0;
}
I'm trying to make a substring function on c. It must be return "cdef", but it returns nothing. How can i fix it? Thanks.
#include<stdio.h>
#include<conio.h>
#include<string.h>
char* substring( char *, int, int );
int main(){
char stuff[] = "abcdefghjklmnoprstuvyz";
printf("%s\n", stuff);
printf("%s\n", substring(stuff, 2, 6));
getch();
return 0;
}
char* substring(char *text, int a, int b){
char nText[b-a];
char tmp[2];
strcpy(nText, "");
for(int i=a; i<b; i++){
tmp[0] = text[i];
tmp[1] = '\0';
strcat(nText, tmp);
}
return nText;
}
You are making the mistake of returning a pointer to a variable that may not exist after the function returns. You need to allocate the space in the calling function and just put the result in the space provided, or create permanent space in the function with static. Note - as pointed out by Jonathan Leffler - since the space is "permanent", you can't change the length of the block from one call to the next, and you would have to pick a "sensible" value and test that b-a+1 is not longer than the space allocated. Thus my second method is more robust.
char* substring(char *text, int a, int b){
static char nText[100];
if ((b-a+1)>100) // do something! you can't copy this!
// code
return nText;
}
As Employed Russian pointed out, using a static in this way is in any case quite dangerous since another piece of code might call this function while you're still using the result of the first call. This is NOT ADVISABLE if you do any kind of multi threading, but it's a quick fix if you have a single thread.
A better formulation is
void substring(char *text, int a, int b, char *nText) {
// code, nothing to return
}
In the latter case, you create space in the calling function and pass the pointer to substring. n your main program you would have
char shortString[100];
substring(stuff, 4, 6, shortString);
printf("%s\n", shortString);
As an aside, your method for copying the substring is terribly inefficient. Consider replacing it with
for(int i=a; i<b;i++) nText[i-a]=text[i];
nText[b-a] = '\0';
From this you can see that you actually need to allocate nText[b-a+1] elements, otherwise there is no space for the final '\0'.
Your bug is here:
char* substring(char *text, int a, int b){
char nText[b-a];
...
return nText;
}
The buffer you return becomes invalid as soon as you return from the function.
GCC nicely warns you about this:
t.c:24:5: warning: function returns address of local variable [enabled by default]
How can i fix it?
You have to allocate a new buffer (and the caller will have to free it), or have the caller provide output buffer (as Floris suggested).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* substring( char *, int, int );
char* substringb(char *substr, char *text, int a, int b);
int main(){
char stuff[] = "abcdefghjklmnoprstuvyz";
char substr[5];
printf("%s\n", stuff);
printf("%s\n", substring(stuff, 2, 6));//Things to think to be able to release!
printf("%s\n", substringb(substr, stuff, 2, 6));
getch();
return 0;
}
//dynamic allocate
char* substring(char *text, int a, int b){
char *nText;
nText = (char*)malloc((b-a+1)*sizeof(char));
strncpy(nText, &text[a], b-a);
ntext[b-a] = 0;
return nText;
}
//copy to reserve area
char* substringb(char *substr, char *text, int a, int b){
substr[b-a]=0;
return strncpy(substr, &text[a], b-a);
}