Неопределенное поведение в C при создании массивов и извлечении из них данных

#c #arrays #undefined-behavior

#c #массивы #неопределенное поведение

Вопрос:

У меня неопределенное поведение, и поскольку я новичок в C , я не знаю, как даже попытаться решить эту проблему. Я просматривал эту ссылку, где показаны возможные ошибки. Единственное предположение, которое у меня есть, это то, что, возможно, мне следует использовать malloc?

 #include <iostream>
using namespace std;

int main()
{

    int population[100];

    for (int i = 0; i < 100;   i)
    {
        population[i] = rand()%(10);
    }

    int firstTournament[2];
    int secondTournament[2];

    int randomNumbers[4] = {};

    for (int i = 0; i < 4;   i)
    {
        int indexOfIndividual = rand()%(101);
        randomNumbers[i] = indexOfIndividual;
    }

    for(int i = 0; i < 4; i  )
    {
        if(i < 2)
        {    
            firstTournament[i] = population[randomNumbers[i]];
            cout << "first tournament " << firstTournament[i] <<endl;
        }
        else
        {    
            secondTournament[i] = population[randomNumbers[i]];
            cout << "second tournament " << secondTournament[i] <<endl;
        }
    }

    for (int i = 0; i < 2;   i)
    {
        // This is where the problem starts. It prints gibberish
        cout << "before tournament first  " << firstTournament[i] << endl;
        cout << "before tournament second " << secondTournament[i] << endl;
    }

    return 0;
}
  

Это то, что распечатывается:

 first tournament 4
first tournament 6
second tournament 5
second tournament 3

//This is where the fun begins:
before tournament first 4            // so far correct
before tournament second -1834234234 // ??? 
before tournament first 6            // correct
before tournament second 3266        // the numbers are supposed to be between 0 and 10
  

Как мне подойти к этой проблеме? Что я делаю не так?

Я компилирую его, выполняя

 g   -std=c  11 -c -I /stuff/include main.cc
  

Комментарии:

1. Рассмотрим, что i будет при cout << "second tournament " << secondTournament[i] <<endl; запуске и насколько оно велико secondTournament .

2. rand()%(101); может возвращать 100 , который находится вне диапазона для индексации int population[100];

Ответ №1:

В логике вашей программы есть ошибка. Здесь вы заполняете secondTournament :

 for(int i = 0; i < 4; i  )
    {
        if(i < 2)
        {    
            firstTournament[i] = population[randomNumbers[i]];
            cout << "first tournament " << firstTournament[i] <<endl;
        }
        else
        {    
            secondTournament[i] = population[randomNumbers[i]];
            cout << "second tournament " << secondTournament[i] <<endl;
        }
    }
  

secondTournament[0] никогда не устанавливается. Потому что, когда i есть 0 , if(i < 2) есть true и secondTournament[i] = ... не выполняется. Затем позже, в этом блоке:

  for (int i = 0; i < 2;   i)
    {
        // This is where the problem starts. It prints gibberish
        cout << "before tournament first  " << firstTournament[i] << endl;
        cout << "before tournament second " << secondTournament[i] << endl;
    }
  

Вы печатаете secondTournament[0] то, что не было установлено. Вместо этого вы устанавливаете secondTournament[2] и secondTournament[3] , оба из которых выходят за рамки. Возможно, вместо этого вы хотели secondTournament[i-2] = ... .

Ответ №2:

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

 #include <iostream>
#include <random>
#include <algorithm>

int main()
{
    std::mt19937 gen{std::random_device{}()}; // or any other prng   
    std::uniform_int_distribution<int> dis(0, 9);

    int population[100];
    std::generate(population, population   100, [amp;]{ return dis(gen); });

    int firstTournament[2];
    int secondTournament[2];

    std::sample(population, population   100, firstTournament, 2, gen);
    std::sample(population, population   100, secondTournament, 2, gen);

    for (int i = 0; i < 2;   i)
    {
        std::cout << "before tournament first  " << firstTournament[i] << std::endl;
        std::cout << "before tournament second " << secondTournament[i] << std::endl;
    }

    return 0;
}