c++ - tamaño - ¿Cómo encuentro la longitud de una matriz?
vectores en c (22)
¿Hay una manera de encontrar cuántos valores tiene una matriz? Detectar si he llegado o no al final de una matriz también funcionaría.
¿Hay una manera de encontrar cuántos valores tiene una matriz?
¡Sí!
Prueba sizeof(array)/sizeof(array[0])
Detectar si he llegado o no al final de una matriz también funcionaría.
No veo ninguna forma para esto a menos que su matriz sea una matriz de caracteres (es decir, una cadena).
PS: En C ++ siempre usa std::vector
. Hay varias funciones incorporadas y una funcionalidad extendida.
Al hacer sizeof( myArray )
obtendrá el número total de bytes asignados para esa matriz. Luego, puede averiguar el número de elementos en la matriz dividiendo por el tamaño de un elemento en la matriz: sizeof( myArray[0] )
Aquí hay una implementación de ArraySize
de 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) funciona inspeccionando sizeof (arr) (el número de bytes en la matriz) y sizeof (* (arr)) (el número de bytes en un elemento de la matriz). Si lo primero es divisible entre lo segundo, quizás arr sea de hecho una matriz, en cuyo caso el resultado de la división es el número de elementos en la matriz. De lo contrario, arr no puede ser una matriz, y generamos un error de compilación para evitar que el código se compile.
Dado que el tamaño de bool está definido por la implementación, debemos convertir (sizeof (a) & sizeof (* (a))) a size_t para garantizar que el resultado final tenga el tipo size_t.
Esta macro no es perfecta, ya que acepta erróneamente ciertos punteros, es decir, donde el tamaño del puntero es divisible por el tamaño del pointee. Dado que todo nuestro código tiene que pasar por un compilador de 32 bits, donde un puntero es de 4 bytes, esto significa que todos los punteros a un tipo cuyo tamaño es 3 o mayor que 4 serán rechazados (correctamente).
Como han dicho otros, puede usar sizeof(arr)/sizeof(*arr)
pero esto le dará una respuesta incorrecta para los tipos de punteros que no son matrices.
template<class T, size_t N>
constexpr size_t size(T (&)[N]) { return N; }
Esto tiene la agradable propiedad de no compilar para tipos que no sean de matriz (Visual Studio tiene _countof
que hace esto). El constexpr
hace que esta sea una expresión de tiempo de compilación por lo que no tiene ningún inconveniente en la macro (al menos ninguno que yo sepa).
También puede considerar el uso de std::array
de C ++ 11, que expone su longitud sin sobrecarga sobre una matriz C nativa.
C ++ 17 tiene std::size()
en el encabezado <iterator>
que hace lo mismo y también funciona para contenedores STL (gracias a @Jon C ).
Desde C ++ 11, se introducen algunas plantillas nuevas para ayudar a reducir el dolor al tratar con la longitud de la matriz. Todos ellos están definidos en el encabezado <type_traits>
.
-
Si
T
es un tipo de matriz, proporciona el valor constante del miembro igual al número de dimensiones de la matriz. Para cualquier otro tipo, el valor es 0. -
Si
T
es un tipo de matriz, proporciona el valor constante del miembro igual al número de elementos a lo largo de la dimensiónN
th de la matriz, siN
está en [0,std::rank<T>::value
). Para cualquier otro tipo, o siT
es una matriz de límite desconocido a lo largo de su primera dimensión yN
es 0, el valor es 0. -
Si
T
es una matriz de algún tipoX
, proporciona el tipo typedef miembro igual aX
, de lo contrario, el tipo esT
Tenga en cuenta que siT
es una matriz multidimensional, solo se elimina la primera dimensión. std::remove_all_extents<T>::type
Si
T
es una matriz multidimensional de algún tipoX
, proporciona el tipo typedef miembro igual aX
, de lo contrario, el tipo esT
Para obtener la longitud en cualquier dimensión de una matriz multidimensional, se podría usar decltype
para combinar con std::extent
. Por ejemplo:
#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, para obtener el número total de elementos en una matriz multidimensional:
constexpr auto l = sizeof(a) / sizeof(std::remove_all_extents<decltype(a)>::type);
O ponlo en una plantilla de función:
#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;
}
Se pueden encontrar más ejemplos de cómo usarlos siguiendo los enlaces.
Digamos que tienes una matriz global declarada en la parte superior de la página
int global[] = { 1, 2, 3, 4 };
Para averiguar cuántos elementos hay (en c ++) en la matriz, escriba el siguiente código:
sizeof(global) / 4;
El tamaño de (NAME_OF_ARRAY) / 4 le devolverá el número de elementos para el nombre del arreglo dado.
En C ++, al usar la clase std :: array para declarar una matriz, se puede encontrar fácilmente el tamaño de una matriz y también el último elemento.
#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;
}
De hecho, la clase array tiene muchas otras funciones que nos permiten usar un contenedor estándar.
Referencia 1 a C ++ std :: array class
Referencia 2 a std :: array class
Los ejemplos en las referencias son útiles.
En lugar de utilizar la función de matriz integrada aka:
int x[2] = {0,1,2};
debe utilizar la clase de matriz y la plantilla de matriz. Tratar:
#include <array>
array<type_of_the_array, number_of_elements_in_the_array> Name_of_Array = {};
así que ahora, si desea encontrar la longitud de la matriz, todo lo que tiene que hacer es usar la función de tamaño en la clase de matriz.
Name_of_Array.size();
y eso debería devolver la longitud de los elementos de la matriz.
Evite usar el tipo junto con sizeof, ya que sizeof(array)/sizeof(char)
, de repente se corrompe si cambia el tipo de array.
En Visual Studio, tiene el equivalente if sizeof(array)/sizeof(*array)
. Simplemente puede escribir _countof(array)
Para C ++ / CX (al escribir, por ejemplo, aplicaciones UWP que usan C ++ en Visual Studio) podemos encontrar el número de valores en una matriz simplemente usando la función size()
.
Código fuente:
string myArray[] = { "Example1", "Example2", "Example3", "Example4" };
int size_of_array=size(myArray);
Si cout
the size_of_array
la salida será:
>>> 4
Para el viejo compilador g ++, puedes hacer esto
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;
}
Personalmente sugeriría (si no puede trabajar con funciones especializadas por cualquier motivo) que primero expanda la compatibilidad de tipos de arreglos más allá de lo que normalmente usaría como (si almacenara valores ≥ 0:
unsigned int x[] -> int x[]
de lo que haría que la matriz 1 elemento sea más grande de lo que necesita para hacerlo. Para el último elemento, pondría algún tipo que esté incluido en el especificador de tipo expandido pero que normalmente no usaría, por ejemplo, utilizando el ejemplo anterior, el último elemento sería -1. Esto le permite (utilizando un bucle for) encontrar el último elemento de una matriz.
Proporciono una solución difícil aquí:
Siempre se puede almacenar la length
en el primer elemento:
// malloc/new
arr[0] = length;
arr++;
// do anything.
int len = *(arr-1);
free(--arr);
El costo es que debes --arr
cuando se invoca free
Si bien esta es una pregunta antigua, vale la pena actualizar la respuesta a C ++ 17. En la biblioteca estándar ahora existe la función con plantilla std::size()
, que devuelve el número de elementos en un contenedor estándar o en una matriz de estilo C. Por ejemplo:
#include <iterator>
uint32_t data[] = {10, 20, 30, 40};
auto dataSize = std::size(data);
// dataSize == 4
Si te refieres a una matriz de estilo C, entonces puedes hacer algo como:
int a[7];
std::cout << "Length of array = " << (sizeof(a)/sizeof(*a)) << std::endl;
Sin embargo, esto no funciona en los punteros, es decir , no funcionará para ninguno de los siguientes:
int *p = new int[7];
std::cout << "Length of array = " << (sizeof(p)/sizeof(*p)) << std::endl;
o:
void func(int *p)
{
std::cout << "Length of array = " << (sizeof(p)/sizeof(*p)) << std::endl;
}
int a[7];
func(a);
En C ++, si desea este tipo de comportamiento, entonces debería usar una clase contenedora; probablemente std::vector
.
Solo un pensamiento, pero solo decidí crear una variable de contador y almacenar el tamaño del arreglo en la posición [0]. Eliminé la mayor parte del código que tenía en la función, pero lo verá después de salir del bucle, a Prime [0] se le asigna el valor final de ''a''. Intenté usar vectores, pero a VS Express 2013 no le gustó mucho. También tenga en cuenta que ''a'' comienza en uno para evitar sobrescribir [0] y se inicializa al principio para evitar errores. No soy un experto, solo pensé en compartirlo.
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;
}
También está la forma TR1 / C ++ 11 / C ++ 17 (verlo en vivo en 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
Una buena solución que utiliza genéricos:
template <typename T,unsigned S>
inline unsigned arraysize(const T (&v)[S]) { return S; }
Luego simplemente llame a arraysize(_Array);
para obtener la longitud de la matriz.
Una de las razones más comunes por las que terminaría buscando esto es porque desea pasar una matriz a una función y no tener que pasar otro argumento para su tamaño. En general, también le gustaría que el tamaño de la matriz sea dinámico. Esa matriz puede contener objetos, no primitivos, y los objetos pueden ser complejos, por lo que size_of () no es una opción segura para calcular el recuento.
Como otros han sugerido, considere usar un std :: vector o lista, etc. en lugar de una matriz primitiva. Sin embargo, en los compiladores antiguos, todavía no tendrías la solución final que probablemente deseas haciendo simplemente eso, porque llenar el contenedor requiere un montón de líneas push_back () feas. Si eres como yo, quieres una solución de una sola línea con objetos anónimos involucrados.
Si opta por un contenedor STL alternativo a una matriz primitiva, esta publicación SO puede serle útil para iniciar el proceso: ¿Cuál es la forma más fácil de inicializar un std :: vector con elementos codificados?
Aquí hay un método que estoy usando para esto que funcionará universalmente en compiladores y plataformas:
Cree una estructura o clase como contenedor para su colección de objetos. Defina una función de sobrecarga del operador para <<.
class MyObject;
struct MyObjectList
{
std::list<MyObject> objects;
MyObjectList& operator<<( const MyObject o )
{
objects.push_back( o );
return *this;
}
};
Puede crear funciones que tomen su estructura como un parámetro, por ejemplo:
someFunc( MyObjectList &objects );
Entonces, puedes llamar a esa función, así:
someFunc( MyObjectList() << MyObject(1) << MyObject(2) << MyObject(3) );
De esa manera, puede crear y pasar una colección de objetos de tamaño dinámico a una función en una sola línea limpia.
std::vector
tiene un size()
método size()
que devuelve el número de elementos en el vector.
(Sí, esta es la respuesta irónica)
length = sizeof(array_name)/sizeof(int);
#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;
}