2009-03-25 2 views
2

Я должен использовать динамический массив длины в моей программе и хочу иметь возможность получить количество объектов в нем в разных точках моего кода. Я не знаком с C++, но вот что у меня есть. Почему это не дает мне правильную длину? Благодарю.Int Array Length C++

<#include <iostream> 
Using Namespace std; 
int length(int*); 


void main() 
{ 
    int temp[0]; 
    temp[0] = 7; 
    temp [1] = 10; 
    temp[2] = '\0'; 

    cout << length(temp) << endl; 
} 

int length(int* temp) 
{ 
    int i = 0; 
    int count = 0; 

    while (*temp + i != '\0') 
    { 
      count++; 
      i++; 
    } 
    return count; 
} 

В настоящее время он просто переходит в бесконечную петлю; _;

+1

Это не должно быть скомпилирован; вы не можете иметь массивы с длиной 0. Какой компилятор вы используете? –

ответ

4

Вы можете попробовать:

while (*(temp + i) != '\0') 

Ваше текущее решение расчета temp[0] + i (равно 7+i), который, по-видимому, не то, что вы хотите.

15

В C++ массивы не являются динамическими. Ваш массив temp имеет нулевую длину, и попытка написать членам за пределами его длины - неопределенное поведение. Скорее всего, он не работает, так как он будет писать какую-то часть стека.

Либо создайте массив фиксированного размера с достаточным пространством, чтобы разместить все, что вы хотите в нем, или используйте std::vector<int>, который представляет собой динамическую структуру данных.

#include <iostream> 
#include <vector> 
using namespace std; 
int length(int*); 


int main() // error: ‘::main’ must return ‘int’ 
{ 
    int temp[3]; 
    temp[0] = 7; 
    temp[1] = 10; 
    // don't use char constants for int values without reason 
    temp[2] = 0; 

    cout << length(temp) << endl; 

    vector<int> vec_temp; 

    vec_temp.push_back(7); 
    vec_temp.push_back(10); 

    cout << vec_temp.size() << endl; 

} 

int length(int* temp) 
{ 
    int i = 0; 
    int count = 0; 

    while (*(temp + i) != 0) // *temp + i == (*temp) + i 
    { 
      count++; 
      i++; // don't really need both i and count 
    } 
    return count; 
} 

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

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

int length(int* temp) 
{ 
    int count = 0; 

    while (*temp != 0) 
    { 
      ++count; 
      ++temp; 
    } 

    return count; 
} 

или с использованием счета для индекса температуры:

int length(int* temp) 
{ 
    int count = 0; 

    while (temp[count] != 0) 
      ++count; 

    return count; 
} 
0

Чтобы получить динамическую поведение в массивах, используйте std::vector или упасть назад на старом школу гр стиля с использованием int * с ручным распределением памяти (new и delete) [*]

[*] реализации C (обсуждается в контексте характера массивов s C dynamic string length) использовали malloc, realloc и free, но их следует избегать в коде C++.

+0

Почему он хотел бы использовать malloc & realloc (и предположительно бесплатно) вместо нового и удалить? – 2009-03-25 23:00:24

+0

@Neil: Хорошая точка. Я думал о. Но если он делает это C++-стиль, редко бывает выбор для выбора подхода int * по std :: vector ... – dmckee

5

Этот подход является плохой идеей для нескольких причин, но первый здесь некоторые проблемы:

int temp[0]; 

Это массив из 0 пунктов, которые я даже не думаю, разрешено для элементов стека. При объявлении массива, подобного этому, вы должны указать максимальное количество значений, которое вы когда-либо использовали: например. int temp[10];

Это очень важно! - если вы указали меньшее число (например, [10], а вы используете [11]), то вы вызовете перезапись памяти, которая в лучшем случае сработает и в худшем случае вызовет странные ошибки, которые являются кошмаром для отслеживания.

Следующая проблема эта линия:

while (*temp + i != '\0') 

, что эта линия делает принимает значение сохраняет в адрес, указанный в «Темп» и добавить I. Что вы хотите, чтобы получить значение в п-й элемент адреса, указанного в температуре, например, так:

while (*(temp + i) != '\0') 

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

Причины я уже говорил, что это плохая идея, являются:

  • Вам нужно перебирать весь любое массива вы требуете его длина
  • Вы не можете хранить согласующий элемент (в данном случае 0) в массив

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

Стандартная библиотека C++ поставляется с классом шаблонов с именем «вектор», который может быть использован для этой цели. Это не совсем то же самое, что массив (вы должны добавлять элементы перед индексированием), но это очень похоже. Он также обеспечивает поддержку копирования/изменения размера, что тоже удобно.

Вот ваша программа, написанная для использования std :: vector. Вместо функции «длины» Я добавил что-то напечатать значения:

#include <vector> 
#include <iostream> 

void print(std::vector<int> const& vec) 
{ 
    using namespace std; 

    for (size_t i = 0; i < vec.size(); i++) 
    { 
     cout << vec[i] << " "; 
    } 

    cout << endl; 
} 

int main() 
{ 
    std::vector<int> temp; 
    temp.push_back(7); 
    temp.push_back(10); 

    print(temp); 

    return 0; 
} 
+0

'int temp [0]' разрешено. Это просто требует наличия действительного адреса для массива, а не того, что он на самом деле указывает на что-либо. – greyfade

3

не только C++ массивы не являются динамическими, как Пит указывает, но только строки (символ *) завершаются «\ 0» , (Это не означает, что вы не можете использовать аналогичное соглашение для других типов, но это довольно необычно и по уважительным причинам: в частности, полагаясь на символ терминатора, вы должны прокручивать массив, чтобы найти его размер!)

В таких случаях, как ваша, лучше использовать стандартную библиотеку.

#include <vector> 
#include <iostream> 

int main() 
{  
    std::vector<int> v; 
    v.push_back(7); 
    v.push_back(10); 
    std::cout << v.size() << std::endl; 
    return 0; 
} 
+0

Почему вы не могли принять решение о том, чтобы использовать '\ 0' в качестве контрольной точки для других типов данных? (даже если он не является общеупотребительным) – Reunanen

+0

(и даже при назначении '\ 0' для int вводит в заблуждение ... но он все равно заканчивается 0, и если вы знаете, что действительные данные никогда не содержат нуля, то этот подход должен работать, хотя это еще не лучший способ сделать это) – Reunanen

+0

@Pukku: Я никогда не говорил, что вы не можете принять решение о таком соглашении. Для строк - это не только конвенция, применяемая библиотеками: например, строковый литерал автоматически добавит «\ 0» в конце. Это неверно для массива int литералов, например. – UncleZeiv

0

Потому что вы выделяете пространство для массива из нулевых элементов. Следующие строки

temp [1] = 10; 
    temp[2] = '\0'; 

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

Если вы хотите изменяемый массив, вы можете использовать зЬй :: вектор (и использовать функцию-член push_back для вставки новых значений)

Вектора также имеет размер() функцию-член, который говорит вам текущий размер.

Если вы хотите использовать примитивный массив, вы должны сами отслеживать размер.(И, при изменении размера массива необходимо скопировать все элементы из старого массива в новый, больше одного)

1

Наиболее распространенный способ, чтобы получить размер массива фиксированной длины что-то вроде этого:

int temp[256]; 
int len = sizeof (temp)/sizeof (temp[0]); 
// len == 256 * 4/4 == 256 on many platforms. 

Это не работает для динамических массивов, потому что они на самом деле указатели.

int* temp = new int[256]; 
int len = sizeof (temp)/sizeof (temp[0]); 
// len == 4/4 == 1 on many platforms. 

Для массива динамической длины, если вы заботитесь о размере, то Вам лучше всего хранить его где-нибудь, когда вы выделяете массив.

Проблема с петлей, как было отмечено многими, что у вас есть проблемы оператор старшинства здесь:

*temp + i 

должно быть:

*(temp + i) 

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

1

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

int n; 
cin>>n; 
int array = new int[n]; 
int array_length=n; 

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

2

Если вы не хотите использовать зЬй :: вектор, попробуйте следующее:

#include <iostream> 
using namespace std; 

int main() { 
    int vet[] = {1,2,3,4,5,6}; 
    cout << (sizeof (vet)/sizeof *(vet)) << endl; 
    return 0; 
} 
-1

Попробуйте это:

int length(int* temp) 
{ 
    int count = 0; 

    while (*temp != 0 && *temp != -858993460) 
    { 
     ++count; 
     ++temp; 
    } 

    return count; 
}