I'm assuming you want a 2D array of char pointers. Your declaration of strNameList is incorrect in both locations in your program. You have:
char strNameList[][2] = { { "Luca","Daniel"} ,{"Vivan","Desmond"},{"Abdul","Justin"}, {"Nina","Marlene"},{"Donny","Kathlene"} };
But char[][N] is declaring a 2D array of chars, not char* Therefore you're being warned by the compiler you're assigning a raft of pointer values to items of type char
Change both your declarations (your variable and your function parameter) to:
const char *strNameList[][2]
which declares an array of unknown length of arrays of two char*, which now matches your initialization lists. Also, the const is added because (a) I'm assuming you are not planning on modify that name list in your function, and (b) writable string literal declarations assigned to char* via initializer is undefined behavior in C, and officially deprecated in C++, so you should not be using it regardless. Likewise, your lookup-name is probably not being modified either, so also declare it const.
Result:
const char * strNameList[][2] = {
{"Luca","Daniel"} ,
{"Vivan","Desmond"},
{"Abdul","Justin"},
{"Nina","Marlene"},
{"Donny","Kathlene"}
};
and in your function:
int find_name(const char * strNameList[][2], const char strLookUp[])
Last but certainly not least, unless you have a crystal ball your find_name() function has no way of knowing with the given information how many names are in the name list being passed. I'd rather you see this now rather than wonder what happened later. you need to either (a) terminate the list with a token-value that find_name() knows about, or (b) pass the number of names in the list to find_name(). To each their own, but I prefer the latter of these:
int find_name(const char * strNameList[][2], size_t nNameListSize, const char strLookUp[])
and invoke it on your caller side by:
find_name(strNameList, sizeof(strNameList)/sizeof(strNameList[0]), strFindName)
Answer from WhozCraig on Stack OverflowI'm assuming you want a 2D array of char pointers. Your declaration of strNameList is incorrect in both locations in your program. You have:
char strNameList[][2] = { { "Luca","Daniel"} ,{"Vivan","Desmond"},{"Abdul","Justin"}, {"Nina","Marlene"},{"Donny","Kathlene"} };
But char[][N] is declaring a 2D array of chars, not char* Therefore you're being warned by the compiler you're assigning a raft of pointer values to items of type char
Change both your declarations (your variable and your function parameter) to:
const char *strNameList[][2]
which declares an array of unknown length of arrays of two char*, which now matches your initialization lists. Also, the const is added because (a) I'm assuming you are not planning on modify that name list in your function, and (b) writable string literal declarations assigned to char* via initializer is undefined behavior in C, and officially deprecated in C++, so you should not be using it regardless. Likewise, your lookup-name is probably not being modified either, so also declare it const.
Result:
const char * strNameList[][2] = {
{"Luca","Daniel"} ,
{"Vivan","Desmond"},
{"Abdul","Justin"},
{"Nina","Marlene"},
{"Donny","Kathlene"}
};
and in your function:
int find_name(const char * strNameList[][2], const char strLookUp[])
Last but certainly not least, unless you have a crystal ball your find_name() function has no way of knowing with the given information how many names are in the name list being passed. I'd rather you see this now rather than wonder what happened later. you need to either (a) terminate the list with a token-value that find_name() knows about, or (b) pass the number of names in the list to find_name(). To each their own, but I prefer the latter of these:
int find_name(const char * strNameList[][2], size_t nNameListSize, const char strLookUp[])
and invoke it on your caller side by:
find_name(strNameList, sizeof(strNameList)/sizeof(strNameList[0]), strFindName)
Do it this way:
#define STOPPER_NAMELIST NULL
char * strNameList[][2] = {
{ "Luca","Daniel"},
{"Vivan","Desmond"},
{"Abdul","Justin"},
{"Nina","Marlene"},
{"Donny","Kathlene"}
{STOPPER_NAMELIST, STOPPER_NAMELIST}
};
size_t sizeNameList(const char * strNameList[][2])
{
size_t size = 0;
while ((strNameList[size][0] != STOPPER_NAMELIST) &&
(strNameList[size][0] != STOPPER_NAMELIST))
++ size;
return size;
}
int find_name(char * strNameList[][2], char strLookUp[])
{
size_t size = sizeNameList(strNameList);
...
}
...
nSearch = find_name(strNameList, strFindName);
This approach uses an open array ([]) of char * arrays with 2 entries.
Update:
You could add a stopper element to the array carring the names, then there is no need to pass around the array's size along with array itself, as the size could alway be determined by scanning the array members until the stopper is found.
Videos
I know at all arrays in C are essentially pointer to the first element of an array
Not quite. Arrays and pointers are two different things entirely. Except when it is the operand of the sizeof, _Alignof, or unary & operator, or is a string literal being used to initialize an array in a declaration, an expression of type "N-element array of T" will be converted to an expression of type "pointer to T" and its value will be the address of the first element in the array.
Given the declaration
int a[10];
the object that a designates is always and forever a 10-element array of int; however, the expression a may be treated as a pointer to the first element.
If you know your strings will never be more than 19 characters long (20 elements including the terminator), but don't know the number of strings ahead of time, you can do something like this:
char (*mens_names)[20];
char (*womens_names)[20];
...
mens_names = malloc(number_of_couples * sizeof *mens_names);
womens_names = malloc(number_of_couples * sizeof *womens_names);
...
fscanf(input_file, "%s", mens_names[i]);
...
free(mens_names);
free(womens_names);
In this case, we've declared mens_names and womens_names as pointers to 20-element arrays of char (the parentheses matter). Thus, sizeof *mens_names is equivalent to sizeof (char [20]).
You would access each individual character as you would with a regular 2-d array:
char x = mens_names[i][j];
mens_names[i] implicitly dereferences the mens_names pointer (remember that the expression a[i] is interpreted as *(a + i)).
This method has a couple of advantages over KBart's method. First, all the memory is allocated contiguously as a single chunk, which may matter if caching becomes an issue. Secondly, you only need one malloc and one free for each array. Of course, this assumes that the maximum size of each name array is a) fixed and b) known at compile time.
If you won't know the size of the name until runtime, and you're using a C99 compiler or a C2011 compiler that supports variable-length arrays, you can do something like this:
size_t name_len, number_of_couples;
// get name_len from the user or input file
// get number_of_couples
char (*mens_names)[name_len+1] = malloc(number_of_couples * sizeof *mens_names);
...
If you won't know the size of the name until runtime, and you're using a compiler that doesn't support VLAs, then you'll need to use KBart's method.
If you wanted to get really fancy, you could use a single 3-dimensional array instead of two 2-dimensional arrays:
#define MENS_NAMES 0
#define WOMENS_NAMES 1
...
char (*all_names)[2][20] = malloc(number_of_couples * sizeof *all_names);
...
fscanf(input_file, "%s", all_names[i][MENS_NAMES]);
...
free(all_names);
You are talking about 2D array, but initializing it only as a one dimensional array. The correct initialization of 2D array (matrix) is as follows:
static char** allocate_matrix(int nrows, int ncols)
{
int i;
char **matrix;
/* allocate array of pointers */
matrix = malloc( nrows*sizeof(char*));
if(matrix==NULL)
return NULL; /* Allocation failed */
/* Allocate column for each name */
for(i = 0; i < nrows; i++)
matrix[i] = malloc( ncols*sizeof(char));
if(matrix[i-1] == NULL)
return NULL; /* Allocation failed */
return matrix;
}
In your main():
<...>
mens_names = allocate_matrix(number_of_couples, 19);
womens_names = allocate_matrix(number_of_couples, 19);
<...>
/* Of course, do not forget to free memory once you are done */
First you need to create an array of strings.
char arrayOfWords[NUMBER_OF_WORDS][MAX_SIZE_OF_WORD];
Then, you need to enter the string into the array
int i;
for (i=0; i<NUMBER_OF_WORDS; i++) {
scanf ("%s" , arrayOfWords[i]);
}
Finally in oreder to print them use
for (i=0; i<NUMBER_OF_WORDS; i++) {
printf ("%s" , arrayOfWords[i]);
}
char * str[NumberOfWords];
str[0] = malloc(sizeof(char) * lengthOfWord + 1); //Add 1 for null byte;
memcpy(str[0], "myliteral\0");
//Initialize more;
for(int i = 0; i < NumberOfWords; i++){
scanf("%s", str[i]);
}
Create an array of string pointers. Each element in your 2D array will then point to the string, rather than holding the string itself
quick and dirty example :) (Should realy init the elements)
#include <stdio.h>
int main(void)
{
char * strs[1][3]; // Define an array of character pointers 1x3
char *a = "string 1";
char *b = "string 2";
char *c = "string 3";
strs[0][0] = a;
strs[0][1] = b;
strs[0][2] = c;
printf("String in 0 1 is : %s\n", strs[0][1]);
printf("String in 0 0 is : %s\n", strs[0][0]);
printf("String in 0 2 is : %s\n", strs[0][2]);
return 0;
}
A two dimensional array of strings in c can be represented by a three dimensional array of character pointers.
// allocate space for the "string" pointers
int size = height + (height * length);
char*** a = malloc (size * sizeof (char*));
//setup the array
for (i= 0; i< height; i++)
{
a [i] = a + (height + (length * i));
}
Now a [x][y] resolves to char *. You can assign string literals to it or allocate an array of chars to hold dynamic data.
If you actually know the size of the array before running the program, you don't need to dinamically allocate the memory with malloc, you could create a 2D static array. In your case, as it is a 2D array of strings, it could be declared as char * array[ROWS][COLS], and then you could asign a string to a specific element this way: array[nrow][ncol]="Your String".
C, unlike Java, actually has a concept of multidimensional arrays; so unless there's a specific reason you want a char * * *, you might prefer to write:
char (*people)[COLS][NAME] = malloc(ROWS * sizeof(*people));
which sets people to be a pointer to the first of ROWS dynamically-allocated two-dimensional character arrays.
Due to pointer "decay", where an expression of array type will double as a pointer to the first element of the array, you can use people very much as if it were a char * * *; for example, people[3][4] will point to the string in row 3, column 4. The only restriction is that you can't write something like people[3][4] = ... to suddenly change what string to point to. But it sounds like you don't want to do that, anyway?
Note: the above is assuming that you are intentionally using dynamic memory allocation. However, I do recommend you consider Sizigia's suggestion to use static memory, which is the same sort of storage as is used for global variables. If you write something like
static char people[ROWS][COLS][NAME];
then the memory will be allocated just once, at the start of the program, and reused by all calls to the function that declares it.
My code collects strings with fgets from the user.
The user fills 5 strings that can be max 100 characters long.
How can I check how long the strings given by the user are?
Within a multidimensional string just like this one: string[5][100]
string[5][how long is the string here?]