Как определить размер массива строк в C++?

Я пытаюсь просто распечатать значения, содержащиеся в массиве.

у меня есть массив строк под названием "результат". Я не знаю точно, насколько он велик, потому что он был автоматически сгенерирован.

из того, что я прочитал, вы можете определить размер массива, выполнив следующее:

sizeof(result)/sizeof(result[0])

это правильно? Потому что для моей программы sizeof (result) = 16 и sizeof (result[0]) = 16, чтобы код сказал мне, что мой массив имеет размер 1.

однако это не кажется правильным, потому что, если я вручную распечатаю значения массива следующим образом:

std::cout << result[0] << "n";
std::cout << result[1] << "n";
std::cout << result[2] << "n";
std::cout << result[3] << "n";
etc...

...затем я вижу результирующие значения, которые я ищу. Массив имеет более 100 значений длины/размера.

похоже, что определить размер / длину массива должно быть очень просто... надеюсь, я что-то упустил.

Я немного новичок в C++, поэтому любая помощь будет оценена.

8 ответов


вы не можете определить размер массива динамически в C++. Вы должны передать размер как параметр.

в качестве примечания, используя стандартный контейнер библиотеки (например, вектор) allieviates это.

в своем sizeof например, sizeof(result) запрашивает размер указателя (предположительно, std::string). Это связано с тем, что фактический тип массива "распадается" на тип указателя на элемент при передаче функции (даже если функция объявлена как принимающая массив тип.) The sizeof(result[0]) возвращает размер первого элемента в массиве, который по совпадению тоже 16 байт. Похоже, что указатели-это 16 байт (128 бит) на вашей платформе.

помните, что sizeof is всегда оценивается во время компиляции на C++, никогда во время выполнения.


в качестве бокового комментария есть лучшие способы проверки размера массива (для случаев, когда массив находится в области видимости и не распался на указатель), которые являются typesafe:

// simple: runtime result
template <typename T, std::size_t N>
inline std::size_t sizeof_array( T (&)[N] ) {
   return N;
}

// complex: compile time constant
template <typename T, std::size_t N>
char (&static_sizeof_array( T(&)[N] ))[N];   // declared, not defined
#defined SIZEOF_ARRAY( x ) sizeof(static_sizeof_array(x))

в обоих случаях компилятор обнаружит, если вы попытаетесь передать указатель (динамический массив или распадающийся массив):

void f( int array[] ) { // really: void f( int *array )
{
//   sizeof_array(array);              // compile time error
//   int another[SIZEOF_ARRAY(array)]; // compile time error
}
int main() {
   int array[] = { 1, 2, 3 };
   std::cout << sizeof_array(array) << std::endl; // prints 3
   int another_array[ SIZEOF_ARRAY(array) ];
   std::cout << sizeof_array(another_array) << std::endl; // 3 again
}

Если у вас есть" реальный " массив, то работает трюк sizeof(x)/sizeof(x[0]). Если, однако, то, что у вас есть, действительно указатель (например, что-то возвращается из функции), тогда этот трюк не работает-вы в конечном итоге разделите размер указателя на размер указателя. Они!--1-->are указатели на разные типы, но в типичной системе все указатели имеют одинаковый размер, поэтому вы получите один. Даже если указатели имеют разные размеры, результат все равно не будет иметь все, что связано с тем, сколько у тебя струн.


лучше использовать std::vector<std::string> вместо необработанного массива. Тогда вам не нужно вручную управлять памятью массивов, и вы можете использовать size() способ если вы хотите знать количество элементов.

Если вы используете динамически выделенный необработанный массив, вы должны отслеживать его размер самостоятельно, размер не может быть получен из массива. Лучше сохранить его в дополнительной переменной.


sizeof(array)/sizeof (element) работает для массива фиксированной длины массивов фиксированной длины (не указателей). В качестве массива строк мы чаще всего используем массив(фиксированной длины)указателей на различные (фиксированные)строки длины, поэтому этот трюк не сработает. sizeof() используется для объектов, размер которых известен во время компиляции. Он неприменим к динамически распределенным данным.

когда объект содержит указатели как и в случае массива строк, sizeof () возвращает размер структура самого высокого уровня (фиксированного размера). Часто это просто размер одного указателя. Он не включает размер выделенных данных, на которые указывают указатели. Поскольку эти данные на самом деле не являются частью основного объекта, это действительно один или несколько отдельных объектов (у нас есть агрегация здесь вместо композиции, см. http://en.wikipedia.org/wiki/Object_composition).

в C++ использование векторов очень удобно для ваших нужд. Другие подходящие стандартные контейнеры тоже можно использовать. методы length() и size() являются синонимами, см. http://www.cplusplus.com/reference/string/string/size/)

пример использования векторного массива:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main()
{
    string s = "01234";
    cout << "s[" << s.length() << "]=\"" << s << "\"" << endl; 
    cout << "sizeof(s)=" << sizeof(s) << " (implementation dependent)" << endl;
    cout << endl;

    s += "56789012345";
    cout << "s[" << s.length() << "]=\"" << s << "\"" << endl; 
    cout << "sizeof(s)=" << sizeof(s) << " (implementation dependent)" << endl;
    cout << endl;

    vector<string>vs={"12","23","345","456","567","67888","7899999999","8","9876543210"};

    cout << "vs[" << vs.size() << "]={";
    size_t sz=0;
    for (size_t index=0; index<vs.size(); index++)
    {
        sz+=vs[index].size();
        if (index>0)
            cout << ",";
        cout << "\"" << vs[index] << "\":" << vs[index].size();
    }
    cout << "}:" << sz << endl;
    cout << "sizeof(vs)=" << sizeof(vs) << " (implementation dependent)" << endl;

    return 0;
}

результат:

s[5]="01234"
sizeof(s)=8 (implementation dependent)

s[16]="0123456789012345"
sizeof(s)=8 (implementation dependent)

vs[9]={"12":2,"23":2,"345":3,"456":3,"567":3,"67888":5,"7899999999":10,"8":1,"9876543210":10}:39
sizeof(vs)=24 (implementation dependent)

template< class T, size_t N >
std::size_t Length(const T(&)[N])
{
    return N;
};

std::cout << Length(another_array) << std::endl;

в векторной строке используйте метод size ()


что-то, что нужно знать: текст может быть представлен различными методами. Массив текста также может быть представлен различными методами.

массив указателей на строки C-стиля

общим методом является наличие массива указателей на char. Вопрос в том, что размер массива не представляет размер всего текста. Кроме того, необходимо также установить право собственности на данные или указатель, поскольку текст может быть удален (и может ли вызываемый удалить текст или звонящий?). Поскольку это массив, размер массива должен всегда сопровождать массив во всех параметрах (если массив не всегда фиксированный размер).

массив char - упакованный текст

другой метод-передать массив char и имеют строки, смежные в массиве. Одна строка следует за завершающим символом предыдущей. В этом массиве представлен общий размер всех строк, нет пустого места. Опять же, с массивами размер массива должен сопровождать массив при передаче.

массив std::string

в C++, текст может быть представлен с помощью std::string. В этом случае массив представляет количество строк (аналогично массиву C-строк выше). Чтобы получить общий размер всех строк, необходимо суммировать размер каждой отдельной строки. Поскольку это массив, размер массива должен быть передан также.

резюме

во время выполнения размеры массива должны сопровождать массив, когда массив передается. sizeof обрабатывается только во время компиляции. Более простая структура std::vector, который обрабатывает размер и выделение памяти динамически.