Передача массива в качестве аргумента в C ++

В базе ответа NGLG https://stackoverflow.com/a/8811242/6619626 вы можете использовать следующую функцию:

type
OurArrayStr=array of string;

function SplitString(DelimeterChars:char;Str:string):OurArrayStr;
var
seg: TStringList;
i:integer;
ret:OurArrayStr;
begin
    seg := TStringList.Create;
    ExtractStrings([DelimeterChars],[], PChar(Str), seg);
    for i:=0 to seg.Count-1 do
    begin
         SetLength(ret,length(ret)+1);
         ret[length(ret)-1]:=seg.Strings[i];
    end;
    SplitString:=ret;
    seg.Free;
end;

Он работает во всех Delphi версии.

13
задан jkeys 18 April 2009 в 18:01
поделиться

7 ответов

Чтобы немного расширить это, помните, что массивы C ++ - это в точности массивы C. Таким образом, все, что у вас есть, это адрес фрагмента памяти, который якобы (без каких-либо гарантий) является массивом чего-то.

Update

Хорошо, мы расширим немного больше.

C (и, следовательно, C ++) на самом деле не имеет «массивов» как таковых. Все это есть адреса, указатели. Поэтому, когда вы создаете что-то «массив», в действительности вы говорите компилятору, что некоторая переменная представляет адрес.

Полезно проводить различие в C между объявлением и определение . В объявлении вы просто даете что-то имя и тип; в определении вы фактически выделяете пространство.

Итак, если мы начнем с определения массива, подобного

int ar[100];

, это означает, что мы сообщаем компилятору, что нам нужно пространство для 100 int , мы хотим, чтобы он был размещен в одном фрагменте, и мы собираюсь использовать имя ar для него. Оператор sizeof дает число байтов, используемых типом или объектом, поэтому наш массив ar займет 100 × sizeof (int) байтов. На большинстве машин это будет 400 байт, но оно варьируется от машины к машине.

Если мы определяем переменную

int * ar_p;   // using '_p' as a reminder this is a pointer

, мы определяем пространство для переменной, которая будет содержать адрес. Его размер будет sizeof (int *) , который обычно будет 4 или 8, но на некоторых машинах может быть от 2 до 16 на некоторых машинах, с которыми вы вряд ли столкнетесь в ближайшее время.

Имя массива: ar . Компилятор преобразует это имя в адрес, поэтому мы можем сохранить этот адрес с помощью

ar_p = ar ;     // THIS WORKS

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

Это имя ar не не имеет места для него; это как константа, число. Таким образом, вы не можете отменить это назначение

ar = ar_p ;     // THIS WON'T WORK

по той же причине, по которой вы не могли сказать

1000 = ar_p ;   // THIS WON'T WORK EITHER

, т. Е. Вы не можете изменить значение 1000. (Назад в ранних версиях FORTRAN этот трюк работал бы, для сложные причины. Это была ошибка. Вы никогда не жили, пока не попытались отладить программу, в которой значение «2» равно 3.)

Массивы в C всегда начинаются с нуля, то есть Первый индекс всегда равен нулю. Любые другие индексы - это просто адреса, вычисленные с использованием индекса. Таким образом, ar [0] - это просто адрес 1000 плюс 0 байтов смещения или 1000. ar [1] равен 1000 плюс 1 раз размер int , поэтому следующий int закончен. И на самом деле, это всегда верно в C.

Это называется ссылкой на массив .

Когда мы используем синтаксис * ar_p , мы сообщаем компилятору получить вещь по адресу, указанному в ar_p . `.

Это называется разыменованием указателя .

Если мы говорим

ar_p = ar;

, то * ar_p и ar [0] относятся к одному и тому же ,

Когда мы говорим ar [0] , мы говорим компилятору, что мы хотим получить объект по адресу 0 байтов из ar . ar [1] - это адрес один int или 4 байта из ar . Так, * (ar_p + 3) относится к тому же, что и ar [3] . (Нам нужны круглые скобки, потому что мы хотим сначала добавить 3 к адресу, а затем посмотреть содержимое. * ar_p + 3 получит содержимое, на которое указывает сначала ap_p , а затем добавьте к ним 3.

Дело в том, что Си не знает или не очень заботится о том, насколько велик массив в действительности. Если я приду и сделаю ar [365] , компилятор с радостью сгенерируйте код для просмотра в ячейке 1000+ (365 × sizeof (int) ). Если это в вашем массиве, хорошо, но если это просто случайная память, это тоже хорошо. C все равно.

(Помните, C приходит из телефонной компании. «Нам все равно; нам не нужно. Мы» (t + i) будет равняться адресу в t плюс i * sizeof (TYPE)

Объяснено это также выше. Когда вы индексируете в массив, например, ar [42] , это означает, что вы хотите получить 42-е число вне начального адреса. Итак, если вы используете int , то вам нужно переместиться в 42 раза, как бы ни было шире int , то есть sizeof (int) .

Теперь, это все C, и, поскольку C ++ определен как «вид» C, это также относится и к C ++. ЗА ИСКЛЮЧЕНИЕМ

  • , если TYPE не определен пользователем, который перегружает операторы [] и оператор * .

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

31
ответ дан 1 December 2019 в 17:28
поделиться

Вы не должны использовать sizeof (originalarray) / sizeof (int) таким образом. Это будет работать только для статически объявленных массивов (размер известен во время компиляции). Вы должны передать размер вместе с ним. Почему бы вам просто не сделать вектор из массива и вместо этого передать его?

Примечание для стороны: Как правило, всегда помните, что sizeof будет быть переведенным во время компиляции. Так что он никак не мог узнать размер массива, переданного в качестве аргумента.

19
ответ дан 1 December 2019 в 17:28
поделиться

Я вижу, вы включаете <вектор> . Я предлагаю вам покончить со всеми видами использования массивов и использовать только класс vector . Вы можете увидеть примеры того, как использовать контейнеры STL, такие как vector здесь .

4
ответ дан 1 December 2019 в 17:28
поделиться
  • Когда вы передаете массивы функциям, они распадаются на указатели на первый элемент массива, несмотря на запись. Итак, ваш sizeof не работает должным образом.

  • Когда вы передаете массив, лучше всего передать размер массива, чтобы вы знали, где остановиться. Добавьте его в качестве дополнительного параметра.

2
ответ дан 1 December 2019 в 17:28
поделиться

В дополнение ко всем ответам выше, вы также можете проверить вопросы и ответы по массивам из c-faq. com: http://c-faq.com/aryptr/index.html

0
ответ дан 1 December 2019 в 17:28
поделиться

К сожалению, очень сложно делать именно то, что вы хотите, на C или C ++. Вы можете передать массив фиксированного размера следующим образом:

int mergeSort(int originalarray[20])
{
    // do something
}

Однако размер вашего массива не определяется числом, он определяется количеством элементов в списке инициализации.

В вашем случае (хотя на самом деле это неправильно) нужно сделать это в два этапа:

int originalarray[] = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
const size_t arraySize = sizeof originalarray / sizeof originalarray[0];
int mergeSort(int array[arraySize])
{
    // do something
}

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

По правде говоря, вы не можете пойти дальше без понимания концепции «указателя».

Функция, которую вам нужно разработать, действительно должна быть такой:

int originalarray[] = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
const size_t arraySize = sizeof originalarray / sizeof originalarray[0];

int mergeSort(int *array, const size_t size)
{
    // do something
}

mergeSort(&(originalArray[0]), arraySize);

Другими словами, вы передаете указатель на первый элемент и количество элементов.

В качестве альтернативы вы можете иметь дело с векторами. Вектор инкапсулирует те же две вещи (указатель на первый элемент и размер) в единую сущность, называемую «объектом». Кроме того, он управляет памятью за вас, поэтому вы можете увеличивать количество элементов по мере необходимости. Это способ C ++. Жаль, что вы не можете инициализировать вектор с помощью {...}, как массив.

0
ответ дан 1 December 2019 в 17:28
поделиться

Looks like you're using both dynamically allocated arrays and vectors, when I believe just using std::vector will be enough.

First, let your input array be changed to a std::vector, and fill it with your input data.

int main()
{
   std::vector<int> originalarray;
   for (int data = 1; data <= 10; data++)
   {
      originalarray.push_back(data);
   }
   mergeSort(originaldata);
}

Now it's important to declare your mergesort function to take a reference to a std::vector.

int mergeSort(std::vector<int>& originalarray)
{
   // The rest of your code, note that now you are passing 
   // in your array for sorting, so you can continue with your code to split
   // the vector into farray and sarray

   // then call sort on your halves.
   mergeSort(farray);
   mergeSort(sarray);

   // I'm guessing at this point you'd write code to combine your farray sarray, and
   // put it back into originalarray...don't forget to clear original array first!
}

Just a note, looks like you're not doing an inplace sort, so expect your sort to take a while since you're copying out a lot of data.

0
ответ дан 1 December 2019 в 17:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: