How to get the number of columns of a char array? - c++

Is there a way to get the number of columns a char array has?
It's declared like this: static const char *countries[][2] = { ... };
But I want to get it dynamically, so without typing '2' myself

No, you have to pass the size along with the array. There might exist system/compiler/library dependent ways, but it's not a good idea to rely on such functionalities.
If you're using the C++ standard library, you'd better use std::vector, which carries more metadata, such as the size() you're interested in.

Sure you may. Statically initialized arrays can be inspected with the sizeof operator easily. The following snippet (in C) prints all sizes that are assoiated to your 2D array of pointers.
#include <stdio.h>
static const char *countries[][2] = { { "dfdf", "dss" }, { "ss"}, { "toto"}};
int main(void) {
printf("dim0 %zu, dim1 %zu, elements %zu\n",
sizeof countries/sizeof countries[0],
sizeof countries[0]/sizeof countries[0][0],
sizeof countries/sizeof countries[0][0]
);
}

Related

Why compiler doesn't pass size of array char *arr[] in parameters?

Why compiler doesn't pass size of array char *arr[] in parameters? I wanted to get get size of array passed by parameter but I guess it doesn't work because even char *a[] is char ** my question is why is it and can I make it work?
#include <stdio.h>
#include <stddef.h>
#include <stdio.h>
template<class T, size_t len>
constexpr size_t lengthof(T(&)[len])
{
return len;
}
void printarr(const char *a[]);
int main()
{
const char *a[] = { "aba", "bd", "cd" };
printarr(a);
}
void printarr(const char *a[])
{
for(size_t i = 0, c = lengthof(a); i < c; i++) {
printf("str = %s\n", a[i]);
}
}
You can make it work by using the same trick you used in your lengthof function template.
template<size_t len>
void printarr(const char* (&a)[len])
{
for(size_t i = 0, c = lengthof(a); i < c; i++) {
printf("str = %s\n", a[i]);
}
}
That has been a feature of C since the beginning and carried through into C++.
In the case of string arrays, the solution has been to add a trailing null character to mark the end.
The was probably done for the sake of efficiency when C started on ancient PDP computers.
Use strlen; or better yet std::string or std::vector.
Because this is required by the C++ standard, which inherited this behavior from C (and since C++ wants to stay compatible with C).
As function parameters, arrays are decayed into pointers.
You really want to use something like std::vector<std::string> instead. Learn more about standard C++ STL containers.
C++ is a language what provides low level access to system resources.
Processor is not working with objects, but with memory addresses.
If you want predefined structures, use Java, C#, python, or c++ libs like stl.
From the point of view of the language, your array doesn't have a length; the compiler cannot read your mind and decide where the array begins and where it ends, and it cannot waste memory and processing to perform range checking.
The closest thing to an array length is the number of consecutive memory spaces that have been allocated by a single new[] invocation, but such information is only authoritative for the purpose of allocating and deallocating memory: the "array" you want to process in your function might be only a portion of a single allocation (for example, you might allocate memory to load a whole text file and process each line separately).

Difference between passing array, fixed-sized array and base address of array as a function parameter

I am confused about which syntax to use if I want to pass an array of known or unknown size as a function parameter.
Suppose I have these variants for the purpose:
void func1(char* str) {
//print str
}
void func2(char str[]) {
//print str
}
void func3(char str[10]) {
//print str
}
What are the pros and cons of using each one of these?
All these variants are the same. C just lets you use alternative spellings but even the last variant explicitly annotated with an array size decays to a normal pointer.
That is, even with the last implementation you could call the function with an array of any size:
void func3(char str[10]) { }
func("test"); // Works.
func("let's try something longer"); // Not a single f*ck given.
Needless to say this should not be used: it might give the user a false sense of security (“oh, this function only accepts an array of length 10 so I don’t need to check the length myself”).
As Henrik said, the correct way in C++ is to use std::string, std::string& or std::string const& (depending on whether you need to modify the object, and whether you want to copy).
Note that in C++, if the length of the array is known at compile time (for example if you passed a string literal), you can actually get its size:
template<unsigned int N>
void func(const char(&str)[N])
{
// Whatever...
}
int main()
{
func("test"); // Works, N is 5
}
In C++, use void func4(const std::string& str).
These are all functionally identical. When you pass an array to a function in C, the array gets implicitly converted to a pointer to the first element of the array. Hence, these three functions will print the same output (that is, the size of a pointer to char).
void func1(char* str) {
printf("sizeof str: %zu\n", sizeof str);
}
void func2(char str[]) {
printf("sizeof str: %zu\n", sizeof str);
}
void func3(char str[10]) {
printf("sizeof str: %zu\n", sizeof str);
}
This conversion only applies to the first dimension of an array. A char[42][13] gets converted to a char (*)[13], not a char **.
void func4(char (*str_array)[13]) {
printf("sizeof str_array: %zu\n"
"sizeof str_array[0]: %zu\n", sizeof str_array, sizeof str_array[0]);
}
char (*)[13] is the type of str_array. It's how you write "a pointer to an array of 13 chars". This could have also been written as void func4(char str_array[42][13]) { ... }, though the 42 is functionally meaningless as you can see by experimenting, passing arrays of different sizes into func4.
In C99 and C11 (but not C89 or C++), you can pass a pointer to an array of varying size into a function, by passing it's size along with it, and including the size identifier in the [square brackets]. For example:
void func5(size_t size, char (*str_array)[size]) {
printf("sizeof str_array: %zu\n"
"sizeof str_array[0]: %zu\n", sizeof str_array, sizeof str_array[0]);
}
This declares a pointer to an array of size chars. Note that you must dereference the pointer before you can access the array. In the example above, sizeof str_array[0] evaluates to the size of the array, not the size of the first element. As an example, to access the 11th element, use (*str_array)[11] or str_array[0][11].
In C, the first two definitions are equivalent.The third one is essentially same but it gives an idea about the size of the array.
If printing str is your intent, then you can safely use any of them.Essentially all three of the functions are passed a parameter of type char*,just what printf() needs to print a string.And lest you don't know, despite what it may seem, all parameter passing in C is done in pass-by-value mode.
Edit: Seems like I'll have to be very rigorous in my choice of words on SO henceforth.Well,in the third case it gives no idea about the size of the array to the function to which it is passed as eventually it is reduced to type char* just as in the first two cases.I meant to say it kinda tells the human reading it that the array's size is 10.Also,it is not wrong/illegal in C.But for the program,doing it is as good as useless.It gives no idea whatsoever about the array size to the function it is passed to.Mr.Downvoter, thanks for pointing out that casual attitude and negligence is not tolerated on SO.
In a one dimensional array they are all treated the same by the compiler. However for a two or more dimensional array, (e.g. myArray[10][10]), it is useful as it can be used to determine the row/column length of an array.
To add-on, describing in points.
1) As everyone told it is same.
2) Arrays are decayed into pointers when they are passed in the function arguments.
3) Fundamental problem could be finding the size of a array in the function. For that we can use macro like.
#define noOfElements(v) sizeof(v)/sizeof(0[v])
int arr[100]
myfunction ( arr, noOfElements(arr))
either 0[v] or v[0] can be used in the macro, where the first is used to avoid user defined data type passed in to noOfElements.
Hope this helps.

getting the length of an array after passing as a char* [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Sizeof an array in the C programming language?
I have code of the following form:
void arrLen(char* array){
// print length
}
int main(){
char bytes[16];
arrLen(bytes);
}
What I need to do is get the length of the underlying array and print it out. The issue is that the array MAY CONTAIN NULL CHARACTERS, and therefore strlen would not work. is there any way to do this, or would I have to pass it as a char[] instead of a char*?
C style arrays do not carry length information with them.
You have several solutions avaliable :
pass the size of your array to your function :
void arrLen(char* array, std::size_t size)
use std::array if you have access to C++ 11 (or TR1 as mentionned in comments)
std::array<char, 16> bytes;
If you don't have access to std::array, you can use boost::array. They are roughly equivalent to the standard one.
Regarding your comment
would I have to pass it as a char[] instead of a char*?
Arrays are always passed to functions as pointers, so void arrLen(char* array) and void arrLen(char[] array) are equivalent.
or would I have to pass it as a char[] instead of a char*?
Changing the declaration of arrLen() to take a parameter of type char[] instead of char* would have no effect, as in this scenario they are equivalent.
A possible solution would be to use a template function:
#include <iostream>
template <typename T, int N>
void array_size(T (&a)[N])
{
std::cout << N << "\n";
}
int main()
{
array_size("hello");
char bytes[16];
array_size(bytes);
return 0;
}
See http://ideone.com/l7GxDp for demo.
Alternatives to using an array:
std::string; these can contain NULL characters:
std::string s("hello\0world", 11);
std::vector<char>
boost::array<char, 16> (available as std::array<char,16> in C++11, or std::tr1::array in most every C++ compiler on the market)
In the traditional way (C) one has to pass the size as an attribute of the function
void arrLen(char* array, int maxSize){
// print length
}
int main(){
char bytes[16];
arrLen(bytes, 16);
}
arrays in C/C++ aren't handled that way per say, you have to manually keep track of the length yourself.. change your function to something like void arrLen(char * array, int size) and specify the size whenever you call the function.
If you have a C++11, may I suggest that you use std::array, it keeps track of it size.
Unfortunately, char[] and char* parameter types are equivalent.
You have two options:
Pass the length along with the pointer like one would in C:
void arrLen(char* array, size_t length)
or use a template:
template<size_t sz>
void arrLen(char (&array)[sz])

problem with sizeof operator

As i want to find array size dynamically in function, i used sizeof operator. But i got some unexpected result.
here is one demo program to show you, what i want to do.
//------------------------------------------------------------------------------------------
#include <iostream>
void getSize(int *S1){
int S_size = sizeof S1/sizeof(int);
std::cout<<"array size(in function):"<<S_size<<std::endl;
}
int main(){
int S[]={1,2,3,2,5,6,25,1,6,21,121,36,1,31,1,31,1,661,6};
getSize(S);
std::cout<<"array size:"<<sizeof S/sizeof(int)<<std::endl;
return 0;
}
//------------------------------------------------------------------------------------------
compilation command : g++ demo1.cc -o demo1 {fedora 12}
output:
array size(in function):2
array size:19
please explain ,why this is happening.
what can be done to solve this problem.
void getSize(int *S1)
When you pass an array to this function, it decays to pointer type, so sizeof operator will return the size of pointer.
However, you define your function as,
template<int N>
void getSize(int (&S1)[N])
{
//N is the size of array
int S_size1 = N;
int S_size2 = sizeof(S1)/sizeof(int); //would be equal to N!!
std::cout<<"array size(in function):"<<S_size1<<std::endl;
std::cout<<"array size(in function):"<<S_size2<<std::endl;
}
int S[]={1,2,3,2,5,6,25,1,6,21,121,36,1,31,1,31,1,661,6};
getSize(S); //same as before
then you can have the size of array, in the function!
See the demonstration yourself here : http://www.ideone.com/iGXNU
Inside getSize(), you're getting size of pointer, which is 8 bytes (since you're probably running 64-bit OS). In main(), you're getting size of array.
If you want to know array size, pass result of sizeof(S) as additional argument to getSize().
More alternatives would be using some container (like std::vector) or turning function into template function, as Nawaz proposed.
S is an int *, a pointer to an integer, which is a memory address, which is on your machine twice the size of an integer.
If you want the size of the array (I.e., the number of elements), you can't get that directly in pure C. But since this is a c++ question, there is a way: use a vector, which has a size() method.
Actually, this isn't quite true: within the function that you declare S (and only if it's explicitly initialized at compile time as you do in your example -- even new int[19] doesn't work), the sizeof operator actually does get the correct answer, which is why c++ allows you to do this:
int S[]={1,2,3,2,5,6,25,1,6,21,121,36,1,31,1,31,1,661,6};
vector<int> v(S, S + sizeof(S) / sizeof(int) );
and then you can use v.size() (see these docs).
The template version by Nawaz elsewhere is another excellent suggestion which forces the compiler into carrying the full information about the construction of the c++ array around (again, note that this is all known at compile time, which is why you can be explicit about the size in the argument).
you are getting the size of the pointer to the array. If you want the size of the array you have to multiply the number of elements by the size of each element.
You will have to pass the size of the array to the function.
Since you are only passing a pointer to the first element in the array, your function has no information on its actual size.
void getSize(int *S1, size_t size)
{
int S_Size = sizeof(*S1) * size;
}
This is redundant though, if you think about it :D
To prevent this type of accidental misuse of sizeof, you can define a function which only works on arrays:
template<class T, int N>
int array_size(T (&)[N]) {
return N;
}
If you use this in your code, you'll see a compiler error when applied to S1, as it is not an array. Plus, it's shorter and a bit more explicit than sizeof array / sizeof array[0] (using the size of the first item means you don't have to repeat the array type).
This also already exists in Boost in a more general form (accepting anything with a size method, such as std::vector).

How do I use member functions of constant arrays in C++?

Here is a simplified version of what I have (not working):
prog.h:
...
const string c_strExample1 = "ex1";
const string c_strExample2 = "ex2";
const string c_astrExamples[] = {c_strExample1, c_strExample2};
...
prog.cpp:
...
int main()
{
int nLength = c_astrExamples.length();
for (int i = 0; i < nLength; i++)
cout << c_astrExamples[i] << "\n";
return 0;
}
...
When I try to build, I get the following error:
error C2228: left of '.length' must have class/struct/union
The error occurs only when I try to use member functions of the c_astrExamples.
If I replace "c_astrExamples.length()" with the number 2, everything appears to work correctly.
I am able to use the member functions of c_strExample1 and c_strExample2, so I think the behavior arises out of some difference between my use of strings vs arrays of strings.
Is my initialization in prog.h wrong? Do I need something special in prog.cpp?
Arrays in C++ don't have member functions. You should use a collection like vector<string> if you want an object, or compute the length like this:
int nLength = sizeof(c_astrExamples)/sizeof(c_astrExamples[0]);
Just use STL vector of strings instead of array:
#include <string>
#include <vector>
using namespace std;
const string c_strExample1 = "ex1";
const string c_strExample2 = "ex2";
vector<string> c_astrExamples;
c_astrExamples.push_back(c_strExample1);
c_astrExamples.push_back(c_strExample2);
int main()
{
int nLength = c_astrExamples.size();
Arrays in C++ are inherited from C, which wasn't object-oriented. So they aren't objects and don't have member functions. (In that they behave like int, float and the other built-in types.) From that ancestry stem more problems with array, like the fact that they easily (e.g., when passed into a function) decay into a pointer to the first element with no size information left.
The usual advice is to use std::vector instead, which is a dynamically resizable array. However, if you the array size is known at compile-time and you need a constant, then boost's array type (boost::array, if your compiler supports the TR1 standard extensions also available as std::tr1::array, to become std::array in the next version of the C++ standard) is what you want.
Edit 1:
A safe way to get the length of an array in C++ involves an incredible combination of templates, function pointers and even a macro thrown into the mix:
template <typename T, std::size_t N>
char (&array_size_helper(T (&)[N]))[N];
#define ARRAY_SIZE(Array_) (sizeof( array_size_helper(Array_) ))
If you (like me) think this is hilarious, look at boost::array.
Edit 2:
As dribeas said in a comment, if you don't need a compile-time constant, this
template <typename T, std::size_t N>
inline std::size_t array_size(T(&)[N])
{return N;}
is sufficient (and much easier to read and understand).
c_astrExamples is an array, there is no "length()" method in it.
In C++ arrays are not objects and have no methods on it. If you need to get the length of the array you could use the following macro
#define COUNTOF( array ) ( sizeof( array )/sizeof( array[0] ) )
int nLength = COUNTOF(c_astrExamples);
Also, beware of initialisation in a header file. You risk offending the linker.
You should have:
prog.h:
extern const string c_strExample1;
extern const string c_strExample2;
extern const string c_astrExamples[];