How to Manage a 2 Dimensional Char Array? - c

Having gone through dozens of tutorials & programming guides, an answer has not become obvious, hence the post. Please be kind.
The matter at hand is the practical manipulation of double-d arrays of char.: {"aaaaa", "bbbbb", "ccccc",.... M}
The first problem is the declaration an initialisation of such beasts, with view to changing data in the strings "aaaaa", "bbbbb" etc.
The declarations and initialization go as:
char *chararray[M][N + 1] //M & N are set as constant values, the extra 1 for the null terminator.
memset (chararray, '\0', sizeof(chararray)); //Assuming array bounds remain constant, in the hope that dynamic allocation is not required
Assume there is also a string literal defined:
char *copyme; //Has been given a string value well within the bounds of N
The problem arises when attempting to use this in strcat or strcat_s (strcpy or strcpy_s similar):
strcat_s (chararray [i][0], N + 1, (char *) copyme); //i ranges from 0 to M
Having not come across any code that handles arrays this way, I did note from this tutorial that memcpy is the only way. Correct?
Also, how does one implement John Bode's General Procedure when calling the function from Main? (For the sake of brevity, this may have to be submitted as a separate question,)

Your initialization is wrong, you are declaring a 2D array of pointers not characters. Change it to char chararray[M][N + 1].
Also regarding the comment to memset, you declared the array with static dimensions, so the bounds will never change and you cannot use dynamic allocation if you picked the above method.
Basically you have the following options when using arrays of strings in C:
In case you are only dealing with read-only string literals, you could use a const char* per literal. An array of strings in that case would then be an array of const char* pointers.
Similarly, you could have an array of pointers if the strings are allocated elsewhere, not in your array. You'd have a lookup table.
If the length of the strings have a known maximum, you could declare it with static dimensions such as char chararray[M][N + 1]. This is a 2D array of characters, or if you will: an array of arrays of characters.
If the length of the strings are unknown, if you need them to be flexible, or if you are allocating large amounts of strings (several hundred), you can allocate them on the heap. In that case you should use an array of pointers, where each pointer is assigned a string through malloc followed by strcpy().

You probably meant
char chararray[M][N + 1];
in order then to copy a string you specify the first index
strcat_s(chararray[i], N + 1, (char *) copyme);
If you have declared it as
char *chararray[M][N + 1]
then you have a 2-dimensional array of pointers which are NULL and then when you derefence them you get an error:
strcat_s(chararray [i][0], N + 1, (char *) copyme); // boom!

Related

Difference between array of pointers and pointer to array?

char string1[3][4]={"koo","kid","kav"}; //This is a 2D array
char * string[3]={"koo","kid","kav"}; //This is an array of 3 pointers pointing to 1D array as strings are stored as arrays in memory
char (*string1Ptr)[4]=string1; //This is a pointer to a 1D array of 4 characters
//I want to know differences between string1Ptr(pointer to array mentioned in question) and string(array of pointers mentioned in question). I only typed string1 here to give string1Ptr an address to strings
Besides the fact that string can point to strings of any size and string1Ptr can only point to strings of size 4 only(otherwise pointer arithmetic would go wrong), I don't see any differences between them.
For example,
printf("%s\n", string1[2]); // All print the same thing, ie, the word "kav"
printf("%s\n", string1Ptr[2]);
printf("%s\n", string[2]);
They all seem to perform the same pointer arithmetic.(My reason for assuming string and string1Ptr are almost similar besides for the difference I stated above)
So what are the differences between string and string1Ptr? Any reason to use one over the other?
PS: I'm a newbie so please go easy on me.
Also, I did check C pointer to array/array of pointers disambiguation, it didn't seem to answer my question.
char string1[3][4]={"koo","kid","kav"}; //This is a 2D array
char * string[3]={"koo","kid","kav"}; //This is an array of 3 pointers pointing to 1D array as strings are stored as arrays in memory
char (*string1Ptr)[4]=string1; //This is a pointer to a 1D array of 4 characters
Besides the fact that string can point to strings of any size and
string1Ptr can only point to strings of size 4 only(otherwise
pointer arithmetic would go wrong), I don't any differences between
them.
They are absolutely, fundamentally different, but C goes to some trouble to hide the distinction from you.
string is an array. It identifies a block of contiguous memory wherein its elements are stored. Those elements happen to be of type char * in this example, but that's a relatively minor detail. One can draw an analogy here to a house containing several rooms -- the rooms are physically part of and exist inside the physical boundaries of the house. I can decorate the rooms however I want, but they always remain the rooms of that house.
string1Ptr is a pointer. It identifies a chunk of memory whose contents describe how to access another, different chunk of memory wherein an array of 4 chars resides. In our real estate analogy, this is like a piece of paper on which is written "42 C Street, master bedroom". Using that information, you can find the room and redecorate it as you like, just as in the other case. But you can also replace the paper with a locator for a different room, maybe in a different house, or with random text, or you can even burn the whole envelope, without any of that affecting the room on C Street.
string1, for its part, is an array of arrays. It identifies a block of contiguous memory where its elements are stored. Each of those elements is itself an array of 4 chars, which, incidentally, happens to be just the type of object to which string1Ptr can point.
For example,
printf("%s\n", string1[2]); // All print the same thing, ie, the word "kav"
printf("%s\n", string1Ptr[2]);
printf("%s\n", string[2]);
They all seem to perform the same pointer arithmetic.(My reason for
assuming string and string1Ptr are almost similar besides for the
difference I stated above)
... and that is where C hiding the distinction comes in. One of the essential things to understand about C arrays is that in nearly all expressions,* values of array type are silently and automatically converted to pointers [to the array's first element]. This is sometimes called pointer "decay". The indexing operator is thus an operator on pointers, not on arrays, and indeed it does have similar behavior in your three examples. In fact, the pointer type to which string1 decays is the same as the type of string1Ptr, which is why the initialization you present for the latter is permitted.
But you should understand that the logical sequence of operations is not the same in those three cases. First, consider
printf("%s\n", string1Ptr[2]);
Here, string1Ptr is a pointer, to which the indexing operator is directly applicable. The result is equivalent to *(string1Ptr + 2), which has type char[4]. As a value of array type, that is converted to a pointer to the first element (resulting in a char *).
Now consider
printf("%s\n", string1[2]);
string1 is an array, so first it is converted to a pointer to its first element, resulting in a value of type char(*)[4]. This is the same type as string1Ptr1, and evaluation proceeds accordingly, as described above.
But this one is a bit more different:
printf("%s\n", string[2]);
Here, string is a pointer, so the indexing operation applies directly to it. The result is equivalent to *(string + 2), which has type char *. No automatic conversions are performed.
Any reason to use one over the other?
Many, in both directions, depending on your particular needs at the time. Generally speaking, pointers are more flexible, especially in that they are required for working with dynamically allocated memory. But they suffer from the issues that
a pointer may be in scope, but not point to anything, and
declaring a pointer does not create anything for it to point to. Also,
even if a pointer points to something at one time during an execution of the program, and its value is not subsequently written by the program, it can nevertheless stop pointing to anything. (This most often is a result of the pointer outliving the object to which it points.)
Additionally, it can be be both an advantage and a disadvantage that
a pointer can freely be assigned to point to a new object, any number of times during its lifetime.
Generally speaking, arrays are easier to use for many purposes:
declaring an array allocates space for all its elements. You may optionally specify initial values for them at the point of declaration, or in some (but not all) cases avail yourself of default initialization.
the identifier of an array is valid and refers to the array wherever it is in scope.
Optionally, if an initializer is provided then an array declaration can use it to automatically determine the array dimension(s).
* But only nearly all. There are a few exceptions, with the most important being the operand of a sizeof operator.
The difference between string1 and string is the same as the difference between:
char s1[4] = "foo";
char *s2 = "foo";
s1 is a writable array of 4 characters, s2 is a pointer to a string literal, which is not writable. See Why do I get a segmentation fault when writing to a string initialized with "char *s" but not "char s[]"?.
So in your example, it's OK to do string1[0][0] = 'f'; to change string1[0] to "foo", but string[0][0] = 'f'; causes undefined behavior.
Also, since string is an array of pointers, you can reassign those pointers, e.g. string[0] = "abc";. You can't assign to string1[0] because the elements are arrays, not pointers, just as you can't reassign s1.
The reason that string1Ptr works is because the string1 is a 2D array of char, which is guaranteed to be contiguous. string1Ptr is a pointer to an array of 4 characters, and when you index it you increment by that number of characters, which gets you to the next row of the string1 array.

C - Convert int to char

I am looking for a solution for my problem (newbie here).
I have an array of strings (char** arrayNum) and I would like to store the number of elements of that array at the first index.
But I can't find the right way to do convert the number of elements as a string (or character).
I have tried itoa, casting (char), +'0', snprintf ... nothing works.
As every time I ask a question on Stack Overflow, I am sure the solution will be obvious. Thanks in advance for your help.
So I have an array of strings char** arrayNum which I populate, leaving the index 0 empty.
When I try to assign a string to arrayNum[0]:
This works: arrayNum[0] = "blabla";
This does not work: arrayNum[0] = (char) ((arraySize - 1)+'0');
I have tried countless others combinations, I don't even remember...
arrayNum can be thought of as an array of strings (char *). So you will naturally have trouble trying to assign a char (or indeed any type other than char *) to an element of this array.
I think it would preferable to store the length of the array separately to the array. For example, using a struct. To do otherwise invites confusion.
If you really, really want to store the length in the first element, then you could do something like:
arrayNum[0] = malloc(sizeof(char));
arrayNum[0][0] = (char) ((arraySize - 1)+'0');
This takes advantage of the fact that arrayNum is strictly an array of pointers and each of those pointers is a pointer to a char. So it can point to a single character or an array of characters (a "string").
Compare this for clarity with (say):
struct elements {
int length;
char **data;
};
arrayNum is not an "array of strings."
It might be useful for you to think about it that way, but it is important for you to know what it really is. It is an array of pointers where each pointer is a pointer to char.
Sometimes a pointer to char is a "string," and sometimes it's a pointer into the middle of a string, and sometimes it's just a pointer to some character somewhere. It all depends on how you use it.
The C programming language does not really have strings. It has string literals, but a string literal is just a const array of characters that happens to end with a \000. The reason you can write arrayNum[0] = "blabla"; is because the value of the string literal "blabla" is a pointer to the first 'b' in "blabla", and the elements of the arrayNum array are pointers to characters.
It's your responsibility to decide whether arrayNum[i] points to the first character of some string, or whether it just happens to point to some single character; and it's your responsibility to decide and keep track of whether it points to something that needs to be freed() or whether it points to read-only memory, or whether it points to something on the stack, or whether it points to/into some staticly allocated data structure.
The language doesn't care.

Different pointer notations in 2D Arrays?

These are the notations used for 2D Arrays
char (*names)[5] ;
and
char* names[] = {"Jan","Feb"};
and
char names[3][5] = { Initializers..};
I'm getting extremely confused between these notations.
The 1st one declares names to be a pointer to an array of 5 chars i.e
names -> a char pointer -> "Some string"
The 3rd one has a different memory map, i.e it is stored in row major order like a normal array unlike the one stated above.
How is the 2nd notation similar or different from the 1st and 3rd notation.?
Also passing them to functions is a different story altogether. If we declare the 2d array to be of type 2, then it is passed as a double pointer (char** names) while if it is of type 1 or type 3, the columns should be mentioned in the declaration.
Please help me attain more clarity over these issues.
Thanks.
Only one of those examples is a 2D array:
char names[3][5];
The others are different:
char (*names)[5] ;
is a pointer to a 1D array, and:
char* names[] = {"Jan","Feb"};
is a 1D array of pointers.
I'm going to rename them now to be clearer:
char a[3][5];
char (*b)[5];
char *c[3];
a is the only real two dimensional array. That is, it occupies contiguous memory and has room for three strings, each 5 characters long (including null terminator).
b is a pointer to an array; no storage for any potential contents of that array is included.
c is an array of pointers, each can be used to point to any string you happen to care about; no storage is reserved for any of the strings themselves, just for the three pointers.
If you have a function with a prototype like:
void myfunction(char **p);
Only c can be passed to this function; the others won't behave the way you'd like them to.

is there a difference between malloc ** and *

I am wondering if there is a difference between doing this
char ** str;
str=(char **)malloc(sizeof(char*) * ARRAY_LEN);
and doing this :
str=(char*)malloc(sizeof(char)* ARRAY_LEN);
for(i=0;i<ARRAY_LEN;i++)
*(str+i)=(char*)malloc(sizeof(char)* ARRAY_LEN);
and doing this is the same too :
char str[ARRAY_LEN][ARRAY_LEN];
Yes, one is a pointer to a pointer to char, and the other is a pointer to char, there is a very big difference. between those. You can think of it as an array of strings in the first case, and a single string in the second.
Of course, in the first case you have to somehow allocate memory for the actual strings in the "array".
It all depends on what you want to achieve. I guess it is an array of strings, but maybe neither of your snippets will perform what you want. So let's go over them:
char ** str;
str=(char **)malloc(sizeof(char*) * ARRAY_LEN);
str is a pointer to a pointer to char. This could indeed be used for that purpose. The malloc then properly allocates space for ARRAY_LEN number of pointers to char, also OK for the intended purpose. The problem may lie in that there are no actual strings allocated, that is, all the ARRAY_LEN pointers to char are left pointing to God knows where (malloc() does not initialize them, not even to NULL). One way to properly finish this up would be setting all the pointers to NULL indicating your string list is empty.
str=(char*)malloc(sizeof(char)* ARRAY_LEN);
for(i=0;i<ARRAY_LEN;i++)
*(str+i)=(char*)malloc(sizeof(char)* ARRAY_LEN);
I assume str is still a pointer to a pointer to char. Then the cast itself will be invalid, as well as occupying just ARRAY_LEN bytes (sizeof(char) evaulates to 1) for ARRAY_LEN number of pointers (well, undefined as soon as you try to access all those...). The second part, the for loop would be OK for completing the first scenario if you wanted a rectangular array of chars, but this case the assignment to *(str+i) will likely cause a segfault when the loop starts writing outside the insufficient storage allocated for str.
char str[ARRAY_LEN][ARRAY_LEN];
This is a plain rectangular 2 dimensional array of chars. Note that it is conceptually different from both of the above! str can't decay to have an equal meaning to char ** str above since it's 2 dimensional (one dimensional arrays may decay to pointers as needed).
In all three cases it seemed you tried to get a rectangular (ARRAY_LEN * ARRAY_LEN) storage of characters, in the first two in the form of double indirection, in the last as a 2 dimensional array. This might not be what you wanted to do, probably you rather wanted to get an array of strings. If you don't know anything about the strings in advance, and neither their maximum length, this is more complicated to perform properly (you might want to handle all strings separately, by some means depending on use case figuring out their length, and allocating accordingly - probably even needing coding dynamically growing storage). Otherwise if you know or can limit the maximum length (pay attention to a terminating zero), you may allocate accordingly, and then limit the string lengths while you read them in.
Hope it helps.

C Array of strings

I want to create an array of strings. The problem is that I want to be able to access the length of each string statically. I tried this:
char *a[] = {"foo", "foobar"};
The array works fine except that I want to know the length of each element statically.
I can't use sizeof(a[0]) because it returns the size of the char * pointer. What I want is the length of the size of the string (4 for a[0], 7 for a[1]).
Is there any way to do this?
In short, no, not at compile-time (at least not for an arbitrary number of strings). There are various run-time initialization-like things you can do, as others have pointed out. And there are solutions for a fixed number of strings, as others have pointed out.
The type of a[0] must be the same as that of a[1] (obviously). So sizeof() must evaluate to the same for all values of a[i].
Depending on your definition of "string", a is not an array of strings: it is an array of pointers (I define "string" as array of N characters including a null terminator).
If you want an array of lengths and strings (each capable of holding 999 characters and the null terminator), you may do something like
struct lenstring { size_t len; char data[1000]; };
struct lenstring a[] = {
{ sizeof "foo" - 1, "foo" },
{ sizeof "foobar" - 1, "foobar" },
};
Example with simplifying macro running at ideone
The only safe way to know the length of strings statically is to declare them all individually.
char foo[] = "foo";
char foobar[] = "foobar";
char *a[] = {foo, foobar};
You might be able to use a macro to eliminate some of the drudgery, depending on the strings' contents. sizeof(a[0]) will still be sizeof(char*), though.
You can't statically initialize a data structure with the result of strlen(), you could loop over your strings and store the string length in an initialization function.
You can't. sizeof doesn't return the length of the string, but the size of the array, which in your second case is much larger than the length of the string. You need to use strlen or, perhaps, a more featured string type:
struct {
size_t len;
char data[];
} string;
But it'd be a bit more complicated to make an array of them in that case.
if you use char*a[] = {"foo", ...} style of decleration, then you can use strlen(a[0]), strlen(a[1]) etc to find the length of each string.
Maybe you could start with something like this:
size1 = abs(a[0] - a[1]);
That will give you the difference between the beginning address of the first string and the beginning address of the second string. Therefore the size of the first string.
Then you could use some loop and array to get all the sizes.
It is not statically but maybe you could try it.

Resources