-1

How do I code a 2d array that would the user input different values for gold, silver, and bronze medals for each country? I know it's pretty basic but i really need help since I've only started c++ last week

Country          Gold Silver Bronze
Canada            0     3      0
Italy             0     0      1
Germany           0     0      1
Japan             1     0      0
Kazakhstan        0     0      1
Russia            3     1      1
South Korea       0     1      0
United States     1     0      1
jxh
  • 69,070
  • 8
  • 110
  • 193
  • You may try a `std::map`, with a `std:string` as key and a `std:tuple` as value. Or use a specific struct with the 4 fields. It depends how you will use it. 1D array in the last case – Damien Dec 10 '20 at 05:35
  • Or create a `struct` with `std::string` and `std::array` and then create a `std::vector`? Several examples in [How do I declare a 2d array in C++ using new?](https://stackoverflow.com/q/936687/3422102) – David C. Rankin Dec 10 '20 at 05:36
  • 2
    Welcome to Stack Overflow. Please read the [About](http://stackoverflow.com/tour) page soon and also visit the links describing [How to Ask a Question](http://stackoverflow.com/questions/how-to-ask) and [How to create a Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve) (MCVE). Providing the necessary details, including your MCVE, compiler warnings and associated errors, if any, will allow everyone here to help you with your question. – David C. Rankin Dec 10 '20 at 05:40
  • See also the example for [std::tuple](https://en.cppreference.com/w/cpp/utility/tuple) – David C. Rankin Dec 10 '20 at 05:43
  • Can you be more specific as to what you expect the user to be able to do? – EnigmaticBacon Dec 10 '20 at 05:44
  • Read a good [C++ programming book](https://www.stroustrup.com/programming.html), the documentation of your C++ compiler (perhaps [GCC](http://gcc.gnu.org/)...) and debugger (e.g. [GDB](https://www.gnu.org/software/gdb/)...) then see [this C++ reference](https://en.cppreference.com/w/). – Basile Starynkevitch Dec 10 '20 at 07:06

2 Answers2

2

For any particular country, you might have an array to represent the row that holds the medal counts. Each column in a row would be associated with gold, silver, or bronze.

Ignoring country for now, you might do something like:

// Hold all the medal values
std::vector<std::array<int, 3>> medal_table;

// Skip title line
std::string line;
std::getline(std::cin, line);

std::string country;
int gold, silver, bronze;
while (std::cin
       >> country
       >> gold
       >> silver
       >> bronze) {
    std::array<int, 3> row{gold, silver, bronze};
    medal_table.push_back(row);
}

Note: the parsing of the country isn't perfect, because some of the country names actually consist of two strings. I'll leave solving that as an exercise.

But, we have now lost the association between the country and the medal counts. You could create another vector to manage that. For example:

std::vector<std::string> country_table;

And then, inside the loop, push the country value in when you push in the row.

    medal_table.push_back(row);
    country_table.push_back(country);

Now, there is a correspondence between the rows in medal_table and the rows in country_table.

The disadvantage of this approach is that if you want to know the medal counts for a particular country, you will have to scan country_table first to find the country. The found index in country_table is then used on medal_table to find the medal counts.

If you can move away from a strictly 2 dimensional array into one that allows 2 dimensional indexing, you can directly map a country name to the row representing the medal counts.

std::map<std::string, std::array<int, 3>> medal_map;

Then, instead of populating corresponding arrays, you can populate a single map.

    medal_map[country] = row;

Now, to find the medal counts for a particular country, you simply index medal_map by the name of the country.

jxh
  • 69,070
  • 8
  • 110
  • 193
2

Another approach using std::tuple would be to create the std::tuple<std::string, int, int, int> and then add each tuple to a std::vector<std::tuple<std::string, int, int, int>>.

Since you can have whitespace included in the country names, it would be simpler to read the country names with getline() and then use normal iostream for gold, silver and bronze. After creating the std::tuple from the values, use the .push_back() member function of std::vector to add the tuple to your vector.

To output the values, you separate each std::tuple into separate values using std::tim and then output, e.g.

#include <iostream>
#include <iomanip>
#include <vector>
#include <tuple>
#include <limits>

int main (void) {
    
    std::vector<std::tuple<std::string, int, int, int>> medals{};   /* vector tuples */
    std::string country{};      /* string for country input */
    int g, s, b;                /* integers for gold, silver, bronze input */
    
    while (1) { /* loop continually */
        std::cout << "enter country: ";         /* prompt and read country */
        if (!getline (std::cin, country) || !country.length())
            break;
        
        std::cout << "  gold silver bronze: ";  /* prompt and read gold, silver, bronze */
        if (!(std::cin >> g >> s >> b)) {
            std::cerr << "error: invalid integer input.\n";
            break;
        }   /* remove up to \n from stdin */
        std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
        
        medals.push_back (std::make_tuple (country, g, s, b));  /* add tuple to vector */
    }
    
    std::cout << "\nCountry          Gold Silver Bronze\n";     /* output heading */
    for (const auto& t : medals) {              /* loop outputting formatted values */
        std::tie (country, g, s, b) = t;
        std::cout << std::left << std::setw(17) << country << std::right <<
                    std::setw(2) << g << std::setw(6) << s << std::setw(7) << b << '\n';
    }
}

(note: you have to remove characters up to the '\n' after reading the int values before calling getline() again)

Exmaple Use/Output

You simply press Enter on an empty-line to end input:

$ ./bin/tuple_metals
enter country: Canada
  gold silver bronze: 0 3 0
enter country: Italy
  gold silver bronze: 0 0 1
enter country: Germany
  gold silver bronze: 0 0 1
enter country: Japan
  gold silver bronze: 1 0 0
enter country: Kazakhstan
  gold silver bronze: 0 0 1
enter country: Russia
  gold silver bronze: 3 1 1
enter country: South Korea
  gold silver bronze: 0 1 0
enter country: United States
  gold silver bronze: 1 0 1
enter country:

Country          Gold Silver Bronze
Canada            0     3      0
Italy             0     0      1
Germany           0     0      1
Japan             1     0      0
Kazakhstan        0     0      1
Russia            3     1      1
South Korea       0     1      0
United States     1     0      1

There are a number of ways to do this, this just being one approach. Look things over and let me know if you have further questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85