Int Array Length C ++ - PullRequest
       11

Int Array Length C ++

2 голосов
/ 26 марта 2009

Мне нужно использовать массив int динамической длины в моей программе, и я хочу иметь возможность получать количество объектов в нем в различных точках моего кода. Я не очень знаком с 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;
}

в настоящее время он просто входит в бесконечный цикл; _;

Ответы [ 10 ]

15 голосов
/ 26 марта 2009

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

Либо создайте массив фиксированного размера с достаточным пространством для размещения в нем всего, что вы хотите, либо используйте 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. На самом деле вам не нужны ни i, ни count, поэтому вы можете написать это несколькими другими способами, либо увеличивая temp напрямую:

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;
}
5 голосов
/ 26 марта 2009

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

int temp[0];

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

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

Следующая проблема - эта строка:

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

То, что делает эта строка, берет значения, хранящиеся в адресе, указанном в 'temp', и добавляет i. Вам нужно получить значение в n-м элементе адреса, заданного параметром temp, например:

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

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

Причины, которые я упомянул, это плохая идея:

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

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

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

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

#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;
}
4 голосов
/ 26 марта 2009

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

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

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

3 голосов
/ 26 марта 2009

Не только массивы C ++ не являются динамическими, как указывает Пит, но только строки (char *) оканчиваются на '\ 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;
}
2 голосов
/ 22 апреля 2012

Если вы не хотите использовать std :: vector, попробуйте это:

#include <iostream>
using namespace std;

int main () {
    int vet[] = {1,2,3,4,5,6};
    cout << (sizeof (vet) / sizeof *(vet)) << endl;
    return 0;
}
1 голос
/ 16 июля 2011

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

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

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

1 голос
/ 26 марта 2009

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

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)

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

0 голосов
/ 20 ноября 2013

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

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

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

    return count;
}
0 голосов
/ 26 марта 2009

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

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

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

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

Вектор также имеет функцию-член size (), которая сообщает текущий размер.

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

0 голосов
/ 26 марта 2009

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

[*] Реализации C (обсуждаемые в контексте символьных массивов как длина динамической строки C ) использовали malloc, realloc и free, но этого следует избегать в коде c ++ .

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