Can I create an Array of Char pointers in C? - c

I am new to C, and things are different in C than in any other language I've learned. In my homework I want to create an array of chars which point to an array of chars, but rather than make a multidimensional char array, I figure I'd have more control and create char arrays and put each individual one into the indexes of the original char array:
char keywords[10];
keywords[0] = "float";
The above example is to clarify and a simple case. But my question is due to the research I've been doing, and I am confused about something. Normally this would work in other languages, but in C it would be:
char *keyword[10];
keywords[0] = "float";
But when I want to send it through a function, why is this necessary:
void function(char **keyword); //function prototype
Wouldn't just passing the array pointer be enough?

It looks like you're confused by the double stars in
void function(char ** keyword);
The double stars just means that this function expects you to pass a pointer to a pointer to a char. This syntax doesn't include any information about the fact that you are using an array, or that the char is actually the first char of many in a string. It's up to you as the programmer to know what kind of data structure this char ** actually points to.
For example, let's suppose the beginning of your array is stored at address 0x1000. The keyword argument to the function should have a value of 0x1000. If you dereference keyword, you get the first entry in the array, which is a char * that points to the first char in the string "float". If you dereference the char *, you get the char "f".
The (contrived) code for that would look like:
void function(char **keyword)
{
char * first_string = *keyword; // *keyword is equivalent to keyword[0]
char first_char = *first_string; // *first_string is equivalent to first_string[0]
}
There were two pointers in the example above. By adding an offset to the first pointer before dereferencing it, you can access different strings in the array. By adding an offset to the second pointer before dereferencing it, you can access different chars in the string.

char *keyword[10];
keyword is an array 10 of char *. In a value context, it converted to a pointer to a char *.
This conversion is a part of what Chris Torek calls "The Rule":
"As noted elsewhere, C has a very important rule about arrays and pointers. This rule -- The Rule -- says that, in a value context, an object of type ‘array of T’ becomes a value of type ‘pointer to T’, pointing to the first element of that array"
See here for more information: http://web.torek.net/torek/c/pa.html
The C-FAQ also has an entry on this array to pointer conversion:
Question 6.3: So what is meant by the "equivalence of pointers and arrays'' in C?
http://c-faq.com/aryptr/aryptrequiv.html

In C, you can't really pass array to a function. Instead, you pass a pointer to the beginning of the array. Since you have array of char*, the function will get a pointer to char*, which is char**.
If you want, you can write (in the prototype) char *keyword[] instead of char **keyword. The compiler will automatically convert it.
Also, in C you can dereference pointers like arrays, so you loose almost nothing with that "converting to pointer".

If you want to
void function(char **keyword);
Andy, think about that an array is just a pointer(to the beginning of the array), that's why you write:
void function(char **keyword);
Because you have create an array to char pointers.
If it's easier to understand try:
void function(char *keyword[]);
But it's more C standard to use the first one, though if you use a C++ compiler won't really matter.

Here is the answer.
#include<stdio.h>
int main(void)
{
char *CharPtr[3];
char a[4]="abc";
char b[4]="def";
char c[4]="ghi";
CharPtr[0]=a;
CharPtr[1]=b;
CharPtr[2]=c;
printf("\n content of CharPtr[0] =%s",CharPtr[0]);
printf("\n content of CharPtr[1] =%s",CharPtr[1]);
printf("\n content of CharPtr[2] =%s\n",CharPtr[2]);
printf(" \n content of char a[4]=%s",a);
printf(" \n content of char b[4]=%s",b);
printf(" \n content of char c[4]=%s\n",c);
}

char *keywords[10] is an array of character pointers. So keywords[0], keywords[1].. and so on will have the addresses to different character arrays.
In printf you can use %s and keywords[0] to print the entire character array whose address(i.e. address of the first byte in the array) is stored at keywords[0].
While passing to a function, if you give *keywords, you are referring to the value at(address stored at keywords[0]) which is again an address. So, to get the value instead of address, you can add another *... Hope that clarifies a bit..

I am assuming that you are assigning your first string:
"float"
to the first index position of keyword[0]
char keyword[0] = "float";
which is the first index position of the array:
char keyword[10];
If the previous is the case, then in a sense, you are essentially creating a data structure that holds a data structure. The array of any type is the 'smallest' data structure of that type in C. Considering that in your example you are creating a character array, then you are actually utilizing the smallest data type (char=1bit) at each index position of the smallest built in data structure (the array).
With that said, if in your example, you are attempting to create an array of arrays; your character array
/* Hold ten characters total */
char keyword[10];
was designed to hold 10 characters. One at each index position (which you probably already know). So after declaring the array titled keyword, you then try to initialize the first index position of the array with another (the second) character array:
/* I believe this is what you had stated */
char keywords[0] = "float";
With the second character array having an index of 5 positions in size.
In order to achieve your desired goal, you would essentially be creating an array that basically emulates the effect of a data structure that 'holds' other data structures.
NOTE: If you had/have plans on trying to create a data structure that holds a data structure that holds a data structure. A.K.A. a triple nested data structure and in this case I think that would be a Matrix, WHICH I WOULDN'T RECOMMEND!
None the less, the matrix structure would be in the form of the first index position of keyword, being assigned the whole array of keywords, which would include all of the data stored in each index position of the keywords array. Then there would something probably like: keywords1, keywords2, ... keywords9,
which would essentially emulate the form of:
char *keyword[10] = {
char *keywords0[10] = {"float", etc, etc, etc.};
char *keywords1[10] = {"keyword1", "secondIndexOfThisArray", etc, etc, etc.};
and so
};
So basically from right to left, the keyword array, is an array of pointers that points to array of pointers that points to character arrays.
If that is what you are representing you would be better defining a custom data type of struct/record, and with in that custom structure you would want to define a subordinate or child level of structures. You could also pre-declare them then initialize them.
e.g.
typedef *nestedDataStructures {
struct keyWords[];
struct keyWords1[];
struct keyWords2[];
... and so on.
}; nestedDataStructures
Instead of adding ten structs to one custom structure I would break down into 3 or 4 (how ever many structures and use) and create a module in order to yield symmetrical layers of abstraction as you manipulate your data set.
None the less, you can not create the character array and potentially assign the other character array in the fashion that you did (or who knows maybe you can), but the way you would want to emulate the array that holds arrays, is to create a character pointer array up front, of X number index positions and then initialize then use the character arrays in the form of a strings declared with in the initialization of the original declaration.
So basically you could declare your whole array upfront, then with in your program design, either dereference each index position, use assignment, or print/write the index position.
Like for instance you could always do something like this:
/* Example of the program and declaration with out a function */
#include <stdio.h>
int main(){
/*
* A character pointer array that contains multiple
* character arrays.
*/
char *grewMe[2] = {"I want to ", "grow to be bigger"};
int w = 0;
for(; w < 2;) {
printf("%s", grewMe[w]);
++w;
}
printf(" :-)\n");
w = 0;
return 0;
}
// Output:
// I want to grow to be bigger :-)
Or something like this:
/* Example of program: function passed arguments
* of a pointer to the array of pointers
*/
#include <stdio.h>
void mygrowth(char *growMe[]);
int main(){
char *growMe[2] = {"I want to ", "grow to be bigger"};
mygrowth(growMe);
printf(" :-)\n");
return 0;
}
void mygrowth(char *growMe[])
{
int w = 0;
for (; w < 2;) {
printf("%s", growMe[w]);
++w;
}
}
The assignment of each index position as it's passed as an argument:
/*
* This program compiles, runs and outputs properly
* Example of a program with a function of
* arguments pnt2pnter
*/
#include <stdio.h>
#include <stdlib.h>
void thoughtAsAFunction(char **iThink);
int main()
{
char *iThink[10] = {"I am trying to grow, but it's a hard task to ",
"accomplish. My father is short ",
"my mother is even shorter than him, ",
"what is the probability of me getting taller? ",
"Well both my grandfather's were Six ",
"Foot Five, and both my grandmother's ",
"were over 5 foot 8 inches tall! If my ",
"grandparent's genes point to my parents, and my ",
"parent's genes point to mine I might have a chance ",
"of being 6 foot. Do you know what I mean? "};
thoughtAsAFunction(iThink);
printf(":-)\n");
return 0;
}
void thoughtAsAFunction(char **iThink) {
int andy = 0;
for (; andy < 10;) {
char * pntThroughPnt = iThink[andy];
printf("%s", pntThroughPnt);
++andy;
}
andy = 0;
}
Or pass by reference, with an increment of the loop count variable:
/*
* This program compiles, runs, and outputs all of the character
* arrays.
*
*/
#include <stdio.h>
#include <stdlib.h>
void thoughtAsAFunction(char **iThink);
int main()
{
char *iThink[10] = {"I am trying to grow, but it's a hard task to ",
"accomplish. My father is short ",
"my mother is even shorter than him, ",
"what is the probability of me getting taller? ",
"Well both my grandfather's were Six ",
"Foot Five, and both my grandmother's ",
"were over 5 foot 8 inches tall! If my ",
"grandparent's genes point to my parents, and my ",
"parent's genes point to mine, then I might have a chance ",
"of being 6 foot. Do you know what I mean? "};
int andy = 0;
for (; andy < 10;) {
// pass by reference and increment.
thoughtAsAFunction(&iThink[andy]);
++andy;
}
printf(":-)\n");
andy = 0;
return 0;
}
void thoughtAsAFunction(char **iThink) {
char * pntThroughPnt = *iThink;
printf("%s", pntThroughPnt);
}
Keep in mind that this is the case if you declare the array of pointers (char *array[10];), and each pointer points to an array of characters.

Related

When Declaring a Double Pointer that is an array why is there no need to put brackets because it is an array of pointers?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** AllocateShoppingList(int numFoods);
char* AllocateItem();
int DetermineNumberOfCandy(char** list, int numFoods);
int main()
{
char** stringArray;// pointer to pointers
char* words; //pointer to char array
//1. ask the user how many foods are on their list
int foods;
printf("How many foods on the shopping list?\n");
scanf("%d", &foods);
//2. call the AllocateShoppingList function and store the result
stringArray = AllocateShoppingList(foods);
//3. for X times (user's previous input), call the AllocateItem function
// and store the result in the list of pointers (step 2)
for(int i =0;i < foods; i++){
words = AllocateItem();
stringArray[i] = words;}
//strcpy(stringArray[i],words); why not work?
//4. call the DetermineNumberOfCandy function, and print the result
printf("Candy appeared this many times: %d\n",DetermineNumberOfCandy(stringArray, foods));
//5. free up all of the pointers that are held by the shopping list
//6. free up the shopping pointer itself
free(words);
free(stringArray);
}
int DetermineNumberOfCandy(char** list, int numFoods)
{
//0. setup a counter variable
int counter = 0 ;
//1. for each pointer in the shopping list:
//1a. compare the string at the pointer's address to "candy"
for(int i =0; i< numFoods; i++)
if (strcmp(list[i],"candy")==0)
// why you dont have to dereference it
// this concept works with single pointers
// does it work with double or tripple pointers as long as it orignally points to the string?
counter++;
//1b. if it is candy, then tick up the counter variable
//2. return the counter variable
return counter;
}
char** AllocateShoppingList(int numFoods)
{
return calloc(numFoods, sizeof(char*));
//1. allocate memory that can hold X pointers (X = numFoods)
//2. return the memory address holding this pointer to pointers
}
char* AllocateItem()
{
char* wordPtr;
char word[100];
//1. get a word from the user that is max 100 characters
scanf("%s", word);
//2. determine how large the word actually is
wordPtr = calloc(strlen(word)+1,sizeof(char));
strcpy(wordPtr, word);
//3. allocate memory that is just enough to hold the word
return wordPtr;
//4. copy the user's word into the new memory location
//5. return the memory address holding the word
}
**For this code we had to get a shopping last and see print out how many times candy was in the shopping list and in order to do that we had to allocates enough memory to hold onto as many words (strings) as the user wants to have on their shopping list. Then, for each item, allocate just enough memory to store the word. **
This declaration right here for me doesn't make sense
**char** stringArray; **
From what I understand the double pointer is an array which element in the array contains a pointer to the string address.
Because of this I would think that we would have to declare the double pointer like:
char stringArray[]; **
something like this but that would not work.
So I wanted to know how the code knows it is an Array of pointers if we never put brackets
I tried declaring the double pointer with an array and could not get it to work nor could figure out if it was even possible.
Pointers are pointers, arrays are arrays. However, when an array in C is used in an expression or passed as a parameter to a function, it "decays" into a pointer to the first element of that array. This in turn enables things like a pointer arithmetic and the convenient use of the [] index operator.
This also means that in most contexts, a pointer to the first element can be used in place of an array. If we have an array of pointers char* arr[n]; then a char** can be used to point at the first item, and from there on the rest of the array.
So if you'd write a function like int DetermineNumberOfCandy(int numFoods, char* list[numFoods]); that's fine and valid C, but list "decays" into a pointer to the first element anyway, so it is 100% equivalent to
int DetermineNumberOfCandy(int numFoods, char** list);
Also you have misc bugs in your code.
Since AllocateItem is what allocates a valid memory location, the stringArray[i] in main() must be assigned to this memory location before it can be used. Because until then it is just an uninitialized pointer pointing at garbage. Therefore you can't strcpy(stringArray[i], words). Remember that the function did not just allocate a chunk of memory, but also filled it with valid data. So it is sufficient to set the pointer to point at that data, no need to copy anything.
The word variable doesn't fill any purpose, you could as well write this:
for(int i=0; i < foods; i++){
stringArray[i] = AllocateItem();
}
Similarly free(words) is wrong, this would only free the last allocated memory. Rule of thumb: for each malloc call you must have a corresponding free call! Therefore it should be:
for(int i=0; i < foods; i++){
free(stringArray[i]);
}
free(stringArray);
When you declare a variable like a string like this:
char str[10];
Your computer declares in fact a pointer but allocates enough memory to hold 10 characters automaticely. You will see that if you dereference it, you will get the first character of your string.
About your strcpy not working on line 20, if doesnt work because you created your i variable in a for loop and when you do that, the variable disapeers at the end of the loop so you are not able to use it nowhere into your code.
And about your line 40, you can use pointers in at least 2 deferent ways. First one is passing a variabe as a pointer in a function for you to dont have to return it at the end of a function like so:
int main()
{
int var = 0;
my_funct(&var);
//var = 1 now
}
void myfunct(int *var)
{
*var = 1;
}
Here you need to dereference it but if you allocated memory to your pointer, you can now use it as an array without dereferencing it.
Oh and here, you just free one pointer of the 2 in your stringarray. To free everything, try:
for(int i = 0; i < foods; i++) {
free(StringArray[i]);
}
free(StringArray);
Tell me if i didnt awnser to everything or if i was not clear enough

How to return a char** in C

I've been trying for a while now and I can not seem to get this working:
char** fetch (char *lat, char*lon){
char emps[10][50];
//char** array = emps;
int cnt = -1;
while (row = mysql_fetch_row(result))
{
char emp_det[3][20];
char temp_emp[50] = "";
for (int i = 0; i < 4; i++){
strcpy(emp_det[i], row[i]);
}
if ( (strncmp(emp_det[1], lat, 7) == 0) && (strncmp(emp_det[2], lon, 8) == 0) ) {
cnt++;
for (int i = 0; i < 4; i++){
strcat(temp_emp, emp_det[i]);
if(i < 3) {
strcat(temp_emp, " ");
}
}
strcpy(emps[cnt], temp_emp);
}
}
}
mysql_free_result(result);
mysql_close(connection);
return array;
Yes, I know array = emps is commented out, but without it commented, it tells me that the pointer types are incompatible. This, in case I forgot to mention, is in a char** type function and I want it to return emps[10][50] or the next best thing. How can I go about doing that? Thank you!
An array expression of type T [N][M] does not decay to T ** - it decays to type T (*)[M] (pointer to M-element array).
Secondly, you're trying to return the address of an array that's local to the function; once the function exits, the emps array no longer exists, and any pointer to it becomes invalid.
You'd probably be better off passing the target array as a parameter to the function and have the function write to it, rather than creating a new array within the function and returning it. You could dynamically allocate the array, but then you're doing a memory management dance, and the best way to avoid problems with memory management is to avoid doing memory management.
So your function definition would look like
void fetch( char *lat, char *lon, char emps[][50], size_t rows ) { ... }
and your function call would look like
char my_emps[10][50];
...
fetch( &lat, &lon, my_emps, 10 );
What you're attempting won't work, even if you attempt to cast, because you'll be returning the address of a local variable. When the function returns, that variable goes out of scope and the memory it was using is no longer valid. Attempting to dereference that address will result in undefined behavior.
What you need is to use dynamic memory allocation to create the data structure you want to return:
char **emps;
emps = malloc(10 * sizeof(char *));
for (int i=0; i<10; i++) {
emps[i] = malloc(50);
}
....
return emps;
The calling function will need to free the memory created by this function. It also needs to know how many allocations were done so it knows how many times to call free.
If you found a way to cast char emps[10][50]; into a char * or char **
you wouldn't be able to properly map the data (dimensions, etc). multi-dimensional char arrays are not char **. They're just contiguous memory with index calculation. Better fit to a char * BTW
but the biggest problem would be that emps would go out of scope, and the auto memory would be reallocated to some other variable, destroying the data.
There's a way to do it, though, if your dimensions are really fixed:
You can create a function that takes a char[10][50] as an in/out parameter (you cannot return an array, not allowed by the compiler, you could return a struct containing an array, but that wouldn't be efficient)
Example:
void myfunc(char emp[10][50])
{
emp[4][5] = 'a'; // update emp in the function
}
int main()
{
char x[10][50];
myfunc(x);
// ...
}
The main program is responsible of the memory of x which is passed as modifiable to myfunc routine: it is safe and fast (no memory copy)
Good practice: define a type like this typedef char matrix10_50[10][50]; it makes declarations more logical.
The main drawback here is that dimensions are fixed. If you want to use myfunc for another dimension set, you have to copy/paste it or use macros to define both (like a poor man's template).
EDITa fine comment suggests that some compilers support variable array size.
So you could pass dimensions alongside your unconstrained array:
void myfunc(int rows, int cols, char emp[rows][cols])
Tested, works with gcc 4.9 (probably on earlier versions too) only on C code, not C++ and not in .cpp files containing plain C (but still beats cumbersome malloc/free calls)
In order to understand why you can't do that, you need to understand how matrices work in C.
A matrix, let's say your char emps[10][50] is a continuous block of storage capable of storing 10*50=500 chars (imagine an array of 500 elements). When you access emps[i][j], it accesses the element at index 50*i + j in that "array" (pick a piece of paper and a pen to understand why). The problem is that the 50 in that formula is the number of columns in the matrix, which is known at the compile time from the data type itself. When you have a char** the compiler has no way of knowing how to access a random element in the matrix.
A way of building the matrix such that it is a char** is to create an array of pointers to char and then allocate each of those pointers:
char **emps = malloc(10 * sizeof(char*)); // create an array of 10 pointers to char
for (int i = 0; i < 10; i++)
emps[i] = malloc(50 * sizeof(char)); // create 10 arrays of 50 chars each
The point is, you can't convert a matrix to a double pointer in a similar way you convert an array to a pointer.
Another problem: Returning a 2D matrix as 'char**' is only meaningful if the matrix is implemented using an array of pointers, each pointer pointing to an array of characters. As explained previously, a 2D matrix in C is just a flat array of characters. The most you can return is a pointer to the [0][0] entry, a 'char*'. There's a mismatch in the number of indirections.

Dynamic arrays of arrays

If I have:
typedef char pos[2]; /*btw I now know no one should do this*/
void someFunction(void) {
pos *s = malloc(sizeof(pos) * 2);
}
In the cases like this how s working? What is it? Arrays are like pointers except when you use sizeof on them you will get the "correct" size. So in this case the following means that s is going to be a pointing to a sizeof(char)*4 sized memory? But the type of s is a pointer to a pointer which means that you can't use s as a one dimensional array (or a pointer which points chars ) becouse you "still need to go through one level/layer of indirection/pointer". Or am I wrong?
How can I use s? As a 2 dimensional array or as a one dimensional one?
(If you are interested: I need this bc I want to return two pos from a function. Is there a better way? (despite fixing this and using a struct for storing position data instead of a 2-sized array))
This typedef costruct is just equivalent to:
#include <stdio.h>
void someFunction(void) {
char (*pos)[2];
pos = malloc(sizeof(*pos) * 2);
pos[0][0] = 1;
}
int main(void) {
someFunction();
return 0;
}
That means that pos is the pointer to two-elements array of char. You can use just like as two-dimensional array with fixed column size as two. Number of rows is controlled by malloc() call, in your case it happened to be two as well.

2D array using strings

I'm stuck on some homework which isn't graded (its meant for practice).
I have to create a function called find_name that takes 2 arguments. The first argument is a 2D array of names (strings), and the second is a character string which is used to find the name in the 2D array, the function must return 1 if found else 0.
When i call the function (which is empty right now), I get this warning: passing argument 1 of 'find_name' from incompatible pointer type
Here is the important bits.
In Main
char strNameList[][2] = { { "Luca","Daniel"} ,{"Vivan","Desmond"},{"Abdul","Justin"}, {"Nina","Marlene"},{"Donny","Kathlene"} };
char strFindName[] = "\0";
printf("Please enter a name to look for: ");
gets(strFindName);
nSearch = find_name(strNameList, strFindName);
The Function
int find_name(char strNameList[][2], char strLookUp[])
I'm new to C (I'm a student), and I'm completely confused about strings (string arrays etc).
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)
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.
Your function find_name() is looking for a 2-D array of characters ie:
char arr[][2] = { { 'a', 'b'}, ...
if you want to make them strings you need:
char *arr[][2] = { {"John", "Smith"}, ...
Then in the function parameter list you need:
void find_name(char *something[][2])
{
printf("first name: %s, second name: %s\n", something[0][0], something[0][1]);
And in your main() function call it just by:
find_name(arr);

Find the size of integer or floating point array when array is in other file and function is in other file? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to find the sizeof(a pointer pointing to an array)
I know this to find the size of array = sizeof(arr)/sizeof(arr[0])
But I have to implement the following (It's just a demo):
demo.h
#ifndef __DEMO_H
#define __DEMO_H
void heap_sort(int *);
#endif
demo.c
void heap_sort(int *ptrA)
{
//implementing heap sort
But here it requires length of array
}
main.c
#include "demo.h"
int main(void)
{
int A[10];
heap_sort(A)
return 0;
}
FYI .. It's just a demo.. but here I have to implement it in some other scenarios in which there is restriction that "DON'T CHANGE ANYTHING IN HEADER FILE" which means i can't change the function signature . Then how to get the array length in demo.c For char it's easy to get by help of strlen() Isn't there anything similar to get the length of int,float double types
The only alternatives I see are:
use a special value as terminator (as strlen does).
use the Pascal trick, and place array length in the first element.
store the array size in a global external variable.
use a separate function.
E.g.:
int arraySize(int newSize)
{
static int arraySize = 0;
int oldSize;
oldSize = arraySize;
if (newSize)
arraySize = newSize;
return oldSize;
}
in main.c:
arraySize(10);
in demo.c:
arraylen = arraySize(0);
if you can't change the function signature, then maybe you could pass the size of the array in the first element.
A[0] = 10;
heap_sort(A);
Or mark the end of the array with some special value, but I don't like this one because you'd have to iterate the whole array to find the length and you need to make sure this value is not used in the array:
A[LENGTH-1] = END//some value;
void array_length(A) {
while (*A++ != END) {
length++;
}
}
This is just a solution for the restrictions you imposed, what I would normally do, is either pass the size of the array as a second argument, or use a struct for the array:
struct array_t {
int *data; //allocate this
int size;
};
Note: other horrible solutions include global variables.
Thinking of strlen() is going into the right direction.
Strings are character arrays with a '\0' as array termination, as last element.
You could take the same approach for any other type of array.
Just define one value as the value which indicates the last element in an array. Searching for this value then helps you to find the size of the array.
Update:
I like mux's idea of using the first element in an array.
Anyhow, using it to store the numbers of element in there might lead to problems in case the number of elements in the array is larger as what can be store in an array's element (a char array, for example, whould then be limited to 255 elements).
My approach on the other hand has the draw back that the value used as terminator to the array is not usable as real value in the arra itself.
The combining the former and the latter approaches, I propose to use the first element of the array to store the value which is used as terminator of the array.
The constraint seems a bit odd, but whatever.
Why not use a global variable to store the size.

Resources