Get length of string array of unknown length - c

I have this function:
int setIncludes(char *includes[]);
I don't know how many values includes will take. It may take includes[5], it may take includes[500]. So what function could I use to get the length of includes?

There is none. That's because arrays will decay to a pointer to the first element when passing to a function.
You have to either pass the length yourself or use something in the array itself to indicate the size.
First, the "pass the length" option. Call your function with something like:
int setIncludes (char *includes[], size_t count) {
// Length is count.
}
:
char *arr[] = {"Hello,", "my", "name", "is", "Pax."};
setIncludes (arr, sizeof (arr) / sizeof (*arr));
setIncludes (arr, 2); // if you don't want to process them all.
A sentinel method uses a special value at the end to indicate no more elements (similar to the \0 at the end of a C char array to indicate a string) and would be something like this:
int setIncludes (char *includes[]) {
size_t count = 0;
while (includes[count] != NULL) count++;
// Length is count.
}
:
char *arr[] = {"Hello,", "my", "name", "is", "Pax.", NULL};
setIncludes (arr);
Another method I've seen used (mostly for integral arrays) is to use the first item as a length (similar to Rexx stem variables):
int setIncludes (int includes[]) {
// Length is includes[0].
// Only process includes[1] thru includes[includes[0]-1].
}
:
int arr[] = {4,11,22,33,44};
setIncludes (arr);

You have two options:
You can include a second parameter, similar to:
int main(int argc, char**argv)
... or you can double-null terminate the list:
char* items[] = { "one", "two", "three", NULL }

There is no way to simply determine the size of an arbitrary array like this in C. It requires runtime information that is not provided in a standard way.
The best way to support this is to take in the length of the array in the function as another parameter.

You have to know the size either way. One way would be to pass the size as a second parameter. Another way is to agree with the caller the he/she should include a null pointer as the last element in the passed array of pointers.

Though it is a very old thread, but as a matter of fact you can determine the length of an arbitrary string array in C using Glib. See the documentation below:
https://developer.gnome.org/glib/2.34/glib-String-Utility-Functions.html#g-strv-length
Provided, it must be null terminated array of string.

And what about strlen() function?
char *text= "Hello Word";
int n= strlen(text);
OR
int n= (int)strlen(text);

Related

Best way to initialize an array of strings to pass it to a function

I need to intialize an empty array of strings with fixed size ( 3 by 100 for example), pass it to a function to fill it with data and perform things like strcpy(), strcmp(), memset() on it. After the function is terminated I need to be able to read the data from my main().
What I tried so far:
char arrayofstrings[3][100] = {0};
char (*pointer)[3][100] = &arrayofstrings;
function(pointer);
Initalizing an (empty?) array of strings and initializing a pointer on the first element.
int function (char (*pointer)[3][100])
{
strcpy((*pointer)[i], somepointertostring);
strcmp((*pointer)[i], somepointertostring)
memset((*pointer)[i], 0, strlen((*pointer)[i]));
}
Is this a good way to do it? Is there an easier way to do it? Whats up with the brackets around the pointer?
C string functions expect a buffer to be null-terminated. Your arrayofstrings allocation happens on the stack. Depending on your compiler it might be initialized to all zeros or might contain garbage.
The simplest way in your case to make sure string functions won't overrun your buffers is to set the first character of each to 0 (null)
arrayofstrings[0][0] = 0x00;
arrayofstrings[1][0] = 0x00;
arrayofstrings[2][0] = 0x00;
This will give you 3, 100-char buffers that contain a valid empty "string". Note that you can only store 99 "characters" because the last character must be 0x00 (null-terminator).
char (*pointer)[3][100] = &arrayofstrings;
This is unnecessary.
Something to keep in mind about arrays in C is that the [] index is really only there to make things easier for the human programmer. Any array definition is simply a pointer to memory. The values inside the [][]...[] indexes and the type are used by the compiler to allocate the right amount of memory on the stack and do some simple math to come up with the right memory address for the element you want to access.
char arrayofstrings[3][100];
This will allocate sizeof(char)*3*100 bytes on the stack and give you a char* called 'arrayofstrings'. There's nothing special about the char* itself. It would be the same pointer if you had char arrayofstrings[300] or char arrayofstrings[3][10][10] or even long arrayofstrings[75] (char is 1 byte, long is 4 bytes).
Because you declared it as a multidimensional array with [a][b], when you ask for arrayofstrings[x][y], the compiler will calculate ((x*b)+y)*sizeof(type) and add it to the arrayofstrings pointer to get the address of the value you want. But because it's just a pointer, you can treat it like any other pointer and pass it around or cast it to other types of pointer or do pointer math with it.
You don't need the extra level of indirection.
An array, when passed to a function, is converted to a pointer to its first member. So if you declare the function like this:
int function(char (*pointer)[100])
Or equivalently:
int function(char pointer[][100])
Or:
int function(char pointer[3][100])
You can pass the array directly to the function:
function(arrayofstrings);
Then the body could look something like this:
strcpy(pointer[0], "some string");
strcpy(pointer[1], "some other string");
strcpy(pointer[2], "yet another string");
Best way to initialize an array of strings ...
char arrayofstrings[3][100] = {0}; is fine to initialize an array of strings.
In C, initialization is done only at object definition, like above.
Later code like strcpy(), assigns data to the array.
Best way to ... pass it to a function
When the C compiler supports variable length arrays, use function(size_t n, size_t sz, char a[n][sz]).
Add error checks.
Use size_t for array sizing and indexing.
#define somepointertostring "Hello World"
int function(size_t n, size_t sz, char arrayofstrings[n][sz]) {
if (sz <= strlen(somepointertostring)) {
return 1;
}
for (size_t i = 0; i < n; i++) {
strcpy(arrayofstrings[i], somepointertostring);
if (strcmp(arrayofstrings[i], somepointertostring)) {
return 1;
}
// Drop this it see something interesting in `foo()`
memset(arrayofstrings[i], 0, strlen(arrayofstrings[i]));
}
return 0;
}
void foo(void) {
char arrayofstrings[3][100] = {0};
size_t n = sizeof arrayofstrings / sizeof arrayofstrings[0];
size_t sz = sizeof arrayofstrings[0];
if (function(n, sz, arrayofstrings)) {
puts("Fail");
} else {
puts("Success");
puts(arrayofstrings[0]);
}
}
Initalizing an (empty?) array of strings and initializing a pointer on the first element.
The type of &arrayofstrings is char (*)[3][100] i.e. pointer to an object which is a 2D array of char type with dimension 3 x 100. So, this initialisation
char (*pointer)[3][100] = &arrayofstrings;
is not initialisation of pointer with first element of arrayofstrings array but pointer will point to whole 2D array arrayofstrings. That why, when accessing the elements using pointer you need bracket around it -
`(*pointer)[0]` -> first string
`(*pointer)[1]` -> second string and so on..
Is this a good way to do it? Is there an easier way to do it?
If you want pointer to first element of array arrayofstrings then you can do
char (*p)[100] = &arrayofstrings[0];
Or
char (*p)[100] = arrayofstrings;
both &arrayofstrings[0] and arrayofstrings are equivalent1).
Pass it to a function and access the array:
function() function signature should be -
int function (char (*pointer)[100])
// if you want the function should be aware of number of rows, add a parameter for it -
// int function (char (*pointer)[100], int rows)
this is equivalent to
int function (char pointer[][100])
and call it in from main() function like this -
function (p);
In the function() function you can access array as p[0], p[1] ...:
Sample program for demonstration:
#include <stdio.h>
#include <string.h>
#define ROW 3
#define COL 100
void function (char (*p)[COL]) {
strcpy (p[0], "string one");
strcpy (p[1], "string two");
strcpy (p[2], "string three");
}
int main(void) {
char arrayofstrings[ROW][COL] = {0};
char (*pointer)[COL] = &arrayofstrings[0];
function (pointer);
for (size_t i = 0; i < ROW; ++i) {
printf ("%s\n", arrayofstrings[i]);
}
return 0;
}
When you access an array, it is converted to a pointer to first element (there are few exceptions to this rule).

Getting element from dynamic two dimensional array

Currently, I'm studying c programming language and on the test was a task - Write a function that has two strings as a parameter and need to find and print all unique characters that are present in both strings:
the 'main' function for the test is (and I suspect that all tests are generated using similar function):
int main(void)
{
char *str0 = {"example string", "excelent string"};
solution(2, str0);
return (0);
}
Function should be declared as follow void solution(int size, char **strs);
I don't see any problem to write algorithm. The question is - how to get a second string from **strs?
I tried different approaches just to print second element:
printf("%s", strs[1]);
*strs++;
printf("%s", *strs);
But nothing works.
I guess, that mistake in main function:
Should be something like this: char *str0[] = {"example string", "excelent string"};
Could somebody help - is this mistake in the test and with a provided function to solve this task is impossible or is exist any way to get second string from array?
char *str0 = {"example string", "excelent string"}; is incorrect: it declares a character array, but attempts to define it using array of size 2 containing elements of the type 'character array'. It should be declared as an array of arrays, for example using a fixed size of 2. This works:
#include <stdio.h>
void solution(int size, char **strs)
{
printf("%s\n", strs[0]);
printf("%s\n", strs[1]);
}
int main(void)
{
char *str0[2] = {"example string", "excelent string"};
solution(2, str0);
return 0;
}
I do not consider it a good practice to mix the * and [] pointer notations, but this follows the specifications of the task best, given the definition of the string literal array of size 2.
Continuing from the comment, your brace-initializer {"example string", "excelent string"} is the initializer for an array. (in this case) Specifically in your case, it is the initializer for an array of pointers to String-Literals.
You declare your array and determine the number of elements by:
char *strings[] = { "one", "two" };
size_t nelem = sizeof strings / sizeof *strings;
Once you have your array of pointers, you can pass the array as type char ** because the first level of indirection is converted to a pointer on access. See C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)
Your function declaration can then be:
void solution (size_t size, char **strs);
and you would invoke your function like:
solution (nelem, strings);
A short example would be:
#include <stdio.h>
void solution (size_t size, char **strs)
{
for (size_t i = 0; i < size; i++)
puts (strs[i]);
}
int main (void) {
char *strings[] = { "one", "two" };
size_t nelem = sizeof strings / sizeof *strings;
solution (nelem, strings);
return 0;
}
(note: while nelem and size can be type int, it is more properly size_t -- though the compiler will allow the result of the division to be assigned to int without warning)
Example Use/Output
Which will iterate over the strings outputting each from the function:
$ ./bin/array_ptrs_init
one
two
Determining Unique Characters
Now for the rest of your task outputting unique characters from both strings, you can include string.h and iterate over the characters in one string calling strchr() to determine if the character is present in the second string. If it is, continue; and get the next char to check, or it it is unique (e.g. strchr() returns NULL), output the character as unique. (this part I leave to you)
char* is the array of chars, that is, char * is string.
And equally, for some type of T, T* is considered as the array of T.
So, you assume that char * is a new type such as
typedef char * STRING;
Then you can understand easily.
#include <stdio.h>
typedef const char * STRING;
void solution(int size, STRING * strings)
{
int i = 0;
for (i = 0; i < size; i++)
{
printf("%s\n", strings[i]);
}
}
int main()
{
STRING strings[2] = { "example string", "excelent string" };
solution(2, strings);
return 0;
}

Receive an array of strings from a function and find out it's length [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have this code:
char** SplitToWords(char* str);
int main()
{
char** wordarr;
char str[] = "This is a sentence";
wordarr = SplitToWords(str);
return 0;
}
After the main comes the function implementation.
I am not sure the following does what I want it to do (i.e. receive an array of strings from a function):
wordarr = SplitToWords(str);
I somehow managed to convince the compiler that it's ok, but I assume it just does something else.
If it does, how do I find out the length of the array (the number of strings in it).
Thanks
I'll try to quickly visit all aspects you might not yet fully understand:
A string in C is described as a contiguous sequence of chars, ending with a char of value 0 (as a literal: '\0'). It is not a first class object, therefore hasn't its own type. So what you use to hold a string is an array of char. Therefore, taking your question by the word, "receive an array of strings from a function" is not possible.
An array is a contiguous sequence of objects of the same type. In C, the identifier of an array doesn't have a value itself; when it's evaluated, it decays as a pointer to the array's first element instead. This is especially important when passing arrays to functions or returning them from functions -- you can't actually pass the array, you always pass a pointer
e.g. you could write:
char x[] = "foo"; // initialize a char array from a string literal
char *xp = x; // here, x evaluates as a pointer to the first element of the array
You already use pointer types for your function's argument and return value, I just think it's quite important to understand what happens entirely.
You write char** SplitToWords(char* str); and ask whether this returns an "array of strings" -- well, sort of, as you should understand after reading 1. and 2. -- What it does is returning a pointer to char *. This pointer could be a pointer to the first element of an array. So in this case, it would return a pointer to an array of char * pointers. Each of these pointers could itself be a pointer to an array of chars, therefore point to a string. But what's very important is to understand you never return an array, you always return a pointer to it. It's so important because:
You might get the idea to do something like this:
char** SplitToWords(char* str)
{
char *words[16];
// code to fill `words` with pointers to the actual words
return words; // WRONG!
}
Here, because you're not returning the array words but a pointer to it (see point 2), you return a pointer to an object that no longer exists. words is in the scope of your function and has automatic storage duration, that means it only lives as long as the execution is inside of the function. One solution would be to declare words with the static storage class specifier. This way, it lives for the entire execution time of the program. But be aware that this also means there's only a single instance ever, it's always the same object. This will be a major headache for threaded programs, for example. The other way around is to dynamically allocate words using malloc(). But then, the caller of the function must free() it later.
As for your second question, how to let the caller know the number of words -- it's in the comments already, but just for completeness, a typical approach to solve this is to append another entry that is a NULL pointer. So the caller can iterate over the pointers until it finds NULL.
Regarding your comment, of course you can create the array outside the function and pass a pointer to the function, so the function only fills it. This is a common idiom in C (e.g. think about fgets(), which takes a pointer to the char array that's filled with a string by the function).
Functions working this way will need an additional size_t parameter, so they know the size of the array they should fill through the pointer, otherwise you'd have the risk of buffer overflows (this is why gets() was finally removed from the C standard). If you decide that the caller provides the storage, your function should have this prototype:
// returns the number of words found, up to `nwords`
size_t SplitToTwords(char **words, size_t nwords, char *str);
It should be called e.g. like this:
char *words[16];
size_t nwords = SplitToWords(words, 16, "the quick brown fox"); // returns 4
Remember that the strings holding the words themselves need storage as well. You can either manipulate the bytes in str to insert a '\0' after each word, overwriting the first whitespace character (this is what strtok() does) or you can copy the words to new strings, but then you would have to malloc() each of them again and the caller has to free() them later.
Yes, you could solve it by using a function with return value char **. However, there's no way to find out how many words there are afterwards.
You can solve this by allocating one more element for the return pointer and set it to NULL. Then you can get the number of words with this code:
wordarr = SplitToWords(str);
char **ptr=wordarr;
int noWords=0;
while(!*(ptr+noWords))
noWords++;
But if you want to return multiple data in C, you either need to define a return struct or using return arguments. In this case, it could look like this for the first option:
typedef struct wordList {
char **wordarr;
int noWords;
}
wordList SplitToWords(char* str);
And the second:
char** SplitToWords(char* str, int *noWords);
or
void SplitToWords(char* str, char*** wordarr, int *noWords);
Note that there's three *. That's because we want it to be a pointer to char **
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXSTRINGS 5000
int main(int argc, char *argv[]) {
char *stringTable[MAXSTRINGS];
char sentence[] = "This is a sentence";
char *token = NULL;
int i = 0;
while ((token = strtok(token == NULL ? sentence : NULL, " ")) != NULL)
{
printf("%s\n\r", token);
stringTable[i] = (char *)malloc(strlen(token) + 1); //have no "plain" C compiler - VS C++ used so cast needed :)
strcpy(stringTable[i++], token);
}
stringTable[i] = NULL; // if you need to iterate through later
printf("%d tokens found\n\r", i);
for (int y = 0; y < i; y++)
free(stringTable[y]);
}

How do I receive a char array in a C function?

I wish to split a "string" by the character ','.
The string holds a GPS NMEA encoded string, but that is of no matter.
My problem is that sometimes the parameter from the function that processes this char array is empty... Like nothing is in the array.
How should I correctly pass a "char string[]" to a function so that I may operate on a that parameter as I sent it(as a char array, not a char pointer to an array).
I also need to specify that I'm using mikroC for PIC.
Here is my code as of right now:
char* GPS_sateliti;
char CsatInView[] =
"$GPGSV,3,2,11,14,25,170,00,16,57,208,39,18,67,296,40,19,40,246,00*74";
GPS_sateliti = GrupeazaDupaVirgule(CsatInView, 2);
char* GrupeazaDupaVirgule( char deGasit[],int nrVirgule ){
int cVirgule = 1;
char* pch = strtok (deGasit,",");
while (pch != 0)
{
pch = strtok (0, ",");
cVirgule++;
if(nrVirgule == cVirgule){
break;
}
}
return pch;
}
The function that operates on the char array received as a parameter in debug mode, before entering the function the char array is fine, after entering it, it seems to be empty
It may be that I should receive a pointer to an array of chars??
Any sort of advice is welcome.
Thank you
How should I correctly pass a "char string[]" to a function so that I may operate on a that parameter as I sent it(as a char array, not a char pointer to an array).
You can't. A function parameter of an array type always decays as the corresponding pointer type.
There are two idiomatic solutions to this.
1. a sentinel:
The last value in the array is a special value that marks the end. This is done in C with strings. They always end with a \0 character, that is guaranteed not to occur inside the string. The function can search for that character to know where the data ends.
(Note: with this info I have to add I'm not sure what your problem is. If you pass an "empty string", as literally "", the \0 will be there, so you shouldn't have a problem)
2. explicitly passing the size:
instead of just
void foo(int bar[]);
you define a function
void foo(size_t barSize, int bar[]);
The caller knows the size of the array, so it can just pass it along.
With a pointer :
char* arr;
yourFunction(arr);
If you wish to initialize it before :
char* arr = malloc(51 * sizeof(char)); // Allocate a memory place of 50 because strings are null terminated in C
yourFunction(arr);
An other way to allocate memory to an array :
char* arr = calloc(50, sizeof(char)); // Allocate 50 memory place which size if the size of a char
With a string :
char arr[50];
char* ptr = arr;
yourFunction(ptr);
You have to know that it is impossible in C to know the size of an array when using pointer. The only thing you can do is to parse the size of the string as a parameter :
size_t size = 50;
char arr[size];
char* ptr = arr;
yourFunction(ptr, size);
If you wish to understand in detail how pointer works and how to iterate them, may be this post can help you. I think it is very interesting.
Globally, you iterate through an array via a pointer like this :
for ( int i = 0; i < size; i++)
printf("Current pointed value in the array : %c\n", ptr[i]); // or arr[i]
I guess you understand why giving the size of a pointed array as a parameter is important. Sometimes you can avoid using this parameter like this :
for ( int i = 0; i != '\0'; i++) // Because strings are null-terminated in C.
// Do something

C string array function How call the function?

What Parameters should I give this function? I think it needs a string array but I don't know the exact syntax.
void write_file(char *result[], int len)
{
..
}
char result[10];
write_file(&(result[0]), 10);
or
char result[10];
write_file(result, 10);
which is the same, as array identifier is simply the address of its first element
Infact it does not need string array. In C, you can not send array to a function and also you can not return an array from a function. Solution? You can send "the" array's starting point and it's length. Then the receiver side can understand "the" array. About your question, you must send start position of the array as first argument and length of the array as the second argument.
char *result[] means an array of pointers to char. However the question is what is the meaning of the parameter len?
Normally with a function named something like write_file() the function would write a character string to an output and the len parameter would be the number of characters to write out.
To use this function as the function looks would mean something like:
char *myStrings[] = {
"string 0",
"string 1"
};
write_file (myStrings, 0); // passing zero as len as unsure what it is.
Or something like:
char *myStrings[20]; // array of pointers to chars
int iLoop;
for (iLoop = 0; iLoop < 20; iLoop++) {
myStrings[iLoop] = malloc(1000); // allocate a large buffer for each string
read_string (myStrings[iLoop], 1000); // some made up function to read a string
}
write_file (myStrings, 20);
What I suspect is that the function should actually be void write_file(char *result, int len) or it should be void write_file(char result[], int len) so that rather than accepting an array of pointers to char arrays (how strings are normally used in C) it should be accepting a pointer to a char array.
So the idea of write_file() would be to write a single string to a file rather than several strings.

Resources