Finding the size of an array of strings in C++
Asked Answered
M

12

26

So I have an array of strings. Here's an example:

std::string array[] = {"Example", "Example2", "Example3"};

Is there any way I can find the number of elements in an array like the one above. I can't use this method:

int numberofelements = sizeof(array)/sizeof(array[0]);

This is because the size of the elements vary. Is there another way?

Madore answered 13/1, 2013 at 22:29 Comment(8)
The method you wrote works just find, numberoflemenets would contain 3. The reason is that the size of each array element is the same, it is the size of a the string class (which doesn't contain the string itself, but only points to it).Eau
Use a std::vector, or a std::array if your compiler supports it.Boulder
How do you define "size of a String array"? What answer do you expect in your example?Lester
Do you mean add up the amount of memory used by all the strings? So 8 + 9 + 9 characters? Or something else?Boulder
What if I was using C-Strings? Would the method still work?Madore
sizeof(array)/sizeof(string) works for me.Rumanian
@Madore yes it will also work with C-StringsMerriment
@Madore you can check en.cppreference.com/w/cpp/iterator/sizeMerriment
R
49

Given your array of strings, you can most certainly use sizeof(array)/sizeof(array[0]) to get its size and the following program works just fine:

int main()
{
    std::string array[] = { "S1", "S2", "S3" };
    std::cout << "A number of elements in array is: "
              << sizeof(array)/sizeof(array[0]) << '\n';
    foo(array);
}

It is not clear what do you mean by saying that size of elements vary. Size of the elements of any array is always known at compiler-time, no exceptions.

There are, however, situations where the above will not work. Consider the following example:

void foo(std::string array[])
{
    std::cout << "A number of elements in array is: "
              << sizeof(array)/sizeof(array[0]) << '\n';
}

The above code is doomed to fail. It might look a bit weird at first, but the reason for this is actually very simple — this is called array decaying. It means that every time you pass an array to a function, its type is automatically decayed to that of a pointer. So the above function is in fact an equivalent of this:

void foo(std::string *array)
{
}

And if in the first example the sizeof operator returns the total size of an array, in the second example it returns the size of a pointer to that array, which is a totally different thing.

There are usually two ways people go about it. The first is to add a special “last” element of the array so that application can traverse the array until it sees the last element and calculate the array’s length. String literals are the perfect example of this — every string literal ends with ‘\0’ and you can always calculate its length. Here is an example:

static void foo(const std::string *array)
{
    size_t i = 0;
    while (!array[i].empty())
        ++i;
    std::cout << "Array length is: " << i << std::endl;
}

The downside is obviously a need to traverse the array to determine its length. The second way it to always carry array length around, for example:

static void foo(const std::string *array, size_t length)
{
    // ...
}

void bar()
{
    std::string array[] = { "S1", "S2", "S3" };
    foo(array, sizeof(array)/sizeof(array[0]));
}

In C++, you can use a template to deduct array’s length, for example:

template <size_t array_length>
static void foo(const std::string (&array)[array_length])
{
    std::cout << "A number of elements in template array is: "
              << array_length << '\n';
}

All of the above applies to simple arrays that are built-in into the language. C++, on the other hand, provides a rich set of higher-level containers that give you a lot of flexibility. So you might want to consider using one of the containers that are available to you as part of C++ Standard Library. For a list of standard containers, see — http://en.cppreference.com/w/cpp/container

Hope it helps. Good Luck!

Rivy answered 13/1, 2013 at 23:20 Comment(3)
@user405725: str.empty returns 1 if str = "", so in your array-traversal code, the loop prematurely exits if any element is "", e.g. string array[] = {"Example", "", "Example3"};Nicholson
@Rivy :"It is not clear what do you mean by saying that size of elements vary" .I think he is trying to say that the length of each string in the array is different. eg : {"ab","abc","abcd"} these have lengths {1,2,3}Meed
Great answer, but I think the answerer got confused when he/she wrote this part: "String literals are the perfect example of this — every string literal ends with ‘\0’ and you can always calculate its length" - The answerer is thinking about "array of char", but the OP(and even this answerer) is talking about "array of string". Also, Gnubie's above comment is correct(I have no idea why the answerer wrote that example, maybe he/she was quite sleepy), and ChandraShekhar's comment should be right.Hex
C
7

You could use a template function to achieved that :

#include<cstdlib>

template<class T, std::size_t n>
constexpr std::size_t size(T (&)[n])
{ return n; }

And like Luchian Grigore said, you should use STL containors. std::array if you want equivalent to static C array.

Cornute answered 13/1, 2013 at 22:36 Comment(3)
@Vlad Lazarenko : You prefer Standard Library ? While, manual of sgi STL include containor (so std::array), I think STL is adapted to containors (like std::array). But, I don't think using "STL" or "Standard Library" is really important here (isn't the main subject, and use one or other don't disturb understanding).Cornute
@FlorianBlanchet: Here is a good detailed explanation of why confusing the STL term is bad — https://mcmap.net/q/73791/-what-39-s-the-difference-between-quot-stl-quot-and-quot-c-standard-library-quotRivy
@Vlad Lazarenko : I know that, but except when it's really matter, I use one or other to the same meaning (I am in the For "STL" school of our linked post). Note that even committee use STL in some (recent) paper (not in standard), I pretty sure they refer to original STL extend with similar concept of C++11 (ie containors, algorithms and iterators of all C++11). It includes Stepanov ...Cornute
P
6

We can find the number of elements of an array by simply using the size() function.

Example Code:

string exampleArray[] = { "Example", "Example2", "Example3" };
    int size_of_array = size(exampleArray);

cout << "Number of elements in array = " << size_of_array << endl;

Output:

>>> Number of elements in array = 3

Hope it helps you.

Pleo answered 6/6, 2017 at 18:52 Comment(5)
what's wrong with this can you mention the reason plz?Pleo
What does it has to do with Visual Studio? And this also produces the incorrect result, doesn't it?Unveiling
it find the size of arrayPleo
@Unveiling it's working.I upload screenshot you can check in the answer.Pleo
@Unveiling it's ok.I'm not sure about that it work on both .i'm on 64bitPleo
A
5

You can still use

int numberofelements = sizeof(array)/sizeof(array[0]);

This is because sizeof(array) will return the sum of sizes of pointers corresponding to each string. sizeof(array[0]) will return the size of the pointer corresponding to the first string. Thus, sizeof(array)/sizeof(array[0]) returns the number of strings.

Amendatory answered 8/12, 2014 at 10:28 Comment(0)
P
4

There is standart function in stdlib library:

#include <stdlib.h>
static const char * const strings[] = {"str1", "str2", "str3"};
const int stringCount = _countof(strings);
Pilocarpine answered 26/8, 2014 at 14:58 Comment(1)
Visual C++ supports this built-in macro called _countof to detect invalid inputs at compilation time but this solution is not standard. if you are building C++11, then this will not workTeryl
A
2

Mandatory advice: use std::vector<std::string>.

A function like this can help:

template<typename T, int sz>
int getSize(T (&) [sz])
{
    return sz;
}

Your method also works because the size of the elements don't vary - a std::string has constant size, regardless of the actual string it holds.

Adis answered 13/1, 2013 at 22:33 Comment(0)
I
1

Is this what you're looking for?

string array[] = {"Example", "Example2", "Example3"};
int num_chars = 0;
int num_strings = sizeof(array)/sizeof(array[0]);
for (int i = 0; i < num_strings; i++) {
    num_chars += array[i].size();
}
Invincible answered 13/1, 2013 at 22:32 Comment(0)
T
1

Here is a different example:

string array[] = {"Example", "Example2", "Example3"};
int numberofelements = 0; for(auto c: array) { numberofelements++; };
// now numberofelements will contain 3
Teryl answered 22/2, 2017 at 14:6 Comment(0)
B
0
string s[] = {"apple","banana","cherry","berry","kiwi"};
int size = *(&s+1)-s;  
// OR
int size = sizeof(s)/sizeof(s[0]);

for more info regarding the first one: https://aticleworld.com/how-to-find-sizeof-array-in-cc-without-using-sizeof/

Berryman answered 20/7, 2018 at 8:25 Comment(0)
S
0

no one actually counts duplicates so:

int count_duplicated(string cities[], size_t length) {
    string **cities_copy = new string *[length];
    for (size_t j = 0; j < length; j++)
        cities_copy[j] = &cities[j];

    string bom = "#";
    int counter = 0;
    for (size_t j = 0; j < length; j++) {
        string city = cities[j];
        bool is_duplicated = false;


        for (size_t k = j+1; k < length; k++) {
            if (city == *cities_copy[k]) {
                is_duplicated = true;
                cities_copy[k] = &bom;
            }
        }
        if (is_duplicated)
            counter++;
    }
    delete[] cities_copy;
    return counter;
}
Splat answered 9/11, 2020 at 13:6 Comment(0)
S
-1

I test this code and it's work fine:

string as[] = {"kayak","deified","rotator","repaper","deed","peep","wow","noon"};

int asize = as->length();
Stemware answered 22/9, 2022 at 6:15 Comment(4)
This is wrong. as->length() will only give you the length of the first string kayak. Better use std::vector or std::array in c++11Merriment
Thank you for your remark, you are right and unfortunately this two methods give same results. int asize = as->size(); cout << "asize=" << asize << endl; asize = as->length(); cout << "asize=" << asize << endl;Stemware
Not sure if you got me right, but the reason as->length() and as->size() are giving you the same values, because they are giving you the count of letters in the first string kayak. en.cppreference.com/w/cpp/string/basic_string/size. To get the number of elements in the C-type array you have to use sizeof(as)/sizeof(as[0]), which should give you 8 as OP has mentionedMerriment
However better way is https://mcmap.net/q/513901/-finding-the-size-of-an-array-of-strings-in-c en.cppreference.com/w/cpp/iterator/sizeMerriment
P
-1

NOTE: sizeof(array) will no longer return the full size of the array in Windows, but only the size of the pointer. The standard libraries in Windows have quietly changed this to allow for use of their additional libraries such as std:array and std::iterator. You will need to use the functions from these libraries or create your own methods to count the elements. This is a sample for those that cannot use std::array or std::iterator due to library conflicts or other reasons.

size_t SizeOfArray(std::string* inComing)
{
  size_t outGoing = 0;
  bool end = false;
  // Validate Array
  if (inComing != NULL)
  {
    // Appended arrays can be valid or not. Sometimes earlier cleanup
    // will link to an empty array location, so check for empty and invalid. 
    while ((!end) && (inComing[outGoing].size() != 0))
    {
      __try
      {
        // if an appended memory location has value, but is not an array
        // you look for the NULL character. For wstrings change '\0' to L'\0'.
        // If the memory location is not valid, it will throw the exception.
        if (inComing[outGoing].c_str()[inComing[outGoing].length()] != '\0')
        {
          // End of array -  if nice empty value
          end = true;
        }
        else
        {
          outGoing++; // Count each valid string in the array
        }
      }
      // This is the blank exception catch to an extra element that is not
      // valid.
      __except (EXCEPTION_EXECUTE_HANDLER)
      {
      // End of array -  if unknown value
      end = true;
      }
    }
  }
  return outGoing; // Return the count
}
Priestess answered 20/2, 2023 at 0:40 Comment(7)
Just blindly trying to interpret memory as string class instances is fragile at best. Don't do this.Lorenlorena
Klaus; - Just saying "Don't do it" doesn't provide any useful information and is just trolling. As I mentioned in the start. Microsoft has replaced the use of a core method "sizeof()". If you have a better method, I am willing to listen and would love to learn. Without the core method, then you either need to build your own array class with allocation handlers and size details, use the other standard libraries such as "SafeArray", "vector", "list" etc, or do this. I agree it is not safe, but it solves the problem.Priestess
Why do you believe Microsoft changed the meaning of the sizeofoperator? You simply cannot find the length of an array if the only thing you have is a pointer.Lorenlorena
You used to be able to do this. I have older code from VS version 6 that still functions using sizeof() to find the full size of the array. You had to do this in a lot of low-level apis, so I wasn't just me, look to the code above.Priestess
Now, using VS2019 version 16.11.15 and any and using SDK libraries 10.0.14393.0 -> onward just build a small test that builds a std::wstring* array. Add as many elements as you like. I did it with a unit test that added and removed items from the array. When trying to use the old standard method of "sizeof(array)/sizeof(array[0])", It fails because the sizeof(*) returns the size of the pointer, not the entire memory allocation for the pointer array.Priestess
Regardless of how large or small I make a string, sizeof() returns the size OF THE POINTER, and .size() and .length() return the number of characters in the strings. That is not correct behavior. However, for Microsoft to start making "safe" methods and libraries, they needed to make changes to the core libraries. Looks like this was an unforeseen by product. You will never find this if you are using SafeArray, Vector, List, etc.Priestess
sizeof(whatever*) will always be the size of the pointer. Maybe you confuse it with anytype array[20] where sizeof(array)/sizeof(array[0]) is the number of elements in the array? There is no way to derive the number of array elements if you only have a pointer.Lorenlorena

© 2022 - 2024 — McMap. All rights reserved.