Программа компилируется, и я могу ввести число, но оно не генерирует или не отображает массив. Когда я убираю условие while с помощью линейного поиска в функции randomFillUnique, оно генерирует и отображает массив, но не уникальные числа. Мне нужен был двумерный массив без повторяющихся чисел.
#include <iostream>
#include <string>
#include <random>
#include <ctime>
using namespace std;
int** gen2Array(int n);
void randomFillUnique(int** arr, int n);
bool lSearch(int** arr, int n, int target);
void display(int** arr, int n);
int main()
{
int number;
cout << "Enter a number: ";
cin >> number;
randomFillUnique(gen2Array(number), number);
system("pause");
return 0;
}
int** gen2Array(int n)
{
int** arr2D = new int*[n];
for (int index = 0; index < n; index++)
arr2D[index] = new int[n];
return arr2D;
}
void randomFillUnique(int** arr, int n)
{
static default_random_engine e;
uniform_int_distribution<int> u(1, n*n);
e.seed(static_cast<int>(time(NULL)));
bool result = false;
for (int row = 0; row < n; row++)
{
for (int col = 0; col < n; col++)
{
arr[row][col] = u(e); //generate random number
result = lSearch(arr, n, arr[row][col]);
while (result == true)
{
arr[row][col] = u(e); //generate random number
result = lSearch(arr, n, arr[row][col]);
}
}
}
display(arr, n);
delete[] arr;
}
bool lSearch(int** arr, int n, int target)
{
bool found = false;
for (int row = 0; row < n; row++)
for (int col = 0; col < n; col++)
{
if (arr[row][col] == target)
{
found = true;
return found;
}
}
return found;
}
void display(int** arr, int n)
{
for (int row = 0; row < n; row++)
{
for (int col = 0; col < n; col++)
cout << arr[row][col];
cout << endl;
}
}
Поскольку вы устанавливаете запись в массиве на u (e) до того, как начнете использовать lsearch, lsearch всегда возвращает значение true, и ваш цикл while будет работать вечно. Ниже, адаптированный из вашего кода, должен это исправить (я предполагаю, что остальная часть кода ведет себя так, как и следовало ожидать). Как указывает user4581301, может быть, есть более подходящие подходы, но я надеюсь, что у вас будет достаточно, чтобы заставить его работать, я надеюсь.
void randomFillUnique(int** arr, int n)
{
static default_random_engine e;
uniform_int_distribution<int> u(1, n*n);
e.seed(static_cast<int>(time(NULL)));
int nextEntry;
bool result = false;
for (int row = 0; row < n; row++)
{
for (int col = 0; col < n; col++)
{
result = true;
while (result == true)
{
nextEntry = u(e); //generate random number
result = lSearch(arr, n, nextEntry);
if (result != true)
{arr[row][col]=nextEntry;}
}
}
}
display(arr, n);
delete[] arr;
}
Альтернативный подход заключается в создании контейнера всех уникальных целых чисел, которые будут помещены в массив, используя йота:
std::vector<int> invalues(n*n, 0);
std::iota(invalues.begin(), invalues.end(), 1);
Затем перемешайте этот контейнер:
std::shuffle(invalues.begin(), invalues.end(),
std::mt19937{std::random_device{}()});
Затем введите значения по одному в матрицу.
Вы также можете использовать vector<vector<int>>
вместо встроенных массивов:
using matrix = std::vector<std::vector<int>>;
// initialising a vector<vector<int>> to be a certain size is a bit clumsy
matrix m(size_y, std::vector<int>(size_x, 0));
Затем вводим входные значения в матрицу:
for (auto &row : m) {
for (auto &elem : row) {
elem = invalues.back();
invalues.pop_back();
}
}
Затем отображаем матрицу:
for (const auto &row : m) {
for (const auto &elem : row) {
std::cout << elem << " ";
}
std::cout << std::endl;
}
ХОРОШО. Вот более простой способ сделать это, я прокомментировал. Если std :: vector не разрешен, будет достаточно простого 1D вектора, но здравомыслящий инженер-программист подумает очень-очень серьезно, прежде чем выбрать его поверх vector
,
Я сделал несколько других изменений, чтобы исправить пару других ошибок.
#include <iostream>
#include <string>
#include <random>
#include <vector>
#include <algorithm> // std::shuffle and std::iota
#include <ctime>
using namespace std;
int** gen2Array(int n);
void randomFillUnique(int** arr, int n);
bool lSearch(int** arr, int n, int target);
void display(int** arr, int n);
//Added to properly delete the 2dArray
void del2Array(int ** arr, int n);
int main()
{
int number = 10;
randomFillUnique(gen2Array(number), number);
system("pause");
return 0;
}
int** gen2Array(int n)
{
int** arr2D = new int*[n];
for (int index = 0; index < n; index++)
arr2D[index] = new int[n];
return arr2D;
}
//Added to properly delete the 2dArray
void del2Array(int ** arr,
int n)
{
for (int index = 0; index < n; index++)
delete arr[index];
delete arr;
}
void randomFillUnique(int** arr, int n)
{
//do the seeding here
static default_random_engine e(static_cast<int>(time(NULL)));
// otherwise
// e.seed(static_cast<int>(time(NULL)));
// runs every time reseeding the RNG to potentially the give the same results
// if run more than once in a second. Plus the seeding is expensive.
std::vector<int> v(n*n); // make and size vector
std::iota (v.begin(), v.end(), 0); // init vector with 1 through n*n
std::shuffle(v.begin(), v.end(), e);
size_t index = 0;
for (int row = 0; row < n; row++)
{
for (int col = 0; col < n; col++)
{
arr[row][col] = v[index++]; //generate random number
}
}
display(arr, n);
del2Array (arr, n); // frankly I don't think you want his here
// why fill an array only to delete it?
// more logical to display and delete back in main.
}
void display(int** arr, int n)
{
for (int row = 0; row < n; row++)
{
for (int col = 0; col < n; col++)
cout << arr[row][col] << "\t"; //added a tab to make the printing easier to read
cout << endl;
}
}
Документация по std::iota
, Который использует именно эту технику, чтобы продемонстрировать iota
, Смешно, а?