I want to use an array of string the same as this:
char arr[][20] = {"username1", "username2"};
after i have not problem to get values, for example :
printf("%s", arr[0]); // for "username1"
i have problem to insert new string to this array, something like this!? :
arr[2] = "username3"; // or sprintf(arr[2], "%s", "username3");
You're trying to insert a char* into an array of char[20]. That won't work. You could use strcpy as
strcpy(arr[2], "username3");
if you had allocated sufficient space for a third string, which you haven't. I suggest you read up on malloc and friends; you can't just append a string to this array.
With this static initialization, arr will not dynamically resize to hold a new entry (pointers to entries in the stack generally don't like being written to).
In order for this to work, arr should be of char ** and allocated properly:
// allocate enough for three entries in arr
char **arr = (char **) malloc(3 * sizeof(char *));
The wrong way of doing this would be as follows:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
char arr[][20] = {"username1", "username2"};
printf("%s\n", arr[0]);
printf("%s\n", arr[1]);
printf("sizeof arr : %d \n", sizeof(arr)/sizeof(*arr));
strcpy(arr[2],"username3");
printf("%s\n", arr[2]);
printf("sizeof arr : %d \n", sizeof(arr)/sizeof(*arr));
return 0;
}
because, when you write something like the below
char arr[][20] = {"username1", "username2"};
The first dimension is automatically calculated based on the given initializer, in this case, it is 2 (i.e. index 0 and 1).
Later when you try to access (read or write), the third element i.e. index 2, it is a undefined behavior.
If you want to increase the first dimension of a 2d array, the correct way of doing that would be as follows:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LEN 20
int main(void)
{
char **arr = NULL;
int n=2, n1;
int i;
if ((arr = malloc(sizeof(char *) * n)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
for (i=0; i<n ; i++) {
if ((arr[i] = malloc(sizeof(char) * LEN)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
}
strcpy(arr[0], "username1");
strcpy(arr[1], "username2");
printf("%s\n", arr[0]);
printf("%s\n", arr[1]);
/* add 5 more elements to arr */
n1 = 5;
if ((arr = realloc(arr, sizeof(char *) * (n + n1))) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
for (i=n; i<n1+n ; i++) {
if ((arr[i] = malloc(sizeof(char) * LEN)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
}
strcpy(arr[2], "username2");
strcpy(arr[3], "username3");
strcpy(arr[4], "username4");
strcpy(arr[5], "username5");
strcpy(arr[6], "username6");
/* if you uncomment the below, it will lead to undefined behavior */
//strcpy(arr[7], "username7");
for (i=0; i<n+n1 ; i++)
printf("%d : %s \n", i, arr[i]);
for (i=0; i<n+n1 ; i++)
free(arr[i]);
free(arr);
return 0;
}
$ ./a.out
username1
username2
0 : username1
1 : username2
2 : username2
3 : username3
4 : username4
5 : username5
6 : username6
$
Hope this helps!
C does not have dynamically growing data structures built-in. If you want an array that can hold an increasing number of elements, you need to involve dynamic memory allocation. This is usually done using the realloc() function, which can be used to allocate and then re-allocate a memory block, so that you can grow the allocation as needed.
Related
I have a 2d pointer array:
char **fields = calloc(1, sizeof(char *));
I add to it different strings, like this:
if(i > 0) fields = realloc(fields, (i+1) * sizeof(char *));
fields[i] = calloc(size, sizeof(char));
I then use memcpy into the fields[i] the desired string.
At the end of the program, when I try to free fields, I do it like this:
int j=0
while(fields != NULL && fields[j]){
free(fields[j]);
j++;
}
free(fields);
The program inserts 4 strings into fields.
The first string frees as expected, however on the second iteration of the loop (j=1) the program stops and outputs the error: free(): invalid pointer
EDIT: I made a short program with the same problem:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
char **fields = calloc(1, sizeof(char *));
int fieldsIndex = 0,i=0;
while (i<4) {
if(fieldsIndex > 0){
fields = realloc(fields, (fieldsIndex + 1) * sizeof(char *));
fields[fieldsIndex] =NULL;
printf("amount of field places: %d\n", (fieldsIndex + 1));
}
fields[fieldsIndex] = calloc(8, sizeof(char));
fields[fieldsIndex] = "88888888";
fieldsIndex++;
i++;
}
int j=0;
for(j=0; j<i; j++){
printf("field: %s\n", fields[j]);
free(fields[j]);
}
free(fields);
return 0;
}
Can anyone help?
Addressing mainly the MRE.
The main problems are around this line:
fields[fieldsIndex] = "88888888";
It's not right for two reasons:
Firstly you need one more element in the array for the null byte.
Secondly, you make the fields[fieldsIndex] pointers point to string literals, it not only causes a memory leak, but also those string literals are usually stored in a readonly section of memory, either way the behavior freeing a pointer pointing to a string literal is undefined.
You need to copy the strings to the memory you just allocated. Using memcpy should work as long as you reserve enough memory as mentioned in the previous point, a cleaner way would be to use strdup.
Another issue is if(fieldsIndex > 0) because then fields[0] will not have allocated memory.
Some other notes, if you know the amount of strings (i < 4) you shouldn't need to realloc, just allocate space for all the pointers in the first calloc* (assuming that is not brought about by the construction of the MRE) , also i and fieldsIndex seem to be redundant.
Here is a demo keeping realloc (as it's tangential to the OP):
int main()
{
char **fields = NULL;
char **tempfields; // I advise the use of an auxiliary pointer for reallocation
int fieldsIndex = 0;
while (fieldsIndex < 4)
{
tempfields = realloc(fields, (fieldsIndex + 1) * sizeof *fields); //*
if (!tempfields)
{
// handle the allocation error appropriately
}
fields = tempfields;
printf("amount of field places: %d\n", (fieldsIndex + 1));
fields[fieldsIndex] = strdup("88888888");
// Or
// fields[fieldsIndex] = calloc(9, sizeof **fields); // check return
// strcpy(fields[fieldsIndex], "88888888");
fieldsIndex++;
}
// With int iterator
int j = 0;
for (j = 0; j < fieldsIndex; j++)
{
printf("field: %s\n", fields[j]);
free(fields[j]);
}
free(fields);
}
Or with a sentinel element in fields:
Live demo
// With sentinel
tempfields = realloc(fields, (fieldsIndex + 1) * sizeof *fields);
if (!tempfields)
{
// handle the allocation error appropriately
}
fields = tempfields;
fields[fieldsIndex] = NULL;
while (*fields)
{
printf("field: %s\n", *fields);
free(*fields);
fields++;
}
free(tempfields);
To allocate and free a single string in C, I do the following:
char[10] stringToCopy = "CopyString";
int length = strlen(stringToCopy) + 1;
char* CopiedString = malloc(length);
strcpy(CopiedString, stringToCopy, length);
printf("DatabasePath=%s\r\n", CopiedString);
free(CopiedString);
In my program, I need to copy such strings to a char** datatype. I need help in writing such a program. I am using a third party API which has a structure with this char** field entry.
I am not aware of how to allocate memory to this datatype and then copy the CopiedString into a list of such values. And also how to free the value after usage.
Allocating memory:
char **arr = malloc(r * sizeof(char *));
for (i=0; i<r; i++)
{
arr[i] = malloc(c * sizeof(char));
}
Freeing memory:
for (i=0; i<r; i++)
{
free(arr[i]);
}
free(arr);
I am not aware of how to allocate memory to this datatype ....
Follows is a useful C idiom for allocating.
size_t number_in_array = ...;
ptr = malloc(sizeof *ptr * number_in_array);
if (ptr == NULL) {
puts("Allocation failed");
} else {
puts("Success");
// Use ptr
free(ptr): // **
}
...
free(ptr): // **
// ** free(ptr) in 1 of 2 places.
Notice there is no need to code the type of the pointer in the allocation: ptr = malloc(sizeof *ptr * number_in_array);. This is easier to code right, review and maintain than attempting to code the type.
... then copy the CopiedString into a list of such values.
You already have good code to form a copied string. Make a helper function. Below is OP's with some improvements. Also research the common strdup() function.
char *my_strdup(const char *stringToCopy) {
size_t size = strlen(stringToCopy) + 1;
char* CopiedString = malloc(size);
if (CopiedString) {
memcpy(CopiedString, stringToCopy, size);
}
return CopiedString;
}
And also how to free the value after usage.
size_t number_in_array = 3;
char **ptr = malloc(sizeof *ptr * number_in_array);
if (ptr == NULL) {
puts("Allocation failed");
} else {
ptr[0] = my_strdup("Hello");
ptr[1] = my_strdup(" ");
ptr[2] = my_strdup("World");
// Use ptr (could check for ptr[] allocation failures first)
for (size_t i = 0; i < number_in_array; i++) {
free(ptr[i]);
}
free(ptr):
}
You can use strdup to create malloced string in c.
char ** presult = NULL;
for double pointer "presult" we can assign data like this.
if (presult) {
*presult = strdup("CopyString");
}
Sample code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int copy_data(char ** p) {
if (p) {
*p = strdup("Test data");
}
return 0;
}
int main () {
char * p = NULL;
copy_data(&p);
if (p) {
printf("daat : %s\n", p);
// free if not used
free(p);
p = NULL;
}
return 0;
}
Go through the below program which explains how to allocate memory for char** and also how to free the same.
Comments are in lined for understanding, please get back in case of any clarification needed.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define NUMBER_OF_STRINGS 5
#define MAX_LEN_OF_STRING 50
void printStrings_array(char ex_strings[][MAX_LEN_OF_STRING], int nstrings);
char** allocMemForStrings(int nStrings);
void printStrings_ptr(char** strings, int nStrings);
int main()
{
// example list of string for which we are going to allocate memory and store in char**
char ex_strings[NUMBER_OF_STRINGS][MAX_LEN_OF_STRING] =
{
"This is the First String",
"This is the Second String",
"This is the Third String",
"This is the Fourth String",
"This is the Fifth String",
};
printf("contents of char[][] \n");
printStrings_array(ex_strings, NUMBER_OF_STRINGS);
// list_of_strings is a variable which points to list of strings
char** list_of_strings = NULL;
// allocating memory for list of strings
if ( list_of_strings = allocMemForStrings(NUMBER_OF_STRINGS))
{
int i = 0;
printf("got %p for list_of_strings\n", (void*)list_of_strings);
while(i < NUMBER_OF_STRINGS)
{
size_t len = strlen(ex_strings[i])+1;
// allocate memory for each string as per its length
list_of_strings[i] = malloc(len);
printf("got %p for string %d\n", (void*)list_of_strings[i], i);
memset(list_of_strings[i], 0, len);
strncpy(list_of_strings[i], ex_strings[i], len);
i++;
}
printf("contents of char** \n");
printStrings_ptr(list_of_strings, NUMBER_OF_STRINGS);
// free ing the memory for char **
// first we need to free the memory for each of the strings pointed by the list_of_strings variable.
i = 0;
while(i < NUMBER_OF_STRINGS)
{
printf("\n freeing %p ", (void*)list_of_strings[i]);
free(list_of_strings[i]);
list_of_strings[i] = NULL;
i++;
}
//now free the list_of_strings pointer
printf("\n finally freeing %p ", (void*)list_of_strings);
free(list_of_strings);
// to avoid dangling pointers, its best practice to set the pointers = NULL after free.
list_of_strings = NULL;
}
else
{
printf("cannot allocate memory for strings\n");
}
return 0;
}
void printStrings_array(char ex_strings[][MAX_LEN_OF_STRING], int nstrings)
{
for(int i = 0; i< nstrings;i++)
printf(" %s\n", ex_strings[i]);
}
void printStrings_ptr(char** strings, int nStrings)
{
for(int i = 0; i< nStrings;i++)
printf(" %s\n", strings[i]);
}
char** allocMemForStrings(int nStrings)
{
// need to have memory to store nStrings
return malloc(nStrings * sizeof (char*));
}
I want to allocate some memory to one of the members of a dynamic structure, dynamically. But I don't know what do I do and also, i don't know how to use them after allocating.
This is my code work :
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
int main()
{
struct Sample_Structure {
float *Number_ptr; // This is the pointer to allocate some memory, dynamically.
int Num1;
int Num2;
} *struct_ptr;
struct_ptr = (struct Sample_Structure*) malloc (sizeof (struct Sample_Structure));
if (!struct_ptr)
{
printf("An error occurred while allocating memory.\n");
exit(1);
}
// I don't know what do I write here to allocate some memory to the pointer, "Number_ptr" in the structure
printf("Enter your number 1 and 2 : ");
scanf("%d%d", &struct_ptr->Num1, &struct_ptr->Num2);
system("cls");
printf("Your numbers are %d and %d\n", Struct_ptr->Num1, Struct_ptr->Num2);
return 0;
}
I wrote some comments for you to know where did I want to allocate some memory to the pointer of the structure, "Sample_Structure". Generally, can we do that? If yes, how?
you can allocate memory the for it , the same way you allocated for *struct_ptr
like this
struct_ptr->Number_ptr = (float *) malloc(sizeof(float));.
and when you want to scan data for it you shouldn't use & for it:
scanf("%d%d%f", &struct_ptr->Num1, &struct_ptr->Num2, struct_ptr->Number_ptr);
and in printf you should use * for it:
printf("Your numbers are %d and %d\nand %f\n", struct_ptr->Num1, struct_ptr->Num2, *struct_ptr->Number_ptr);
also you should this capital S to lowercase letter in this printf:
printf("Your numbers are %d and %d\n", struct_ptr->Num1, struct_ptr->Num2);
also note that you don't need to cast for malloc and it's not good to that , unless you're using c++ compiler.
int main()
{
struct Sample_Structure {
float* Number_ptr;
int Num1;
int Num2;
} *struct_ptr;
struct_ptr = (struct Sample_Structure *)malloc(sizeof(struct Sample_Structure));
if (!struct_ptr)
{
printf("An error occurred while allocating memory.\n");
exit(1);
}
struct_ptr->Number_ptr = (float *) malloc(sizeof(float));
printf("Enter your number 1 and 2 : ");
scanf("%d%d%f", &struct_ptr->Num1, &struct_ptr->Num2, struct_ptr->Number_ptr);
system("cls");
printf("Your numbers are %d and %d\nand %f\n", struct_ptr->Num1, struct_ptr->Num2, *struct_ptr->Number_ptr);
return 0;
}
For example, you want to allocate memory for 10 floats for Number_ptr:
struct_ptr->Number_ptr = malloc( sizeof(float) * 10 );
Correction:
Change this line
printf("Your numbers are %d and %d\n", Struct_ptr->Num1, Struct_ptr->Num2);
^ ^
to
printf("Your numbers are %d and %d\n", struct_ptr->Num1, struct_ptr->Num2);
And, you're leaking memory. You need to deallocate memory using free() after use. Make sure for every allocation e.g. malloc(), there is corresponding deallocation e.g. free().
Also, validate if the memory is allocated or not.
Here's a small example for your reference (live):
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define MAX 10
typedef struct S
{
int* ilist;
} S;
int main()
{
S s;
s.ilist = malloc( MAX * sizeof(*s.ilist) ); // allocation
if ( s.ilist == NULL )
{
printf("Unable to allocate memory!\n");
return -1;
}
// An assertion may also be used like this (Header: <assert.h>):
// assert( s.ilist != NULL );
for ( int i = 0; i < MAX; ++i )
{
s.ilist[i] = i + 1; // store elements
}
for ( int i = 0; i < MAX; ++i )
{
printf("%d ", s.ilist[i]); // read elements
}
free( s.ilist ); // deallocation
return 0;
}
Output:
1 2 3 4 5 6 7 8 9 10
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int isPresent(char *array[], char *string, int dimension) {
for (int i=0; i<dimension; i++) {
if (strcmp(array[i], string) != 0) {
continue;
} else {
return 1;
}
}
return 0;
}
int main(int argc, char *argv[]) {
int dim = 0;
char **without_duplicates = malloc(dim * sizeof(char *));
for (int i=1; i<argc; i++) {
if (!isPresent(without_duplicates, argv[i], dim)) {
realloc(without_duplicates, (dim + 1) * sizeof(char *));
without_duplicates[dim] = malloc((strlen(argv[i]) + 1) * sizeof(char));
strcpy(without_duplicates[dim], argv[i]);
printf("%s\n", without_duplicates[dim]);
dim++;
} else {
continue;
}
}
printf("%s\n", "Not duplicated arguments:");
for (int i=0; i<dim; i++) {
printf("%s\n", without_duplicates[i]);
}
return 0;
}
I execute the code: ./a.out rome turin rome milan venice milan florence.
But obtain segmentation fault error.
I tried to debug the code and it works until a certain point.
For example it copies rome, turin, discards rome, copies milan, but not venice and the other cities.
If it works for some cities why not with the others?
The program has an unexpected behavior, and crashes at different points with different arguments.
I don't know the number of arguments and their length, so the new array without the duplicates must be allocated dynamically.
In your code, you are not assigning the return value of realloc to any variable
realloc(without_duplicates, (dim + 1) * sizeof(char *));
According to cppreference:
On success, returns the pointer to the beginning of newly allocated memory. The returned pointer must be deallocated with free()or realloc(). The original pointer ptr is invalidated and any access to it is undefined behavior (even if reallocation was in-place).
On failure, returns a null pointer. The original pointer ptr remains valid and may need to be deallocated with free() or realloc().
Try doing something like
char** temp = realloc(without_duplicates, (dim + 1) * sizeof(char *));
if(temp != NULL) {
without_duplicates = temp
}
else {
//handle the unsuccessful allocation
}
Note: Similarly you need to check for malloc() whether the memory allocation was successful or not.
Try this: I also allowed myself to remove some useless statements within your code, hope you dont mind
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int isPresent(char *array[], char *string, int dimension)
{
for (int i=0; i<dimension; i++)
{
if (strcmp(array[i], string) == 0)
return 1;
}
return 0;
}
int main(int argc, char *argv[])
{
int dim = 0;
char ** without_duplicates = malloc(dim * sizeof(char *));
for (int i=1; i<argc; i++)
{
if (!isPresent(without_duplicates, argv[i], dim))
{
without_duplicates = realloc(without_duplicates, (dim + 1) * sizeof(char *));
without_duplicates[dim] = malloc((strlen(argv[i]) + 1) * sizeof(char));
strcpy(without_duplicates[dim], argv[i]);
dim++;
}
}
printf("%s\n", "Not duplicated arguments:");
for (int i=0; i<dim; i++)
{
printf("%s\n", without_duplicates[i]);
}
return 0;
}
Your problem was simply not getting the return value out of realloc function,
C is not what one may consider as a high-level programming language... If reallocating some memory, the variable storing that address must be aware of the new address of the new allocated memory hence you must store it:
without_duplicates = realloc(without_duplicates, (dim + 1) * sizeof(char *));
This caused segmentation fault because before storing the new allocated address you simply jumped to an address that does not exist within the context of your process and attempt store some data in it, that in result causes segmentation fault
i have a problem with the initialization of the values inside the first dynamic array of pointers
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char*** GetIndexes()
{
int n = 0;
char ***index;
printf("please insert the number of words you want to add to dictionary\n");
scanf("%d", &n);
index = (char***)calloc(n, sizeof(char));
if (index == NULL)
{
printf("allocation Failed");
return;
}
return index;
}
char** GetDefinitions()
{
int n = 0;
char **definition;
printf("please insert the number of defintions you want to add to the word\n");
scanf("%d", &n);
definition = (char**)calloc(n+1, sizeof(char));
if (definition == NULL)
{
printf("allocation failed");
return;
}
return definition;
}
int main()
{
char *** dptr = GetIndexes();
if (dptr == NULL)
{
printf("memory Allocation failed");
}
int indexcount = sizeof(dptr) / sizeof(char),i;
for (i = 0; i < indexcount; i++)
{
printf("word number %d\n", i + 1);
*dptr[i] = GetDefinitions();
}
printf("%p",dptr);
}
i tried running the debugger in VS2013 and after i enter the number of defintions i want it crashed with this message:
Unhandled exception at 0x01103FB0 in ConsoleApplication1.exe: 0xC0000005: Access violation writing location 0x00000000.
i missed an allocation of something but i cant quite figure out what i missed,
thanks in advance
Your program is very broken
You allocate n char ***s but only request space for n chars and also do it for char **, to prevent this kind of mistake you may use the sizeof operator this way
char ***index;
index = calloc(n, sizeof(*index));
and
char **definition;
definition = calloc(n, sizeof(*definition));
and as you see casting calloc makes it harder and it's not necessary.
You have a return statement that doesn't return anything an GetIndexes() as well as one in GetDefinitions.
They should return NULL if you want to handle failure in the caller function
return NULL;
You erroneously use the sizeof operator to determine the number of char *** pointer allocated in
int indexcount = sizeof(dptr) / sizeof(char)
this will be either 4 or 8 depending on the architecture i.e. the size of a pointer divided by 1 sizeof(char) == 1 always.
You can't compute that value, you simply have to keep track of it. The size
You dereference the triple pointer twice and try to assign a double pointer to it
*dptr[i] = GetDefinitions();
here the operator precedence is also an issue, but regardless of that, this is wrong, may be what you meant was
dptr[i] = GetDefinitions();
This is not going to make your program crash, but it's certainly important to free all malloced pointers before exiting the program.
Here is a suggestion for your code to work, ignore it's purpose since it's not clear what you are trying to do
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char ***GetIndexes(unsigned int *count)
{
char ***index;
printf("please insert the number of words you want to add to dictionary > ");
scanf("%u", count);
index = calloc(*count, sizeof(*index));
if (index == NULL)
{
printf("allocation Failed");
return NULL;
}
return index;
}
char **GetDefinitions(unsigned int *count)
{
char **definition;
printf("please insert the number of defintions you want to add to the word > ");
scanf("%u", count);
definition = calloc(*count + 1, sizeof(*definition));
if (definition == NULL)
{
printf("allocation failed");
return NULL;
}
return definition;
}
int main()
{
unsigned int indexCount, i;
char ***dptr = GetIndexes(&indexCount);
if (dptr == NULL)
{
printf("memory Allocation failed");
}
for (i = 0; i < indexCount; i++)
{
unsigned int definitionsCount;
printf("Word number %u\n", i + 1);
dptr[i] = GetDefinitions(&definitionsCount);
if (dptr[i] != NULL)
{
/* use dptr[i] here or maybe somewhere else, but when you finish */
free(dptr[i]);
}
}
printf("%p", dptr);
/* now if you are done using dptr */
free(dptr);
return 0;
}
As already mentioned in the comment this is a very bad idea and just using double pointers is good here. But the below fixes should be done if you want to use pointers to allocate memory
index = calloc(n, sizeof(char));
should be
index = calloc(n, sizeof(char **));
and
definition = calloc(n+1, sizeof(char));
should be
definition = calloc(n+1, sizeof(char *));