C Array of strings - c

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.

Related

Strings of characters implementation

In C, how can I declare and use/manipulate a an array of strings?
For example, it could be
a[1]="Apples";
a[2]="Pineapples are red"
How can I access these elements and modify them?
In your code, a must be an array of pointers to char, e.g. char *a[5], to which you then assign pointers to string literals:
a[1]="Apples";
a[2]="Pineapples are red";
You can modify an element in the sense to let it point to a different string, e.g. a[1]="another fruit";. You can access an entire string like, for example, printf("%s", a[1]), and you can access single characters like, for example, char willBeA_p = a[1][1]; But you cannot modify the contents of the strings in your example, because they are string literals (and modifying string literals yields undefined behaviour). So a[1][1]='b' is not allowed.
you can define an array of strings like:
char * array_of_strings[100];
and use malloc to allocate memory for each of them.
array_of_strings[0] = (char *) malloc(100);
array_of_strings[0] = "here is your string";
Declaration: data_type array_name[array_size];
Example: float mark[5];
You can access elements of an array by indices. Suppose you declared an array mark as above. The first element is mark[0], second element is mark[1] and so on.
It's possible to initialize an array during declaration. For example.
int mark[5] = {19, 10, 8, 17, 9};

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.

How to Manage a 2 Dimensional Char Array?

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!

Array length counting anomaly

The count is returning unpredictable results. Sometimes they are right. Sometimes totally weird. Anyone can tell me what is wrong?
#include <stdio.h>
int len(int[]);
int main (int argc, const char * argv[])
{
int a[]={1,2,3,4,5,6,7,8};
int* i = a;
printf("length is %d",(len(i)));
return 0;
}
int len(int* a){
int count = 0;
for (; *a!='\0'; a++) {
count++;
}
return count;
}
There is not going to be a zero at the end of your array unless you put one there! A literal char array defined using a character string does, indeed, have such a sentinel value, but they're special; other arrays have no equivalent.
The len() function you're trying to write cannot be written for general arrays in C -- there's no way to determine the size of a dynamic array without using the (undocumented, platform-specific) internals of the memory allocator. If it was important to do this for your application, you could only do it if it were possible for you to add a zero at the end of every array yourself, explicitly.
I think you're confused between C strings (arrays of char) and other arrays. It's a convention that C strings are terminated with a null character ('\0'), but not all arrays (even char arrays) are terminated this way.
The general convention is to either store the length of an array somewhere, or to use a sentinel value at the end of the array. This value should be one that won't come up inside the array - eg '\0' in strings, or -1 in an array of positive ints.
Also, if you know that a is an int array (and not a pointer to an int array), then you can use:
size_t length = sizeof(a) / sizeof(a[0]);
So you could do:
int a[] = {1,2,3,4,5,6,7,8};
size_t length = sizeof(a) / sizeof(a[0]);
// In this case, sizeof(a[0])
// is the same as sizeof(int), because it's an int array.
But you can't do:
int *a = malloc(sizeof(int) * 10);
size_t length = sizeof(a) / sizeof(a[0]); // WRONG!
That last example will compile, but the answer will be wrong, because you're getting the size of a pointer to the array rather than the size of the array.
Note that you also can't use this sizeof to read the size of an array that's been passed into a function. It doesn't matter whether you declare your function len(int *a) or len(int a[]) - a will be a pointer, because the compiler converts arrays in function arguments to be a pointer to their first element.
You cannot count arrays like that. Only strings are null terminated. If you want that to work reliably, you will need to add an additional element to your array that contains '\0'. But be sure to remember to take into account that your length will no be one larger then the true length because of that '\0'
Unlike strings, normal arrays do not terminate with a null byte 0x00. The reason strings use this is because arrays have no concept of length; arrays are merely contiguous pieces of memory, it is up to you to keep track of the length of arrays.

Is this possible? [pointer to char array C]

Is this possible?
size_t calculate(char *s)
{
// I would like to return 64
}
int main()
{
char s[64];
printf("%d", calculate(s));
return 0;
}
I want to write a function which calculates the size of the char array declared in main().
Your function calculate(), given just the pointer argument s, cannot calculate how big the array is. The size of the array is not encoded in the pointer, or accessible from the pointer. If it is designed to take a null-terminated string as an argument, it can determine how long that string is; that's what strlen() does, of course. But if it wants to know how much information it can safely copy into the array, it has to be told how big the array is, or make an assumption that there is enough space.
As others have pointed out, the sizeof() operator can be used in the function where the array definition is visible to get the size of the array. But in a function that cannot see the definition of the array you cannot usefully apply the sizeof() operator. If the array was a global variable whose definition (not declaration) was in scope (visible) where calculate() was written - and not, therefore, the parameter to the function - then calculate() could indicate the size.
This is why many, many C functions take a pointer and a length. The absence of the information is why C is somewhat prone to people misusing it and producing 'buffer overflow' bugs, where the code tries to fit a gallon of information into a pint pot.
On statically declared char[] you can use operator sizeof, which will return 64 in this case.
printf("%d", sizeof(s));
On dynamically declared char*, it is not possible to get the size of the allocated memory.
Dynamic arrays are obtained through malloc and friends. All the others are statically declared, and you can use sizeof on them, as long as you use it in the same scope as the array was declared (same function, in your case, for example).
Yes, it's possible if s has a specific character in the end of it's array. For example you could have s[63] = 125 and by knowing that every other character from 0 to 62 won't be 125, you can do a for loop until you find 125 and return the size of the array.
Otherwise, it's not possible, as s in the function parameter is just a pointer to your array, so sizeof(s) inside calculate will only return your machines pointer size and not 64 as someone could expected.
Unfortunately, you cannot determine from a pointer value alone how many elements are in the corresponding array. You either need some sort of sentinel value in the array (like the 0 terminator used for strings), or you need to keep track of it separately.
What you can do is get the number of bytes or elements in an array using the sizeof operator:
char arr[64];
size_t size = sizeof arr; // # of bytes in arr
size_t count = sizeof arr / sizeof *arr; // # of elements in arr
However, this only works if arr is an array type; if you tried to do this in your function
size_t calculate(char *s)
{
return sizeof s;
}
it would return the size in bytes of the pointer value, not of the corresponding array object.
No. char *x or char x[] just creates a pointer to a memory location. A pointer doesn't hold any information about the size of the memory region.
However, char *x = "Hello" occupies 6 bytes (including the terminating null), and strlen(x) would return 5. This relies on the null char at the end of the string, strlen still knows nothing about the underlying buffer. So strlen("Hello\000There") would still be 5.
This is usually done with a macro in C, like:
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
Whether it's a good idea is a totally different question.

Resources