How to add some element to globally declared char array & access the elements of the array from the another function?
I declared like this in source file
extern char *ArrayItems[] = {"Item1"};
Function 1 - Add element into Array
void AddSomeElementToGloablArray()
{
ArrayItems[1] = "Item 2";
ArrayItems[2] = "Item 3";
...
}
Function 2 - Add again some element into Array
void AddSomeElementToGloablArray()
{
ArrayItems[3] = "Item 3";
ArrayItems[4] = "Item 4";
...
}
Main Function - To access the element of the array
void Main()
{
AddSomeElementToGloablArray();
char *ItemValue = ArrayItems[3];
}
I tried like above code but it does not return added element. Here I cannot pass or return an array from function.
Please anybody help
How to add an element to Global char *Array[]?
There is no way to add an element to an array. During the life time of an array its size never changes - no elements are ever added nor removed.
The way to solve this is indirection: Instead of a plain static/automatic array, we use a pointer to one and allocate that array dynamically. When you want more elements, we simply create a new, bigger array, copy (possibly by moving) the old elements into the new one and destroy the old array. This data structure is typically named "growable array" or "resizable array".
Of course, it would be madness to maintain bare pointers to a dynamic array, so we want to create a RAII wrapper class, with proper destructor etc. to make sure that the memory is handled properly. At this point I'm going to point out that such wrapper for a resizable array exists in the standard library, so there is no need for you to implement one yourself: std::vector.
extern char *ArrayItems[] = {"Item1"};
This is ill-formed because a string literal can not be converted to a (non-const) char*.
ArrayItems[1] = "Item 2";
This has undefined behaviour because the index is outside the bounds of the array.
extern char *ArrayItems[] = {"Item1"};
I'm not sure if extern is needed here. If you only use it in a single source file, you don't need the extern. If you need to share the variable across multiple compilation units (source files), you should declare it in header file with extern keyword, and then declare the variable itself in any one of the source files.
/* shared.h */
extern char *ArrayItems[];
/* foo.c */
char *ArrayItems[] = {"Item1"};
Now, to add an element to array is not trivial. You need to do dynamic memory allocation. If you are using C++, it is highly recommended that you use std::vector instead. The following code works in standard compiler that support C++11.
#include <vector>
#include <iostream>
std::vector<char const *> ArrayItems = {"Item1"};
void AddSomething()
{
ArrayItems.push_back("Foo");
ArrayItems.push_back("Bar");
}
int main()
{
std::cout << ArrayItems[0] << std::endl;
AddSomething();
std::cout << ArrayItems[1] << std::endl;
std::cout << ArrayItems[2] << std::endl;
return 0;
}
Output:
Item1
Foo
Bar
I use char const * instead of char * because "Item1" is a string literal, which shall not be modified on runtime anyway.
short answer: don't do that. use std::vector and call vector.push_back.
long answer: a global array declared with [] has fixed width, so you cannot just create a new member by accessing it's element number, this is extremely dangerous as you are accessing out of bounds memory.
extern keyword does not allocate any memory for ArrayItems. It is only a declaration and not a definition. If this variable is declared in some other file in your project, and you want to use in the current file, you need to declare with extern keyword. If this variable is not defined in any other file, you can simply remove that keyword. Your code will work. However as suggested in the other answers, it is not a good idea to use global variables.
Related
I have a struct with an array in it. The size of this array needs to be 3*input_variable. How can I define a number externally, which is multiplied by an input value, that I can use in a struct to declare the length of an array?
I have tried defining the variable h outside of main as
extern h
then assigning it's value in main from the input variable.
I have also tried to use (in summary)
nt main(int argc, char** argv)
{
int input_variable;
std::cin << input_variable;
int h = input_variable * 3;
void some_function(); // function does some stuff
// with the structs
#ifndef ARRAY_SIZING
#define ARRAY_SIZING h
#endif
return 0;
}
struct _struct_
{
constexpr std::size_t b = ARRAY_SIZING;
double* arr[b];
};
int some_function()
{
// structs are used down here.
return 0;
}
I would love to be able to allocate the size of an array in a struct using an input parameter. Thank you.
Hm. Plain C-arrays in C++. Mostly never needed. OK, you want to interface to a library function.
My guess is that the library does not expect an array, but a pointer. And since your struct contains an array to pointer to doubles, I assume the lib wants to see a double**.
I hardly can imagine that old libraries use references or pointer to arrays, something like:
void function (double* (&array)[10]); // Reference to array
void function (double* (*array)[10]); // Pointer to array
because also here you need an array with a size known at compile time.
I'd rather expect something like
void function (double** array, size_t size); // Pointer to Pointer to double
So, use a std::vector like this:
std::vector<double *> arr(input_variable * 3);
And if you want to hand over the arrays data to the lib functions, then use the vectors data function.
function (arr.data());
You could also create the array with new.
Last hint: Do not use raw pointers.
I hope that I could help a little . . .
Hoping for a little C++ assistance - I'm very new to the topic. I'm attempting to dynamically create an array based on user input with a pointer, then pass the array to a function. But the pointer (and thus array) pass feels a little wrong because there is no dereferencing that occurs.
During/after passing, do we just treat the pointer as if it were any normally declared-and-passed array, without the need to dereference (*) anything? Or am I applying this incorrectly?
Pseudocode follows:
#include<iostream>
using namespace std;
void arrayFunc(int [], int); // << Note no indication of pointer pass
int main()
{
int *arrayPtr = 0; // Array pointer
int arrayElem = 0; // Number of elements in array
cout << "\nPlease enter the number of elements: ";
cin >> arrayElem;
arrayPtr = new int[arrayElem]; // Dynamically create the new array
arrayFunc(arrayPtr, arrayElem); // << Note no dereferencing or other indication of pointer
return 0;
}
void arrayFunc(int array[], int arrayElem) // << Same here - now it's just a plain old array
{
// All the functiony-bits go here, referencing array without the need to dereference
}
[EDIT] While the above code works, the following includes the fixes determined in the discussion below:
#include<iostream>
using namespace std;
void arrayFunc(int*, int); // Changed to pointer pass instead of []
int main()
{
int *arrayPtr = 0; // Array pointer
int arrayElem = 0; // Number of elements in array
cout << "\nPlease enter the number of elements: ";
cin >> arrayElem;
arrayPtr = new int[arrayElem]; // Dynamically create the new array
arrayFunc(arrayPtr, arrayElem);
return 0;
}
void arrayFunc(int* array, int arrayElem) // Passing a pointer now instead of []
{
// All the functiony-bits go here, referencing array without the need to dereference
}
You should pass the pointer in your function, because it describes the situation accurately i.e. you are passing a dynamically allocated memory. arrayPtr is essentially a pointer to the first element of the array. As a result, you do not need to worry about dereferencing it.
Change the function signature to:
void arrayFunc(int*, int);
Your attempt is correct. You are passing the array pointer by value. You can then dereference it as normal within arrayFunc
C is designed to pretend a pointer and an array are the mostly same thing. Lots of simple uses are easier because of that. But the concept gets much more confusing when you think about a pointer to an array. It feels like it shouldn't be the same thing as a pointer to the first element of that array, but in the common methods for allocating memory and using pointers, a pointer to an array really is just a pointer to the first element of the array.
I find it best to think of "pointer to first element of array of" as the normal meaning of * in C. The special case of pointing to a scalar object is effectively treating the scalar as the first (and only) element of an array of length 1.
string** flowFile() {
string line;
string word[8];
int i=0;
static string flow[23][2];
ifstream myfile ("test.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
strSplit(line,word);
flow[i][0]=word[1];
flow[i++][1]=word[2];
}
myfile.close();
}
else cout << "Unable to open file";
return flow;
}
int main()
{
string **fl=flowFile();
}
I'm getting this error:
error: cannot convert ‘std::string (*)[2] {aka std::basic_string<char> (*)[2]}’
to ‘std::string** {aka std::basic_string<char>**}’
in return
What is wrong with my code?
string flow[23][2] and string ** are two different incompatible types. One cannot convert to another implicitly. Thats all. The solution is to make them compatible, by making the later string [23][2], return reference and accept reference, but that would still be a bad solution, because you're still working with raw arrays.
A good solution is to use std::vector and std::string. Maybe, you need std::pair also, or std::array.
Here is one possible solution:
#include <vector>
#include <array>
#include <string>
//C++11 style typedef
using flow_data_t = std::vector<std::array<std::string,2>>;
//reimplementation of your function
flow_data_t flowFile()
{
std::string line;
std::string word[8];
int i=0;
flow_data_t flow;
std::ifstream myfile ("test.txt");
if ( !myfile )
cout << "Unable to open file";
while ( std::getline (myfile,line) )
{
strSplit(line,word);
flow.push_back({word[0], word[1]});
}
return flow;
}
int main()
{
flow_data_t data=flowFile();
for(auto const & row : data)
for(auto const & col : row)
//work!
}
Hope that helps.
You cannot return array from a function even though you can return a pointer and let your array decay to a pointer: Array Decay
However 2D array can decay to neither T* nor T** because of the memory layout of the array is different from "2D pointer array" (it is actually more like flattened), and you cannot return array from function. However in C++ you can return array reference Full Code:
//This does not work
//typedef string * string2d[2];
//typedef string *(&string2d)[2];
typedef string (&string2d)[23][2];
string2d flowFile() {
static string flow[23][2];
return flow;
}
Array reference would even preserve the information of how big each row and columns are and no array decaying happen.
Of course, a more suggested "C++ way" to do this is using std::vector (as always).
In C++, arrays have type std::vector. You should use these, not low-level builtin arrays declared with [].
In C++, string [23] is sometimes interchangeable with string*, but string[23][2] is never interchangeable with string**. That's one reason you should not use builtin arrays.
In C++, you cannot return a local builtin array variable. It will compile but then your program will probably crash. This is another reason you should not use builtin arrays. (Returning a static array should be OK though).
There are many more reasons.
There is nothing wrong with returning a pointer to a static variable. It's just that the return type must be declared properly. It kind of makes sense if you try to reproduce what the declarations mean, and what the compiler accordingly tries to do. Consider the declaration static string flow[23][2];. It declares 23 rows of strings, each with 2 elements. It helps if you look at it as a one-dimensional array. It just so happens that the array elements are arrays, but that's not so important right now (but we'll come back to it). From this perspective the array has just 23 elements, and each element has the size of 2 strings. Like with all arrays, the elements (here: arrys of 2 strings) are simply lined up in memory.
Like any array, flow will in most contexts decay to a pointer to its first element. Incrementing that pointer will point to the next element, i.e the second row. Numerically the compiler must add 2*sizeof(string) to the address of flow in order to compute the address of flow's next element, which would be flow[1]. (It comes directly behind flow[0]. No magic here.)
Now if you declare string **flowpp, flowpp is a pointer already, no need to decay. If we think it is pointing to the first element in an array, what type would the elements have? Sure enough: plain pointers. Incrementing flowpp would let it point to the next element. My pointers are 4 bytes large, so that numerically adding just 4 to flowpp would be enough to access flowpp's next element. Compared to what needs to be added to flow (remember, 2*sizeof(string)), that's completely different. The compiler computes the offsets of elements depending of what the pointers point to! Which is very different in the two cases.
So what can your function return? What does flow decay to when you return it? It decays to a pointer to its first element. The elements are arrays of two strings. It must be string xxx[2], with xxx being a pointer: hence string (*p)[2]. If the pointer is actually returned by a function, we have a function call instead of plain p, so it's (*f())[2].
Here is a complete example:
#include<iostream>
using namespace std;
const int numFlowElems = 3, numArrElems = 2;
/** #return a pointer to the first element of a static array
of string[numArrElems]s.
*/
string (*flowFile())[numArrElems]
{ // init so that we see something below.
static string flow[numFlowElems][numArrElems]
= {{"1","2"},
{"3","4"},
{"5","6"}
};
// your function code ...
return flow;
}
int main()
{
// array decays to ptr, like usual. Ptr elems are string[numArrElems].
// ptrToArr is a pointer to arrays of two strings.
string (*ptrToArr)[numArrElems] = flowFile();
for( int flowInd= 0; flowInd<numFlowElems; ++flowInd )
{
for(int strInd = 0; strInd<numArrElems; ++strInd)
{
cout << ptrToArr[flowInd][strInd] << ' ';
}
cout << endl;
}
return 0;
}
How do you parse string (*flowFile())[numArrElems]? I needed two attempts to get the declaration right, if that's any consolation. The key is that in C and C++ (not in C#, mind you!) a declaration has the shape of an expression.
You can do it from the inside to the outside: flowFile() is a function. The result is dereferenced because the function call has higher precedence than the star: *flowFile() is the dereferenced result. Apparently that result is an array of size numArrElems, with elements which are strings.
You can do it outside in: The result of (*flowFile())[numArrElems] is declared as a string. (*flowFile()) is an array of strings with numArrElems elements. Apparently flowFile() must be dereferenced to obtain that array so that flowfile is a function which returns a pointer to an array of numArrElems strings. That's true! It returns the first element of flow, which is exactly an array of strings.
Vectors of vectors might indeed be easier; if you want to retain the semantics you should pass references, as others mentioned: After all, all functions in your original program will operate on the same static array. If you pass vectors by value that will not be the case any longer. But then, that may actually be beneficial.
I declare the following array:
char* array [2] = { "One", "Two"};
I pass this array to a function. How can I find the length of this array in the function?
You can't find the length of an array after you pass it to a function without extra effort. You'll need to:
Use a container that stores the size, such as vector (recommended).
Pass the size along with it. This will probably require the least modification to your existing code and be the quickest fix.
Use a sentinel value, like C strings do1. This makes finding the length of the array a linear time operation and if you forget the sentinel value your program will likely crash. This is the worst way to do it for most situations.
Use templating to deduct the size of the array as you pass it. You can read about it here: How does this Array Size Template Work?
1 In case you were wondering, most people regret the fact that C strings work this way.
When you pass an array there is NOT an easy way to determine the size within the function.
You can either pass the array size as a parameter
or
use std::vector<std::string>
If you are feeling particularly adventurous you can use some advanced template techniques
In a nutshell it looks something like
template <typename T, size_t N>
void YourFunction( T (&array)[N] )
{
size_t myarraysize = N;
}
C is doing some trickery behind your back.
void foo(int array[]) {
/* ... */
}
void bar(int *array) {
/* ... */
}
Both of these are identical:
6.3.2.1.3: Except when it is the operand of the sizeof operator or the unary & operator,
or is a string literal used to initialize an array, an expression that has type
‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’
that points to the initial element of the array object and is not an lvalue. If
the array object has register storage class, the behavior is undefined.
As a result, you don't know, inside foo() or bar(), if you were
called with an array, a portion of an array, or a pointer to a single
integer:
int a[10];
int b[10];
int c;
foo(a);
foo(&b[1]);
foo(&c);
Some people like to write their functions like: void foo(int *array)
just to remind themselves that they weren't really passed an array,
but rather a pointer to an integer and there may or may not be more
integers elsewhere nearby. Some people like to write their functions
like: void foo(int array[]), to better remind themselves of what the
function expects to be passed to it.
Regardless of which way you like to do it, if you want to know how long
your array is, you've got a few options:
Pass along a length paramenter too. (Think int main(int argc, char
*argv)).
Design your array so every element is non-NULL, except the last
element. (Think char *s="almost a string"; or execve(2).)
Design your function so it takes some other descriptor of the
arguments. (Think printf("%s%i", "hello", 10); -- the string describes
the other arguments. printf(3) uses stdarg(3) argument handling, but
it could just as easily be an array.)
Getting the array-size from the pointer isn't possible. You could just terminate the array with a NULL-pointer. That way your function can search for the NULL-pointer to know the size, or simply just stop processing input once it hits the NULL...
If you mean how long are all the strings added togather.
int n=2;
int size=0;
char* array [n] = { "One", "Two"};
for (int i=0;i<n;++i)
size += strlen(array[i];
Added:
yes thats what im currently doing but i wanted to remove that extra
paramater. oh well –
Probably going to get a bad response for this, but you could always use the first pointer to store the size, as long as you don't deference it or mistake it for actually being a pointer.
char* array [] = { (char*)2,"One", "Two"};
long size=(long)array[0];
for(int i=1; i<= size;++i)
printf("%s",array[i]);
Or you could NULL terminate your array
char* array [] = { "One", "Two", (char*)0 };
for(int i=0;array[i]!=0;++i)
{
printf("%s",array[i]);
}
Use the new C++11 std::array
http://www.cplusplus.com/reference/stl/array/
the standard array has the size method your looking for
Hey guys! When I try to do the following in a header file
static const char FOOT[] = "Foot";
static const char FEET[] = FOOT;
I get a compiler error of error: initializer fails to determine size of FEET. I was wondering what the cause of this is, and if there is a way to rectify it. Thanks!
Even though why you get this error has been answered, there's more to the story. If you really need for FEET to be an array, then you can make it a reference instead of a pointer:
char const foot[] = "foot";
char const (&feet)[sizeof foot] = foot;
// reference to array (length 5) of constant char
// (read the declarations "from the inside-out")
char const* const smelly_feet = foot;
// constant pointer to const char
int main() {
cout << sizeof feet << ' ' << feet << '\n';
cout << sizeof smelly_feet << ' ' << smelly_feet << '\n';
cout << sizeof(void*) << " - compare to the above size\n";
return 0;
}
(More examples of the inside-out rule.)
Secondly, static at file and namespace scope means internal linkage; so when you use it in a header, you'll get duplicate objects in every TU using that header. There are cases when you want this, but I see no reason for it in your code, and it's a common error.
Regarding array size: The sizeof operator returns the memory-size of an object or instance of a type. For arrays this means the total memory-size of all of its items. Since C++ guarantees that sizeof(char) is 1, the memory-size of a char array is the same as its length. For other array types, you can divide by the memory-size of one item to get the length of an array:
void f() {
int array[5];
assert((sizeof array / sizeof *array) == 5);
}
And you can generalize it to a function template:
template<class T, int N>
int len(T (&)[N]) {
return N;
}
// use std::size_t instead of int if you prefer
This exists in boost as boost::size.
You may see code that uses sizeof array / sizeof *array, either through a macro or directly, either because it's old or doesn't want to complicate matters.
The cause is that you are saying that FEET[] is an array of chars but you're initializing it to a ptr;
To rectify, you can change FEET from FEET[] to *FEET
Could also do the same with FOOT
There is no '=' operator for arrays in C++, you need to use strcpy or something similar (which you can't do with a static const). Depending on your requirements the following might be useful:
#define contentsOfFoot "FOOT"
static const char FOOT[5] = contentsOfFoot;
static const char FEET[5] = contentsOfFoot;
static const char *feeet = FOOT;
static is deprecated, and const variables at namespace scope are effectively static, anyway. Also, please reserve ALL_CAPS for preprocessor identifiers.
A bigger question is why you are using raw arrays at all. You very likely want something more like this:
std::string const foot = "foot";
std::string const feet = foot;
Or, more likely:
#include <string>
namespace spbots {
typedef std::string string_t;
string_t const foot = "foot";
string_t const feet = foot;
}
One way would be this
static const char FOOT[] = "Foot";
static const char *FEET = FOOT;
I want to emphasise that you shouldn't put that stuff in a header file. Variables should only be put in header files if you want to make them globally visible (generally not a great idea but it's a legitimate technique).
feet.h
extern char feet[];
feet.cpp
char feet[] = "FEET";
Now when you include feet.h in a different .cpp file, say leg.cpp, the declaration in feet.h means leg.cpp can see and use the array defined in feet.cpp
The extern keyword has the opposite meaning to the static keyword you use. A typical use of static is as follows;
feet.cpp
static char feet[] = "FEET";
Now feet[] is explicitly not visible outside feet.cpp. The static keyword is responsible for this lack of visibility. So static=local, extern=global and (perhaps unfortunately?) extern is the default, so if you don't use either keyword you get extern whether you like it or not.
Because static=local, there's nothing to communicate to other modules, so no need to have a declaration in a header file for other modules to see. Everything is kept within feet.cpp, probably a better idea than a global variable.
Another point I am implicitly trying to get through with this explanation is that declarations go into header files, definitions go into .cpp files. In your question you have a definition in a header file. Not illegal, but if you include it in more than one file (and if you don't, why would you put it in a header?), you will get a single variable defined multiple times, which will give you a link error.
All of this is actually old school C rather than C++ in the modern sense of the word. In other words you are really writing C, but since C is (almost) a subset of C++, you can still use C++ to do this stuff.