Skip to content

dsba-z/week4cpp2022

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DSBA Introduction to Programming // Workshops 7, 8+

Spring semester 2022/23

Dealing with files, streams, vectors and iterators.

Problems are included in the source file. Problems marked with "Example" are supposed to be explained during the workshop. The ones marked with "Practice" are supposed to be solved by the students mostly on their own.

Extra problems and topics

Random number generation

https://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution

There are several ways of generating random numbers in C++. The one described below is a more modern way, but not the only way.

To generate a number you need two objects: a generator and a distribution. The generator is the source of randomness, you can think of it as "the result of a tossed coin" or "a dice roll". The distribution is a function, a set of rules that transforms generator's output into the numbers distributed in a desired way.

For example, you want to generate coin flips - numbers 0 and 1 - but you only have a dice with numbers 1 to 6. In this case, the generator will be the dice, with its output being a uniformly distributed integer from a set {1, 2, 3, 4, 5, 6}. The distribution (in C++ terms) will be, for example, a function "take number X. If it's even, return 0. If it's odd, return 1". Now if you plug generator's output (uniformly distributed numbers 1, 2, 3, 4, 5 and 6) into the desired distribution function, you will get uniformly distributed numbers 0 and 1, which is the goal.

The process that goes in C++ code is similar, but more complex.

Additionally, a generator needs a seed, an initializer number. Random number generators are usually implemented as deterministic functions that always return the same "random" sequence when restarted. For the dice roll example, you can think of it as a video of someone rolling the dice. If you haven't seen the video yet, the output is random for you, it can be any number from 1 to 6. But you replay the same video (restart the application), you already know which numbers will come up. To prevent this, you select a different video when restarting the application. This represents using a new seed in the generator. A commonly used approach is to use the current time as seed, for example.

#include <random>
#include <iostream>
 
int main()
{
    std::random_device rd;  //Will be used to obtain a seed for the random number engine

    // Standard mersenne_twister_engine seeded with rd() - the generator.
    // std::mt19937 is its type, "gen" is just a variable name, it can be anything.
    std::mt19937 gen(rd());

    // Distribution. Here it's uniform distribution of integers of type int, from 1 to 6.
    // distrib is a variable name.
    std::uniform_int_distribution<int> distrib(1, 6);
 
 
    for (int n = 0; n < 10; ++n)
    {
        //Use `distrib` to transform the random unsigned int generated by gen into an int in [1, 6]
        std::cout << distrib(gen) << ' ';
    }
    std::cout << '\n';
}

Exercise 11

Create a function called genThreeDigitNumber(const int& randomState). The function returns a random three digit number as std::string.
Use the randomState variable as seed in the generator. Generate digits from 0 to 9.

Example

std::mt19937 gen(randomState);
std::uniform_int_distribution<int> distr(0,9);
int rNum = distr(gen); // random number

Exercise 12

Create a new vector newVec as VecString and fill it with random numbers.
newVec size should be the same as the size of the vector obtained from getSurvivorSurnames.

Improving previous solution

Exercise 13

Improve your solution of exercise 4 by implementing the following modifications:

First, move the reading of the line outside of the function "extractDataFromLine". Follow this algorithm:

  1. Read the line from the file with std::getline in getFareForClass and save it as a string.
  2. Pass the string to extractDataFromLine or an analogous function.
  3. Convert this string to a stringstream and extract data, just like you're doing currently.
  4. Move the code that checks if the data was read correctly from the input stream to getFareForClass.

Second, use a loop to extract data from a single line.

  1. Read data from the stringstream until ','.
  2. Check the current index. If it is the same as the index if data you want, extract the data.
  3. Repeat until reading fails.

Exercise 14

Modify the program so that if the data cannot be parsed, it prints a helpful message and quits instead of crashing.

std::stoi and std::stod use exception to handle cases when data isn't parsed correctly. We haven't talked about exceptions yet, so the explanation will be about std::stringstream. If you want, you can try using exceptions instead.

When std::stringstream cannot parse data, it will set failbit to true. You can check that it's set by using the usual if (inputStream) approach.

To solve this exercise, modify data conversion from std::stoi and std::stod to conversion via writing data to std::stringstream and reading this data back. Make sure you call sstr.clear() before reusing an empty std::stringstream object. Preferably, try moving data conversion to a separate function where this should not be an issue.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published