C - what does while(*Table[i]) mean/do? - c

I need to add a string to an array and need some help figuring out what this means. Here is what I have:
#include <stdio.h>
#include <stdlib.h>
int insert(char *word, char *Table[], int n)
{
//*word is the string to be added, *Table[] is the array, n is
//the return value, which is the number of words in the array after adding *word
int i = 0;
while(*Table[i])
{
if strcmp(*Table[i], *word) == 0)
{
return n;
break;
}
}
}
I wrote this awhile ago and am just now revisiting it. I have no idea what while *Table[i] means, therefore I have no idea what the code that follows means. Also, this code is incomplete so don't bother telling me it won't add the string.

The * operator dereferences a pointer, and so does the [i].
Since Table is declared as char *Table[] this is the same as char ** in that it is a pointer to a pointer type (like a 2 dimensional array).
In this case it is apparent from the usage that Table is an array of strings (a string being an array of char (hence the array of arrays type)).
So Table[i] is a pointer to the i-th string in the array of strings, and then the * dereferences this again. What the author is doing here is looking for a NULL (zero) which follows the array of strings, which is clearly the method of determining the end of the array.

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).

Why does memcpy return string is never equal to the same string present in an array?

I am using a simple string matching and searching.
Why does *arr is never equal to point though their values(why does I) are same? I am confused what is the cause of this?Is it related to strings or is there any other reason? Any help would be appreciated. I am sorry if the question is not clear.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int search(char ** arr, int size, char *point);
int main()
{
char *array[5]={0};
char original[50];
char toSearch[50];
char *point;
int size=5, searchIndex,i;
/* Copy a string into the original array */
strcpy(original, "why this is not equal");
/* Copy the first 10 characters of the original array into the newcopy array*/
point = memcpy(toSearch, original, 10);
/*string to search*/
array[2]="why this i";
searchIndex = search(array, size, point);
if(searchIndex == -1)
{
printf("%s does not exists in array \n", point);
} else
printf("%s is found at %d position.", toSearch, searchIndex + 1);
return 0;
}
int search(char ** arr, int size, char *point)
{
int index = 0;
// Pointer to last array element arr[size - 1]
char ** arrEnd = (arr + size - 1);
/* Why *arr!=point is never false,
even when both are giving out same values (why this I)?
*/
while(arr <= arrEnd && *arr!=point)
{
printf("%s == %s", *arr,point);
arr++;
index++;
}
if(arr <= arrEnd)
{
printf("%s after found \n",*arr);
return index;
}
return -1;
}
Output:
(null) == why this i
(null) == why this i
why this i == why this i
(null) == why this i
(null) == why this i
why this i does not exists in array
Thank You
I assume that you are asking why the address of the variable of type array-of-char is not identical to the address of the string literal you copy to it.
This is a tricky question, because, excuse me for saying so, it is unclear what could make you expect the address of any variable be different after copying something to it.
Consider the example of not one but two different arrays of char being filled with the same string literal.
char toSearch1[50];
char toSearch2[50];
char *point1;
char *point2;
point1 = memcpy(toSearch1, original, 10);
point2 = memcpy(toSearch2, original, 10);
/* or, depending on what to you is more convincingly copying the same literal */
point2 = memcpy(toSearch2, toSearch1, 10);
Afterwards, the two arrays are still two different variables of type array-of-char and memcpy returns the address of the destination, i.e. of the two different arrays.
Please imagine how those two arrays could have identical address now.
If you follow up with
strcpy(original1, "is this in one or both arrays?");
Would you then expect the two arrays to have different addresses again?
If this does not answer your question, you have a fundamentally different understanding of pointers and addresses of variables than most programmers and I recommend to revise it by finding a tutorial on pointers and addresses.
(Note, for this explanation of what you are asking about I am skipping the discussion of checking lengths in relation to array sizes, using safer versions of string copying, memcpy not correctly null terminating copied strings. All of that is however important for making reliable code, as e.g. Lundin correctly reminds us.)
In C, string are just null terminated char arrays. As ordinary arrays, they decay to pointers when directly used in expression. So when you write str1 == str2 you are just comparing the pointers to their first element.
And two pointers are only equal if they point to the very same object (same address). That is the reason why standard library offers strcmp to compare null terminated strings, and memcmp to compare arbitrary buffers of known size.

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 to find the number of elements in char** array?

I have an string array in the form of char**
I am struggling to find the length of that array:
typedef struct _stringArray
{
int (*Length)(char**);
char** (*Push)(char**, char*);
char** (*Pop)(char**, char*);
}StringArray;
StringArray* StringArray_Constructor(void)
{
StringArray* stringArray = (StringArray *)malloc(sizeof(StringArray));
stringArray->Push = StringArray_Push;
stringArray->Pop = StringArray_Pop;
}
char** StringArray_Push(char** array, char* string)
{
int size = 0; //how to find how many elements in the array object???
array = realoc(array, (sizeof(char *) * (size + 1));
array[size] = string;
return array;
}
Any help would be greatly appreciated!
Thanks.
With C, you will have to keep track of this yourself.
There's no way you can infere the lenght of the array, the only way you could do it is doing it dynamically. You have an array of strings (char**), so you have the pointer to the first character of the first element of the array. We all know that, in C, all strings must ed with '\0', so you can "scan" for the strings of the array taking this pointer and saving it, then increment it until you get a '\0'. The next pointer is the first character of the next string and so on.
But this have a huge flaw: memory is not as linear as it appears. What I'm saying is that your first string can be entirely allocated at, e.g., address 0x0010101A, and the next at 0xF0FF0001, so or you hae a huge string #0x0010101A or there is a bunch of data beetween them and you do not know if they are part of the string or not.
And that's why you need to maintain a counter of how many strings you have. :)
PS: and as this number is always greater than zero, you should use unsigned int to type it.
You have a few options:
1) Pass a size parameter around which indicates the current size of your char **array.
2) Declare a structure which combines char **array with int array_size (really the same as #1).
3) If your array will always contain valid pointers (i.e. non-NULL) then create an extra element at the end which is always set to NULL. This acts as an array terminator, you can scan char **array looking for this terminating element:
int size;
for (size = 0; array[size] != NULL; size++);
// 'size' is number of valid entries in 'array'.

Problem with processing individual strings stored in an array of pointers to multiple strings in C

An array of pointers to strings is provided as the input. The task is to reverse each string stored in the input array of pointers. I've made a function called reverseString() which reverses the string passed to it. This functions works correctly as far as i know.
The strings stored/referenced in the input array of pointers are sent one by one to the reverseString() function. But the code hangs at some point in the reverseString() function when the values of the passed string are swapped using a temp variable. I can't figure out why the code is hanging while swapping values. Please help me with this.
The code is as follows:
#include <stdio.h>
void reverseString(char*);
int main()
{ char *s[] = {"abcde", "12345", "65gb"};
int i=0;
for(i=0; i< (sizeof(s)/sizeof(s[0]) ); i++ )
{ reverseString(s[i]);
printf("\n%s\n", s[i]);
}
getch();
return 0;
}//end main
void reverseString(char *x)
{ int len = strlen(x)-1;
int i=0;
char temp;
while(i <= len-i)
{ temp = x[i];
x[i] = x[len-i];
x[len-i] = temp;
i++;
}
}//end reverseString
You are trying to change string literals.
String literals are usually not modifiable, and really should be declared as const.
const char *s[] = {"abcde", "12345", "65gb"};
/* pointers to string literals */
If you want to make an array of modifiable strings, try this:
char s[][24] = {"abcde", "12345", "65gb"};
/* non-readonly array initialized from string literals */
The compiler will automatically determine you need 3 strings, but it can't determine how long each needs to be. I've made them 24 bytes long.
The strings ("abcde" etc) could be stored in readonly memory. Anything is possible when you try to modify those strings, therefore. The pointers to the strings are modifiable; it is just the strings themselves that are not.
You should include <string.h> to obtain the declaration of strlen(3), and another header to obtain the function getch() - it is not in <stdio.h> on my MacOS X system (so I deleted the call; it is probably declared in either <stdio.h> or <conio.h> on Windows).
Hope this helps you! what i am doing here is that i am going to the address of the last character in the string then printing them all by decreasing the pointer by 1 unit (for character its 2 bytes(please check)).
//program to reverse the strings in an array of pointers
#include<stdio.h>
#include<string.h>
int main()
{
char *str[] = {
"to err is human....",
"But to really mess things up...",
"One needs to know C!!"
};
int i=0; //for different strings
char *p; //declaring a pointer whose value i will be setting to the last character in
//the respective string
while(i<3)
{
p=str[i]+strlen(str[i])-1;
while(*p!='\0')
{
printf("%c",*p);
p--;
}
printf("\n");
i++;
}
}

Resources