И Тааак
Начнём...
(Если лень читать описание или Вы сеньор прогер - сразу см внизу: "САМ ВОПРОС" и "ДОП ВОПРОС")
Есть структура:
struct People {
char name;
int score;
};
В мейне инициализируется массив n таких структур (указатель на такой массив):
People *EsFP = new People[n];
Далее он заполняется значениями из файла:
for (unsigned int i = 0; i < n; i++) {
fscanf_s(fp, "%s %d", EsFP[i].name, 32, &EsFP[i].score))
}
Далее необходимо отредачить (в данном случае - перемешать) элементы массива через функцию и я это реализовал так:
void Fisher_Yates_shuffle(int n, People* EsFP[]) {
People* a;
People* b;
for (int i = n - 1; i >= 1; i--) //(начинаем с последнего элемента, заканчиваем первым)
{
a = EsFP[0] + i; //теперь а указывает на EsFP[i]
int j = rand()%(n+1); //выбираем рандомный индекс элемента, с которым поменяем EsFP[i]
b = EsFP[0] + j; //теперь b указывает на EsFP[i]
People_swap(a, b); //функция свапа двух элементов массива структур People
}
}
САМ ВОПРОС: строчки
a = EsFP[0] + i; и b = EsFP[0] + j;
вообще адекватны? Всм. нельзя ли чего-то более простого? Типа неработающего EsFP[i] и EsFP[j]?
Функция People_swap() (на всякий пожарный):
void People_swap(People* a, People* b){
People temp = *a;
strcpy_s(a->name,b->name);
a->score = b->score;
strcpy_s(b->name, temp.name);
b->score = temp.score;
}
ДОП ВОПРОС: сама идея реализации такой функции тоже смущает) было бы неплохо обойтись и без неё. Но можно ли?
C/C++
Как работать с элементами динамического массива из функции?
Во-первых, исправьте, пожалуйста, объявление struct People: первое поле (name) имеет тип char, а это всего один символ. А ниже Вы считываете из файла строку именно в это поле.
Во-вторых, лучше объявить тип «указатель на People» и сделать переменную EsFP массивом из таких указателей, тогда перемешивание затронет только адреса данных, но сами данные не придётся тягать из одного места в памяти в другое место в той же памяти.
А если Вы сомневаетесь насчёт функции People_swap, то можете вписать перед заголовком этой функции ключевое слово «inline» и не придавать значения. Пускай компилятор решает, нужна функция или не нужна.
Обратите внимание: хотя переменная EsFP объявлена как указатель на People, но применение к ней квадратных скобок фактически разыменовывает этот указатель. Таким образом, EsFP[0] — это уже не адрес, а значение. a = EsFP[0] + i и b = EsFP[0] + j будут работать, но не так, как Вы задумали. Возможно, Вы имели ввиду: a = EsFP + i и b = EsFP + j.
Во-вторых, лучше объявить тип «указатель на People» и сделать переменную EsFP массивом из таких указателей, тогда перемешивание затронет только адреса данных, но сами данные не придётся тягать из одного места в памяти в другое место в той же памяти.
А если Вы сомневаетесь насчёт функции People_swap, то можете вписать перед заголовком этой функции ключевое слово «inline» и не придавать значения. Пускай компилятор решает, нужна функция или не нужна.
Обратите внимание: хотя переменная EsFP объявлена как указатель на People, но применение к ней квадратных скобок фактически разыменовывает этот указатель. Таким образом, EsFP[0] — это уже не адрес, а значение. a = EsFP[0] + i и b = EsFP[0] + j будут работать, но не так, как Вы задумали. Возможно, Вы имели ввиду: a = EsFP + i и b = EsFP + j.
1.Работа с динамическими массивами в С++ ничем не отличается от работы с обычными. Синтаксис - тот же самый. Потому что и статический, и динамический массив - это по сути адрес начального элемента. Поэтому в фунцию надо передать просто People*EsFP
2.Переставлять элементы массива копированием - это ламерство. За это в любой серьезной конторе надают по рукам. Правильное решение - переставлять индексы элементов.
2.Переставлять элементы массива копированием - это ламерство. За это в любой серьезной конторе надают по рукам. Правильное решение - переставлять индексы элементов.
Александр Иванов
2 пункт самый важный совет...
Владимир Батов
Спасибо!
Но не очень понятно, насчёт"передать просто People *EsFP":
На данный момент я реализовал так (и это работает):
main:
....
People* EsFP = new People[n];
int* index = new int[n];
....
Fisher_Yates_shuffle(n, &index[0]);
....
Функция перемешивания:
void Fisher_Yates_shuffle(int n, int* index) {
for (int i = n - 1; i >= 1; i--)
{
int j = rand()%(n+1);
index_swap(&index[0], index[i], index[j]);
}
}
Т. е. если передавать &EsFP[] (когда функция принимает: void Fisher_...(.., People *EsFP[],..)(это как в изначальном вопросе) - то прямое обращение к элементу EsFP[i] - не работает, но если передать &EsFP[0] - то - работает (как в примере выше с *index)
Т. е. адрес *EsFP[] отличен от адреса *EsFP[0]?
Но не очень понятно, насчёт"передать просто People *EsFP":
На данный момент я реализовал так (и это работает):
main:
....
People* EsFP = new People[n];
int* index = new int[n];
....
Fisher_Yates_shuffle(n, &index[0]);
....
Функция перемешивания:
void Fisher_Yates_shuffle(int n, int* index) {
for (int i = n - 1; i >= 1; i--)
{
int j = rand()%(n+1);
index_swap(&index[0], index[i], index[j]);
}
}
Т. е. если передавать &EsFP[] (когда функция принимает: void Fisher_...(.., People *EsFP[],..)(это как в изначальном вопросе) - то прямое обращение к элементу EsFP[i] - не работает, но если передать &EsFP[0] - то - работает (как в примере выше с *index)
Т. е. адрес *EsFP[] отличен от адреса *EsFP[0]?
Похожие вопросы
- Почему динамический массив напрямую в функцию передать нельзя, а динамический массив указателей можно?
- Задачка по СИ на вставку элемента в динамический массив.
- Размер динамического массива, передаваемого в функцию в C++.
- Как в функции распечатать двумерный динамический массив в Си
- С++ Составить функцию, которая меняет местами пары соседних элементов в массиве
- Распределение элементов в динамическом массиве
- Устройство статических и динамических массивов в оперативной памяти (...)
- Двумерный динамический массив с неизвестны количеством столбиков или строк
- Каким образом можно удалить элементы из динамического массива C++(без использования вспомогательного массива)
- C++ добавить элемент, который введет пользователь в одномерный динамический массив
Должно быть:
struct People{
char name[32]
....
Да, но у нас тогда не будет прямой адресации по ключу (хотя, адекватно ли это при неизвестных ключах?)
Да и указатель весит 4/8 байт, когда вся структура - 36 (дохрена, однако))
Суть в том, что здесь сознательно выбран динамический массив, а не список
И хотелось бы верить, что с подобным представлением данных можно как-то более адекватно работать)
Но, Вы, впринципе, можете доказать, что такое представление - во-первых бред, а во-вторых - сивой кобылы)
Пожалуй, теперь вопрос у меня следующий: а вообще есть ли какой-то смысл в представлении подобных данных с помощью массива структур? Из плюсов - меньше памяти (хотя не на много). Из минусов - приходится перемещать элементы структур, что не хорошо для памяти)
Спасибо!
Видимо, экзамен по структурам данных я не сдам)