Я пытаюсь изучить C++, сначала просматривая детали низкого уровня, прежде чем начинать использовать абстракции, такие как std :: copy или memcpy. В настоящее время я застрял в попытке выяснить, почему этот код никогда не присваивается переменной "sortedArray", когда вы смотрите с отладчиком, я разыскиваю значение из "данных" правильно, но никогда не назначается "sortedArray". Я вижу значение, такое как "-842150451" вместо "14" для первого значения. Не могли бы вы помочь мне выяснить, что я делаю неправильно? И любые другие проблемы, которые могут быть, что я не вижу, или совет будет очень признателен!
void swap(int* bigger, int* smaller){
*bigger += *smaller;
*smaller = *bigger - *smaller;
*bigger = *bigger - *smaller;
}
int* bubbleSort(int *data, int size){
bool swapped = true;
int *sortedArray = (int*)malloc(size*sizeof(int));
for (int i = 0; i < size;i++){
*(sortedArray++) = *(data++);
}
while (swapped){
swapped = false;
for (int i = 1; i <= size - 1; i++){
if (sortedArray[i - 1] > sortedArray[i]){
swap(&sortedArray[i - 1], &sortedArray[i]);
swapped = true;
}
}
size--;
}
return sortedArray;
}
*(sortedArray++) = *(data++);
изменяет указатель, чтобы он больше не указывал на начало выделенной памяти. Итак, позже sortedArray[i]
- это то, что происходит в памяти за массивом, и доступ к нему - неопределенное поведение.
Если вы должны использовать указатели, быстрое решение - использовать временный, например:
int *sortedArray = (int*)malloc(size*sizeof(int));
int* s = sortedArray;
for (int i = 0; i < size;i++){
*s++ = *data++;
}
Другой способ:
int *sortedArray = (int*)malloc(size*sizeof(int));
for (int i = 0; i < size;i++){
sortedArray[i] = data[i];
}
Но лучшим способом было бы использовать стандартные контейнеры и алгоритмы, такие как vector
и sort
.
Вот демонстрация первого исправления в действии.
error: 'malloc' was not declared in this scope
поэтому нужно добавить только одну строку #include <cstdlib>
+ Изменить
*(sortedArray++) = *(data++);
в
sortedArray[i] = data[i];
Вам нужно оставить неповрежденным указатель на выделенный вами блок памяти, чтобы вы могли использовать его (и освободить) позже.
Обратите внимание, что ничего не получается, используя синтаксис *(x+y)
вместо x[y]
, они эквивалентны, но последние легче читать.
В C++ вы не должны использовать malloc
. Вместо этого используйте new int[size]
. Для int
нет никакой разницы, кроме снижения риска создания опечатки, однако для нетривиальных типов malloc
не будет правильно их строить.
Вы первый указатель sortedArray
указывает на некоторую выделенную память.
Затем в первом цикле for вы увеличиваете указатель. не он больше не указывает на эту память.
Просто используйте временный указатель для копии памяти.
int* t = sortedArray ;
И теперь используйте t
в вашем цикле for, который копирует данные.
Вместо временной переменной вы можете посчитать количество раз, когда вы sortedArray++
в цикле for.
Если вы посмотрите: for (int я = 0; я < size;i++)
вы увидите, что контур взял точно size
число итераций.
Просто вычтите размер из указателя после цикла, и вы вернетесь в выделенную память.
sortedArray -= size ;
t make use of a auxiliary variable, I didn
заметил эту деталь.
Это совсем не C++. Вы можете написать общий код, который принимает итератор begin
и end
итератор, чтобы он работал с любым контейнером, который поддерживает такую семантику.
template<typename IT>
void bubble_sort(IT begin, IT end) {
while (true) {
bool swapped = false;
for (IT i = begin; i != end-1; i = i+1) {
if (*i > *(i+1)) {
std::iter_swap(i, i+1);
swapped = true;
}
}
if (swapped == false) return;
}
}
Где std::iter_swap
похож на std::swap
но работает на итераторах. Вы можете видеть итераторы как пару указателей на начало и (конец) конца контейнера.
*(sortedArray++) = *(data++);
swap(&sortedArray[i - 1], &sortedArray[i]);