I am trying to create a program that populates a fixed-size argument array using the arguments passed through the terminal. My first step is trying to create and populate the array of default argument strings, which I have succeeded in doing. However, I am now trying to use malloc() to allocate space for this array, and cannot get it to compile. I've tried everything I can think of regarding the proper syntax. I've tried doing more research into malloc() and how to use it for two dimensional arrays, but I haven't found any information that helps me. I'm stuck and not sure what to do next. Here is the code:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define MAX_NUM_OF_ARGS 5
#define MAX_ARG_SIZE 256
int main(int argc, char **argv) {
printf("%s%d\n", "Length: ", argc); //for debug purposes
// Make sure we don't have more than five arguments
if(argc > MAX_NUM_OF_ARGS) {
printf("%s", "Too many arguments. Must enter fewer than 4.");
}
// Populate the array
else{
char defaultArgs[] = "defaultArgs"; //create default argument array
//allocate memory for default array
char argumentArray[MAX_NUM_OF_ARGS][MAX_ARG_SIZE] =
(char *)malloc(MAX_NUM_OF_ARGS * MAX_ARG_SIZE * sizeof(char));
//populate array with default arguments
for (int i = 0; i < MAX_NUM_OF_ARGS; i++) {
strcpy(argumentArray[i], defaultArgs);
printf("%s\n", argumentArray[i]);
}
free(argumentArray);
return 0;
}
}
When I try to compile I get an invalid initializer error at the (char*) cast for malloc(). I've tried casting it to (char**) and (char) and also changing the sizeof(char) to sizeof(char*) and sizeof(char**).
I am not really sure what I am doing wrong at this point and I am at a loss as far as what to even try next.
You've declared argumentArray as a two-dimensional array of char. The malloc function returns a pointer, so you can't assign a pointer to an element of this array.
You need a pointer to store what's being returned. Actually, in this case you need a pointer to a pointer, and you'll need to call malloc multiple times, once for an array of pointers for the arguments, then again in a loop for each argument:
char **argumentArray = malloc(MAX_NUM_OF_ARGS * sizeof(char *));
for (int i=0; i<MAX_NUM_OF_ARGS; i++) {
argumentArray[i] = malloc(MAX_ARG_SIZE);
strcpy(argumentArray[i], defaultArgs);
printf("%s\n", argumentArray[i]);
}
You cannot store an array of strings in C, as a string is a variable-length datastructure, not a simple type.
So, decide what you want:
An array of fixed-length buffers storing strings of fixed (maximum) length.
char (*p)[MAX_LEN] = malloc(n * sizeof *p);
// Store the strings at p[0], p[1], …, p[n - 1]
A buffer storing any number of strings consecutively.
char* p = malloc(sum_of_string_lengths + count_of_strings);
// Now fill in the strings one after the other, including Terminator
An array of pointers to strings.
char** p = malloc(n * sizeof *p);
p[0] = strdup(source[0]);
// ...
// p[n - 1] = ...
With strdup() the common utility-function defined like:
char* strdup(const char* s) {
size_t n = strlen(s) + 1;
char* r = malloc(n);
if (r)
memcpy(r, s, n);
return r;
}
Try thinking about it like this:
Strings are character pointers
You need an array of character pointers
Here is an example where I make an array of char *. Essentially the pointer returned by malloc points to an area where char * will reside. Here is an illustration of what is going on.
/*
malloc_ret_ptr ---> [ char * my_str1 | char * my_str2 | char * my_str3 ]
| | |
| | |
v v v
"Thank" "You" "Chicago"
*/
int main() {
char * my_string = "this is my string";
char ** my_string_array;
my_string_array = malloc(sizeof(char*)*10); //Create an array of character pointers
//Place char * inside of char * array
my_string_array[0] = my_string;
return 0;
}
I am dealing with char arrays and pointers to the arrays.
char firstAr[10] = "First";
char secondAr[10] = "Second";
char thirdAr[10] = "Third";
char* arPtrOne = firstAr;
char* arPtrTwo = secondAr;
char* arPtrThree = thirdAr;
I also have a second set of char arrays
char fourthAr[10] = "Fourth";
char fifthAr[10] = "Fifth";
char sixthAr[10] = "Sixth";
The above char arrays and char pointers can’t be altered (I have to work with them). I need to change the char arrays that my pointers point to, so that they now point to the second set of char arrays. I know I can do this by doing the following,
arPtrOne = fourthAr;
arPtrTwo = fifthAr;
arPtrThree = sixthAr;
This is fine for my example above but if I had 100 array I would need 100 statements to point them all to new char arrays. I am hoping someone could help me find a more efficient way to do this for my example above.
To stop any duplicate effort and also help others who have the same questions discover all the relevant information, This was also posted here https://forum.arduino.cc/index.php?topic=529860.0
How about using char**?
char* l_arry[100];
You can:
l_arry[0] = //your first string;
l_arry[1] = //your second string;
l_arry[2] = //your third string;
As I could not figure out how to point the existing pointers at the new char inside a loop I decided to fill the original arrays with the new char arrays contents. To do this I created all of the new char arrays inside an array char pointers so that I could reference them in a for loop. I then created a new array of char * and pointed them to the original arrays. I then used a strcpy inside a for loop to copy the contents of the new array to the original. This means that the original pointers remain unaltered and still point to the original arrays but now the arrays have updated contents. This has the same effect as pointing the pointers at new c arrays without having to actually do so.
char firstAr[10] = "First";
char secondAr[10] = "Second";
char thirdAr[10] = "Third";
char* arPtrOne = firstAr;
char* arPtrTwo = secondAr;
char* arPtrThree = thirdAr;
char *newStrings[3][10]=
{
"Fourth",
"Fifth",
"Sixth"
};
char *newPtrs[3]=
{
firstAr,
secondAr,
thirdAr
};
for(int i = 0; i<3;i++)
{
strcpy (newPtrs[i], newStrings[i]);
}
I think the whole concept of array and array of chars in C is quite confusing. Can you please tell me if my reasoning is correct?
I have an array of array of char like this
char * array[2];
for(i=0;i<2;i++) {
array[i]=calloc(100,sizeof(char));
}
array[0] = strcpy(array[0], "blah");
array[1] = strcpy(array[1], "blahblah");
Now i want to put this array in the field of a struct (that field has type char**)
Can I go like this?
my_struct.array_field = &(array[0])
or is it a mistake?
Just assign array
my_struct.array_field = array
array is converted to char **.
And note that array is not an array of array of char, it is an array of (five) pointers to char.
No need of
array[0] = strcpy(array[0], "blah");
array[1] = strcpy(array[0], "blahblah");
although no harm except confusion. You can copy strings by just changing it to
strcpy(array[0], "blah");
strcpy(array[0], "blahblah");
If I create one array of character pointers of some size like:
char* temp[10];
//need intialisation here..
temp[0] = "BLAH";
temp[1] = "BLAH";
temp[3] = "BLAH";
.
.
.
temp[9] = "BLAH";
//Need reinitialise..
temp[10] = "BLAH";
temp[11] = "BLAH";
How do I initialise it?
How to re-initialise it with size 20 after some time?
Are malloc() and calloc() useful to do this? If yes then how to use with array of pointers to character?
[EDITED]
My code and requirement,
Basically i want read file in c but without wasting single character...
Here are the code to read data from text file,
FILE *ptr_file;
/* Allocate space for ten strings */
/* Allocate space for ten strings */
char** list = (char **)malloc(10 * sizeof(char));
/* Reallocate so there's now space for 20 strings */
/* And initialize the new entries */
ptr_file =fopen(LogFileCharName,"rb");
if (!ptr_file)
return 1;
int __index = 0;
wchar_t CurrentString[1000];
while(fgetws (CurrentString , 1000 , ptr_file) != NULL)
{
char* errorDes;
errorDes = new char[1000];
wcstombs(errorDes, CurrentString, 1000);
list[__index] = errorDes;
if( __index>10)
{
(char**)realloc(list, 20 * sizeof(char *));
}
__index++;
}
now when size exceeded 10 then in just need to resize that are.
for this i am using win32 console application type of microsoft visual studio.
You don't use arrays, but pointers and allocate on the heap, and then reallocate when needed:
/* Allocate space for ten strings */
char **temp = malloc(10 * sizeof(char *));
temp[0] = "Hello 1";
/* ... */
temp[9] = "Hello 10";
/* Reallocate so there's now space for 20 strings */
temp = realloc(temp, 20 * sizeof(char *));
/* And initialize the new entries */
temp[10] = "Hello 11";
As for initialization, it depends on what the contents of the strings are. Either you make it point to an already existing string (either string literals like in my example above, or other strings), or you allocate space for the strings on the heap as well.
Maybe something like this:
for (int i = 0; i < 10; i++)
{
char temp_string[10];
/* Create strings in the form "Hello 1" to "Hello 10" */
sprintf(temp_string, "Hello %d", i + 1);
/* Duplicate the temporary string */
temp[i] = strdup(temp_string);
}
Note: If you use e.g. strdup or malloc/calloc to allocate the actual strings, you of course have to free them as well.
After your updated question, I see a couple of problems with your code:
The first is that when do the check __index>10 then you're already two indexes out of bounds for the array. The check should be __index==9.
Doing the change above will also solve your other problem, that you will continuously reallocate once the index goes to 11 or higher.
Since you use new for the actual strings in the array, you have to use delete when freeing the actual strings.
Since you use new, you are using C++, for which there are much better facilities to handle things like this:
// Declare and open file
wifstream ifs(LogFileCharName);
std::vector<std::string> list;
std::wstring CurrentString;
while (std::getline(ifs, CurrentString))
{
// Get the needed length of the destination string
size_t length = wcstombs(nullptr, CurrentString.c_str(), 0);
char* tmp = new char[length + 1];
// Do the actual conversion
wcstombs(tmp, CurrentString.c_str(), length + 1);
// Add to list
list.emplace_back(tmp);
delete [] tmp;
}
I am trying to create an array of strings in C. If I use this code:
char (*a[2])[14];
a[0]="blah";
a[1]="hmm";
gcc gives me "warning: assignment from incompatible pointer type". What is the correct way to do this?
edit: I am curious why this should give a compiler warning since if I do printf(a[1]);, it correctly prints "hmm".
If you don't want to change the strings, then you could simply do
const char *a[2];
a[0] = "blah";
a[1] = "hmm";
When you do it like this you will allocate an array of two pointers to const char. These pointers will then be set to the addresses of the static strings "blah" and "hmm".
If you do want to be able to change the actual string content, the you have to do something like
char a[2][14];
strcpy(a[0], "blah");
strcpy(a[1], "hmm");
This will allocate two consecutive arrays of 14 chars each, after which the content of the static strings will be copied into them.
There are several ways to create an array of strings in C. If all the strings are going to be the same length (or at least have the same maximum length), you simply declare a 2-d array of char and assign as necessary:
char strs[NUMBER_OF_STRINGS][STRING_LENGTH+1];
...
strcpy(strs[0], aString); // where aString is either an array or pointer to char
strcpy(strs[1], "foo");
You can add a list of initializers as well:
char strs[NUMBER_OF_STRINGS][STRING_LENGTH+1] = {"foo", "bar", "bletch", ...};
This assumes the size and number of strings in the initializer match up with your array dimensions. In this case, the contents of each string literal (which is itself a zero-terminated array of char) are copied to the memory allocated to strs. The problem with this approach is the possibility of internal fragmentation; if you have 99 strings that are 5 characters or less, but 1 string that's 20 characters long, 99 strings are going to have at least 15 unused characters; that's a waste of space.
Instead of using a 2-d array of char, you can store a 1-d array of pointers to char:
char *strs[NUMBER_OF_STRINGS];
Note that in this case, you've only allocated memory to hold the pointers to the strings; the memory for the strings themselves must be allocated elsewhere (either as static arrays or by using malloc() or calloc()). You can use the initializer list like the earlier example:
char *strs[NUMBER_OF_STRINGS] = {"foo", "bar", "bletch", ...};
Instead of copying the contents of the string constants, you're simply storing the pointers to them. Note that string constants may not be writable; you can reassign the pointer, like so:
strs[i] = "bar";
strs[i] = "foo";
But you may not be able to change the string's contents; i.e.,
strs[i] = "bar";
strcpy(strs[i], "foo");
may not be allowed.
You can use malloc() to dynamically allocate the buffer for each string and copy to that buffer:
strs[i] = malloc(strlen("foo") + 1);
strcpy(strs[i], "foo");
BTW,
char (*a[2])[14];
Declares a as a 2-element array of pointers to 14-element arrays of char.
Ack! Constant strings:
const char *strings[] = {"one","two","three"};
If I remember correctly.
Oh, and you want to use strcpy for assignment, not the = operator. strcpy_s is safer, but it's neither in C89 nor in C99 standards.
char arr[MAX_NUMBER_STRINGS][MAX_STRING_SIZE];
strcpy(arr[0], "blah");
Update: Thomas says strlcpy is the way to go.
Here are some of your options:
char a1[][14] = { "blah", "hmm" };
char* a2[] = { "blah", "hmm" };
char (*a3[])[] = { &"blah", &"hmm" }; // only since you brought up the syntax -
printf(a1[0]); // prints blah
printf(a2[0]); // prints blah
printf(*a3[0]); // prints blah
The advantage of a2 is that you can then do the following with string literals
a2[0] = "hmm";
a2[1] = "blah";
And for a3 you may do the following:
a3[0] = &"hmm";
a3[1] = &"blah";
For a1 you will have to use strcpy() (better yet strncpy()) even when assigning string literals. The reason is that a2, and a3 are arrays of pointers and you can make their elements (i.e. pointers) point to any storage, whereas a1 is an array of 'array of chars' and so each element is an array that "owns" its own storage (which means it gets destroyed when it goes out of scope) - you can only copy stuff into its storage.
This also brings us to the disadvantage of using a2 and a3 - since they point to static storage (where string literals are stored) the contents of which cannot be reliably changed (viz. undefined behavior), if you want to assign non-string literals to the elements of a2 or a3 - you will first have to dynamically allocate enough memory and then have their elements point to this memory, and then copy the characters into it - and then you have to be sure to deallocate the memory when done.
Bah - I miss C++ already ;)
p.s. Let me know if you need examples.
If you don't want to keep track of number of strings in array and want to iterate over them, just add NULL string in the end:
char *strings[]={ "one", "two", "three", NULL };
int i=0;
while(strings[i]) {
printf("%s\n", strings[i]);
//do something
i++;
};
Or you can declare a struct type, that contains a character arry(1 string), them create an array of the structs and thus a multi-element array
typedef struct name
{
char name[100]; // 100 character array
}name;
main()
{
name yourString[10]; // 10 strings
printf("Enter something\n:);
scanf("%s",yourString[0].name);
scanf("%s",yourString[1].name);
// maybe put a for loop and a few print ststements to simplify code
// this is just for example
}
One of the advantages of this over any other method is that this allows you to scan directly into the string without having to use strcpy;
If the strings are static, you're best off with:
const char *my_array[] = {"eenie","meenie","miney"};
While not part of basic ANSI C, chances are your environment supports the syntax. These strings are immutable (read-only), and thus in many environments use less overhead than dynamically building a string array.
For example in small micro-controller projects, this syntax uses program memory rather than (usually) more precious ram memory. AVR-C is an example environment supporting this syntax, but so do most of the other ones.
In ANSI C:
char* strings[3];
strings[0] = "foo";
strings[1] = "bar";
strings[2] = "baz";
The string literals are const char *s.
And your use of parenthesis is odd. You probably mean
const char *a[2] = {"blah", "hmm"};
which declares an array of two pointers to constant characters, and initializes them to point at two hardcoded string constants.
Your code is creating an array of function pointers. Try
char* a[size];
or
char a[size1][size2];
instead.
See wikibooks to arrays and pointers
hello you can try this bellow :
char arr[nb_of_string][max_string_length];
strcpy(arr[0], "word");
a nice example of using, array of strings in c if you want it
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]){
int i, j, k;
// to set you array
//const arr[nb_of_string][max_string_length]
char array[3][100];
char temp[100];
char word[100];
for (i = 0; i < 3; i++){
printf("type word %d : ",i+1);
scanf("%s", word);
strcpy(array[i], word);
}
for (k=0; k<3-1; k++){
for (i=0; i<3-1; i++)
{
for (j=0; j<strlen(array[i]); j++)
{
// if a letter ascii code is bigger we swap values
if (array[i][j] > array[i+1][j])
{
strcpy(temp, array[i+1]);
strcpy(array[i+1], array[i]);
strcpy(array[i], temp);
j = 999;
}
// if a letter ascii code is smaller we stop
if (array[i][j] < array[i+1][j])
{
j = 999;
}
}
}
}
for (i=0; i<3; i++)
{
printf("%s\n",array[i]);
}
return 0;
}
char name[10][10]
int i,j,n;//here "n" is number of enteries
printf("\nEnter size of array = ");
scanf("%d",&n);
for(i=0;i<n;i++)
{
for(j=0;j<1;j++)
{
printf("\nEnter name = ");
scanf("%s",&name[i]);
}
}
//printing the data
for(i=0;i<n;i++)
{
for(j=0;j<1;j++)
{
printf("%d\t|\t%s\t|\t%s",rollno[i][j],name[i],sex[i]);
}
printf("\n");
}
Here try this!!!
I was missing somehow more dynamic array of strings, where amount of strings could be varied depending on run-time selection, but otherwise strings should be fixed.
I've ended up of coding code snippet like this:
#define INIT_STRING_ARRAY(...) \
{ \
char* args[] = __VA_ARGS__; \
ev = args; \
count = _countof(args); \
}
void InitEnumIfAny(String& key, CMFCPropertyGridProperty* item)
{
USES_CONVERSION;
char** ev = nullptr;
int count = 0;
if( key.Compare("horizontal_alignment") )
INIT_STRING_ARRAY( { "top", "bottom" } )
if (key.Compare("boolean"))
INIT_STRING_ARRAY( { "yes", "no" } )
if( ev == nullptr )
return;
for( int i = 0; i < count; i++)
item->AddOption(A2T(ev[i]));
item->AllowEdit(FALSE);
}
char** ev picks up pointer to array strings, and count picks up amount of strings using _countof function. (Similar to sizeof(arr) / sizeof(arr[0])).
And there is extra Ansi to unicode conversion using A2T macro, but that might be optional for your case.
Each element is a pointer to its first character
const char *a[2] = {"blah", "hmm"};
A good way is to define a string your self.
#include <stdio.h>
typedef char string[]
int main() {
string test = "string";
return 0;
}
It's really that simple.