Есть ли способ узнать, сколько значений имеет массив? Определение того, достиг ли я конца массива, также будет работать.
Есть ли способ узнать, сколько значений имеет массив? Определение того, достиг ли я конца массива, также будет работать.
Ответы:
Если вы имеете в виду массив в стиле C, то вы можете сделать что-то вроде:
int a[7];
std::cout << "Length of array = " << (sizeof(a)/sizeof(*a)) << std::endl;
Это не работает с указателями (то есть не работает ни для одного из следующих):
int *p = new int[7];
std::cout << "Length of array = " << (sizeof(p)/sizeof(*p)) << std::endl;
или:
void func(int *p)
{
std::cout << "Length of array = " << (sizeof(p)/sizeof(*p)) << std::endl;
}
int a[7];
func(a);
В C ++, если вы хотите такое поведение, тогда вы должны использовать контейнерный класс; вероятно std::vector
.
Как уже говорили другие, вы можете использовать, sizeof(arr)/sizeof(*arr)
но это даст вам неправильный ответ для типов указателей, которые не являются массивами.
template<class T, size_t N>
constexpr size_t size(T (&)[N]) { return N; }
Это имеет приятное свойство не компилироваться для типов, не являющихся массивами (в Visual Studio _countof
это делается). Это constexpr
делает это выражение времени компиляции, поэтому у него нет недостатков по сравнению с макросом (по крайней мере, я не знаю о нем).
Вы также можете рассмотреть возможность использования std::array
из C ++ 11, которая показывает его длину без издержек над собственным массивом C.
C ++ 17 имеет std::size()
в <iterator>
заголовке, который делает то же самое и работает для контейнеров STL (благодаря @Jon C ).
T(arg&)[N]
.
extent
, сейчас я вижу две характеристики, которые делают его менее полезным, чем функция выше (для этого варианта использования). (1) Возвращает ноль для указателей (а не ошибку компиляции). (2) Требуется параметр типа, поэтому, чтобы проверить переменную, которую вы должны сделать,decltype
В результате sizeof( myArray )
вы получите общее количество байтов, выделенных для этого массива. Затем вы можете узнать количество элементов в массиве, разделив на размер одного элемента в массиве:sizeof( myArray[0] )
Хотя это старый вопрос, стоит обновить ответ на C ++ 17. В стандартной библиотеке теперь есть шаблонная функция std::size()
, которая возвращает количество элементов в контейнере std или в массиве в стиле C. Например:
#include <iterator>
uint32_t data[] = {10, 20, 30, 40};
auto dataSize = std::size(data);
// dataSize == 4
Есть ли способ узнать, сколько значений имеет массив?
Да!
Пытаться sizeof(array)/sizeof(array[0])
Определение того, достиг ли я конца массива, также будет работать.
Я не вижу никакого способа для этого, если ваш массив не является массивом символов (то есть строка).
PS: в C ++ всегда пользуюсь std::vector
. Есть несколько встроенных функций и расширенная функциональность.
std::vector
есть метод, size()
который возвращает количество элементов в векторе.
(Да, это насмешливый ответ)
#include <iostream>
int main ()
{
using namespace std;
int arr[] = {2, 7, 1, 111};
auto array_length = end(arr) - begin(arr);
cout << "Length of array: " << array_length << endl;
}
Начиная с C ++ 11, введены некоторые новые шаблоны, которые помогут уменьшить боль при работе с длиной массива. Все они определены в заголовке <type_traits>
.
If T
является типом массива, предоставляет значение константы члена, равное количеству измерений массива. Для любого другого типа значение равно 0.
If T
является типом массива, обеспечивает значение константы члена, равное количеству элементов вдоль N
измерения th массива, если N
находится в [0, std::rank<T>::value
). Для любого другого типа, или если T
это массив с неизвестной границей вдоль его первого измерения и N
равен 0, значение равно 0.
Если T
является массивом некоторого типа X
, обеспечивает член typedef тип, равный X
, в противном случае тип T
. Обратите внимание, что если T
это многомерный массив, удаляется только первое измерение.
std::remove_all_extents<T>::type
Если T
является многомерным массивом некоторого типа X
, обеспечивает член typedef тип, равный X
, в противном случае тип является T
.
Чтобы получить длину в любом измерении многомерного массива, decltype
можно использовать для объединения с std::extent
. Например:
#include <iostream>
#include <type_traits> // std::remove_extent std::remove_all_extents std::rank std::extent
template<class T, size_t N>
constexpr size_t length(T(&)[N]) { return N; }
template<class T, size_t N>
constexpr size_t length2(T(&arr)[N]) { return sizeof(arr) / sizeof(*arr); }
int main()
{
int a[5][4][3]{{{1,2,3}, {4,5,6}}, { }, {{7,8,9}}};
// New way
constexpr auto l1 = std::extent<decltype(a)>::value; // 5
constexpr auto l2 = std::extent<decltype(a), 1>::value; // 4
constexpr auto l3 = std::extent<decltype(a), 2>::value; // 3
constexpr auto l4 = std::extent<decltype(a), 3>::value; // 0
// Mixed way
constexpr auto la = length(a);
//constexpr auto lpa = length(*a); // compile error
//auto lpa = length(*a); // get at runtime
std::remove_extent<decltype(a)>::type pa; // get at compile time
//std::remove_reference<decltype(*a)>::type pa; // same as above
constexpr auto lpa = length(pa);
std::cout << la << ' ' << lpa << '\n';
// Old way
constexpr auto la2 = sizeof(a) / sizeof(*a);
constexpr auto lpa2 = sizeof(*a) / sizeof(**a);
std::cout << la2 << ' ' << lpa2 << '\n';
return 0;
}
BTY, чтобы получить общее количество элементов в многомерном массиве:
constexpr auto l = sizeof(a) / sizeof(std::remove_all_extents<decltype(a)>::type);
Или поместите это в шаблон функции:
#include <iostream>
#include <type_traits>
template<class T>
constexpr size_t len(T &a)
{
return sizeof(a) / sizeof(typename std::remove_all_extents<T>::type);
}
int main()
{
int a[5][4][3]{{{1,2,3}, {4,5,6}}, { }, {{7,8,9}}};
constexpr auto ttt = len(a);
int i;
std::cout << ttt << ' ' << len(i) << '\n';
return 0;
}
Дополнительные примеры их использования можно найти по ссылкам.
Существует также способ TR1 / C ++ 11 / C ++ 17 (см. Его Live on Coliru):
const std::string s[3] = { "1"s, "2"s, "3"s };
constexpr auto n = std::extent< decltype(s) >::value; // From <type_traits>
constexpr auto n2 = std::extent_v< decltype(s) >; // C++17 shorthand
const auto a = std::array{ "1"s, "2"s, "3"s }; // C++17 class template arg deduction -- http://en.cppreference.com/w/cpp/language/class_template_argument_deduction
constexpr auto size = std::tuple_size_v< decltype(a) >;
std::cout << n << " " << n2 << " " << size << "\n"; // Prints 3 3 3
Вместо использования встроенной функции массива aka:
int x[3] = {0, 1, 2};
Вы должны использовать класс массива и шаблон массива. Пытаться:
#include <array>
array<type_of_the_array, number_of_elements_in_the_array> Name_of_Array = {};
Так что теперь, если вы хотите найти длину массива, все, что вам нужно сделать, это использовать функцию размера в классе массива.
Name_of_Array.size();
и это должно вернуть длину элементов в массиве.
В C ++, используя класс std :: array для объявления массива, можно легко найти размер массива, а также последний элемент.
#include<iostream>
#include<array>
int main()
{
std::array<int,3> arr;
//To find the size of the array
std::cout<<arr.size()<<std::endl;
//Accessing the last element
auto it=arr.end();
std::cout<<arr.back()<<"\t"<<arr[arr.size()-1]<<"\t"<<*(--it);
return 0;
}
На самом деле, класс массива имеет множество других функций, которые позволяют использовать массив в стандартном контейнере.
Ссылка 1 на класс C ++ std :: array
Ссылка 2 на класс std :: array
Примеры в ссылках полезны.
Это довольно старый и легендарный вопрос, и там уже есть много удивительных ответов. Но со временем к языкам добавляются новые функции, поэтому мы должны продолжать обновлять их в соответствии с новыми доступными функциями.
Я только заметил, что никто еще не упомянул о C ++ 20. Вот и подумал написать ответ.
В C ++ 20, есть новый лучший способ добавляется к стандартной библиотеке для нахождения длины массива , т.е. std:ssize()
. Эта функция возвращает signed value
.
#include <iostream>
int main() {
int arr[] = {1, 2, 3};
std::cout << std::ssize(arr);
return 0;
}
В C ++ 17 был лучший способ (в то время) для того же, который std::size()
определен в iterator
.
#include <iostream>
#include <iterator> // required for std::size
int main(){
int arr[] = {1, 2, 3};
std::cout << "Size is " << std::size(arr);
return 0;
}
PS Этот метод работает vector
также.
Этот традиционный подход уже упоминался во многих других ответах.
#include <iostream>
int main() {
int array[] = { 1, 2, 3 };
std::cout << sizeof(array) / sizeof(array[0]);
return 0;
}
Просто FYI, если вам интересно, почему этот подход не работает, когда массив передается другой функции . Причина в том,
Массив не передается по значению в C ++, вместо этого передается указатель на массив. Поскольку в некоторых случаях передача целых массивов может быть дорогостоящей операцией. Вы можете проверить это, передав массив в некоторую функцию и внеся в него некоторые изменения, а затем снова напечатайте массив в main. Вы получите обновленные результаты.
И, как вы уже знаете, sizeof()
функция дает число байтов, поэтому в другой функции она возвращает количество байтов, выделенных для указателя, а не для всего массива. Так что этот подход не работает.
Но я уверен, что вы можете найти хороший способ сделать это, согласно вашему требованию.
Удачного кодирования.
У вас есть куча опций, которые будут использоваться для получения размера массива Си.
int myArray [] = {0, 1, 2, 3, 4, 5, 7};
1) sizeof(<array>) / sizeof(<type>):
std::cout << "Size:" << sizeof(myArray) / sizeof(int) << std::endl;
2) sizeof(<array>) / sizeof(*<array>):
std::cout << "Size:" << sizeof(myArray) / sizeof(*myArray) << std::endl;
3) sizeof(<array>) / sizeof(<array>[<element>]):
std::cout << "Size:" << sizeof(myArray) / sizeof(myArray[0]) << std::endl;
Вот одна реализация ArraySize
от Google Protobuf .
#define GOOGLE_ARRAYSIZE(a) \
((sizeof(a) / sizeof(*(a))) / static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
// test codes...
char* ptr[] = { "you", "are", "here" };
int testarr[] = {1, 2, 3, 4};
cout << GOOGLE_ARRAYSIZE(testarr) << endl;
cout << GOOGLE_ARRAYSIZE(ptr) << endl;
ARRAYSIZE (arr) работает путем проверки sizeof (arr) (количество байтов в массиве) и sizeof (* (arr)) (количество байтов в одном элементе массива). Если первое делится на второе, возможно, arr действительно является массивом, и в этом случае результатом деления является число элементов в массиве. В противном случае arr не может быть массивом, и мы генерируем ошибку компилятора, чтобы предотвратить компиляцию кода.
Так как размер bool определяется реализацией, нам нужно привести! (Sizeof (a) & sizeof (* (a))) к size_t, чтобы конечный результат имел тип size_t.
Этот макрос не идеален, так как он ошибочно принимает определенные указатели, а именно, где размер указателя делится на размер указателя. Поскольку весь наш код должен проходить через 32-битный компилятор, где указатель составляет 4 байта, это означает, что все указатели на тип, размер которого равен 3 или больше 4, будут (по праву) отклонены.
int nombres[5] = { 9, 3 };
эта функция возвращает 5
вместо 2
.
Для C ++ / CX (при написании, например, приложений UWP с использованием C ++ в Visual Studio) мы можем найти число значений в массиве, просто используя size()
функцию.
Исходный код:
string myArray[] = { "Example1", "Example2", "Example3", "Example4" };
int size_of_array=size(myArray);
Если вы на выходе будет:cout
size_of_array
>>> 4
sizeof(array_name)
дает размер всего массива и sizeof(int)
дает размер типа данных каждого элемента массива.
Таким образом, деление размера всего массива на размер одного элемента массива дает длину массива.
int array_name[] = {1, 2, 3, 4, 5, 6};
int length = sizeof(array_name)/sizeof(int);
ОТВЕТ :
int number_of_elements = sizeof(array)/sizeof(array[0])
ОБЪЯСНЕНИЕ :
Поскольку компилятор выделяет определенный объем памяти для каждого типа данных, а массив - это просто группа из них, вы просто делите размер массива на размер типа данных. Если у меня есть массив из 30 строк, моя система выделяет 24 байта для каждого элемента (строки) массива. На 30 элементах это всего 720 байтов. 720/24 == 30 элементов. Небольшой, жесткий алгоритм для этого:
int number_of_elements = sizeof(array)/sizeof(array[0])
что соответствует
number_of_elements = 720/24
Обратите внимание, что вам не нужно знать, какой тип данных у массива, даже если это пользовательский тип данных.
Просто подумал, но решил создать переменную счетчика и сохранить размер массива в позиции [0]. Я удалил большую часть кода, который у меня был в функции, но после выхода из цикла вы увидите, что простому [0] присваивается окончательное значение 'a'. Я пытался использовать векторы, но VS Express 2013 не очень понравилось. Также обратите внимание, что «a» начинается с единицы, чтобы избежать перезаписи [0], и инициализируется в начале, чтобы избежать ошибок. Я не эксперт, просто думал, что поделюсь.
int prime[] = {0};
int primes(int x, int y){
using namespace std; int a = 1;
for (int i = x; i <= y; i++){prime[a] = i; a++; }
prime[0] = a; return 0;
}
Хорошее решение, которое использует дженерики:
template <typename T,unsigned S>
inline unsigned arraysize(const T (&v)[S]) { return S; }
Затем просто позвоните, arraysize(_Array);
чтобы получить длину массива.
constexpr
- это исправление. inline
не является. constexpr
довольно современный, хотя Вы уверены, что ваша тестовая программа не использует другую современную функцию, где вы можете объявить локальный массив, длина которого задается переменной? Попробуйте это с двумя глобальными массивами.
Для старого компилятора g ++, вы можете сделать это
template <class T, size_t N>
char (&helper(T (&)[N]))[N];
#define arraysize(array) (sizeof(helper(array)))
int main() {
int a[10];
std::cout << arraysize(a) << std::endl;
return 0;
}
Я предлагаю хитрое решение здесь:
Вы всегда можете хранить length
в первом элементе:
// malloc/new
arr[0] = length;
arr++;
// do anything.
int len = *(arr-1);
free(--arr);
Стоимость вы должны --arr
при вызовеfree
arr
тип совместим с, int
а массив не длиннее максимального значения типа. Например, строки Pascal на самом деле являются байтовыми массивами, использующими этот трюк; максимальная длина строк в Паскале составляет 255 символов.
Вы можете найти длину массива следующим образом:
int arr[] = {1, 2, 3, 4, 5, 6};
int size = *(&arr + 1) - arr;
cout << "Number of elements in arr[] is "<< size;
return 0;
Просто вы можете использовать этот фрагмент:
#include <iostream>
#include <string>
#include <array>
using namespace std;
int main()
{
array<int,3> values;
cout << "No. elements in valuea array: " << values.size() << " elements." << endl;
cout << "sizeof(myints): " << sizeof(values) << endl;
}
и вот ссылка: http://www.cplusplus.com/reference/array/array/size/
Избегайте использования типа вместе с sizeof, так как sizeof(array)/sizeof(char)
внезапно портится, если вы измените тип массива.
В визуальной студии у вас есть эквивалент, если sizeof(array)/sizeof(*array)
. Вы можете просто напечатать_countof(array)
Лично я бы предложил (если по какой-либо причине вы не можете работать со специализированными функциями) сначала расширить совместимость типов массивов за пределы того, что вы обычно используете как (если вы сохраняете значения ≥ 0:
unsigned int x[] -> int x[]
чем вы сделаете элемент массива на 1 больше, чем вам нужно. Для последнего элемента вы бы поместили некоторый тип, который включен в спецификатор расширенного типа, но который вы обычно не используете, например, в предыдущем примере последний элемент будет равен -1. Это позволяет вам (используя цикл for) найти последний элемент массива.
Одна из наиболее распространенных причин, по которой вам придется искать это, заключается в том, что вы хотите передать массив функции, а не передавать другой аргумент для его размера. Вы также хотели бы, чтобы размер массива был динамическим. Этот массив может содержать объекты, а не примитивы, и объекты могут быть сложными, так что size_of () является небезопасной опцией для вычисления количества.
Как уже предлагали другие, рассмотрите возможность использования std :: vector или list и т. Д. Вместо примитивного массива. Однако на старых компиляторах у вас все еще не было бы окончательного решения, которое вы, вероятно, хотели бы сделать, просто делая это, потому что для заполнения контейнера требуется куча уродливых строк push_back (). Если вы похожи на меня, вам нужно однострочное решение с участием анонимных объектов.
Если вы используете контейнер STL, альтернативный примитивному массиву, этот пост SO может пригодиться вам для способов его инициализации: Каков самый простой способ инициализации std :: vector с жестко закодированными элементами?
Вот метод, который я использую для этого, который будет работать универсально на всех компиляторах и платформах:
Создайте структуру или класс в качестве контейнера для вашей коллекции объектов. Определить функцию перегрузки оператора для <<.
class MyObject;
struct MyObjectList
{
std::list<MyObject> objects;
MyObjectList& operator<<( const MyObject o )
{
objects.push_back( o );
return *this;
}
};
Вы можете создавать функции, которые принимают вашу структуру в качестве параметра, например:
someFunc( MyObjectList &objects );
Затем вы можете вызвать эту функцию, например так:
someFunc( MyObjectList() << MyObject(1) << MyObject(2) << MyObject(3) );
Таким образом, вы можете построить и передать динамически измеренную коллекцию объектов в функцию в одну чистую строку!
Допустим, у вас есть глобальный массив, объявленный в верхней части страницы
int global[] = { 1, 2, 3, 4 };
Чтобы узнать, сколько элементов (в c ++) в массиве, введите следующий код:
sizeof(global) / 4;
Sizeof (NAME_OF_ARRAY) / 4 вернет вам количество элементов для данного имени массива.