complex looping question. Maybe impossible

Viewed 48

Is there a way to loop this so I don't have to write it out 10 times?

Basically, I'm creating instances for a DVD class which each has different member values. It would be nice if I could make my file more readable. I've got this far.

for (int i=n; i<= 10; i++) {
    for (int j=0; j<=9; j++) {
        if (n == i) {
            dvd[j].print();
        }
    }
}

but it's obviously wrong and I know why to. I just don't know if it's possible.

DVD dvd[10];
    dvd[0].id = d[2];
    dvd[0].name = d[3];
    dvd[0].genre = d[4];
    dvd[0].cast = d[5];
    dvd[0].desc = d[6];
    dvd[0].dateRent = d[7];
    dvd[0].dateRet = d[8];
    dvd[0].cost = d[9];
    dvd[1].id = d[12];
    dvd[1].name = d[13];
    dvd[1].genre = d[14];
    dvd[1].cast = d[15];
    dvd[1].desc = d[16];
    dvd[1].dateRent = d[17];
    dvd[1].dateRet = d[18];
    dvd[1].cost = d[19];
    dvd[2].id = d[22];
    dvd[2].name = d[23];
    dvd[2].genre = d[24];
    dvd[2].cast = d[25];
    dvd[2].desc = d[26];
    dvd[2].dateRent = d[27];
    dvd[2].dateRet = d[28];
    dvd[2].cost = d[29];
    dvd[3].id = d[32];
    dvd[3].name = d[33];
    dvd[3].genre = d[34];
    dvd[3].cast = d[35];
    dvd[3].desc = d[36];
    dvd[3].dateRent = d[37];
    dvd[3].dateRet = d[38];
    dvd[3].cost = d[39];
    dvd[4].id = d[42];
    dvd[4].name = d[43];
    dvd[4].genre = d[44];
    dvd[4].cast = d[45];
    dvd[4].desc = d[46];
    dvd[4].dateRent = d[47];
    dvd[4].dateRet = d[48];
    dvd[4].cost = d[49];
    dvd[5].name = d[53];
    dvd[5].id = d[52];
    dvd[5].genre = d[54];
    dvd[5].cast = d[55];
    dvd[5].desc = d[56];
    dvd[5].dateRent = d[57];
    dvd[5].dateRet = d[58];
    dvd[5].cost = d[59];
    dvd[8].id = d[62];
    dvd[8].name = d[63];
    dvd[8].genre = d[64];
    dvd[8].cast = d[65];
    dvd[8].desc = d[66];
    dvd[8].dateRent = d[67];
    dvd[8].dateRet = d[68];
    dvd[8].cost = d[69];
    dvd[7].id = d[72];
    dvd[7].name = d[73];
    dvd[7].genre = d[74];
    dvd[7].cast = d[75];
    dvd[7].desc = d[76];
    dvd[7].dateRent = d[77];
    dvd[7].dateRet = d[78];
    dvd[7].cost = d[79];
    dvd[8].id = d[82];
    dvd[8].name = d[83];
    dvd[8].genre = d[84];
    dvd[8].cast = d[85];
    dvd[8].desc = d[86];
    dvd[8].dateRent = d[87];
    dvd[8].dateRet = d[88];
    dvd[8].cost = d[89];
    dvd[9].id = d[92];
    dvd[9].name = d[93];
    dvd[9].genre = d[94];
    dvd[9].cast = d[95];
    dvd[9].desc = d[96];
    dvd[9].dateRent = d[97];
    dvd[9].dateRet = d[98];
    dvd[9].cost = d[99];

and

if (n == 1) {
    dvd[0].print();
}
if (n == 2) {
    dvd[1].print();
}
if (n == 3) {
    dvd[2].print();
}
if (n == 4) {
    dvd[3].print();
}
if (n == 5) {
    dvd[4].print();
}
if (n == 6) {
    dvd[5].print();
}
if (n == 7) {
    dvd[6].print();
}
if (n == 8) {
    dvd[7].print();
}
if (n == 9) {
    dvd[8].print();
}
if (n == 10) {
    dvd[9].print();
}
1 Answers

eglease's comment was spot on: You'll notice that the index you want to print is one smaller than your n (wherever that comes form), so you can simply use n-1 as an index to print. That is, I think, what you tried to achieve with your nested loop and did with your if-chain, but you were thinking too complicated: No loop is required! You could have spotted the connection between n and the array index when you wrote the if-chain: The index is always one smaller than the n. You can simply write that ;-).

void print dvd_number_n(int n) { dvd[n-1].print(); }

If you want to loop over all your DVDs you can loop from 0 to n-1, which is very common in C or C++ because it has zero-based arrays, that is, the first element is at index 0.

The idiomatic way to code that is a for loop starting at 0 and testing the loop variable for being truly smaller than the number of elements.

For an array with 3 DVDs array alements would be dvd[0], dvd[1], and dvd[2]. dvd[3] would be out-of-bounds, because there are only 3 elements in the array, not 4. Such boundary violations are one of the most common errors in C or C++ which do not check array indices (and typically can't do that at all because the array size is unknown at the site of use). The print loop for an array of 3 DVDs would be

for( int i=0; i<3; i++) { dvd[i].print(); }

The index i

  • starts with 0, execute loop (1)
  • is incremented to 1, smaller than 3, execute loop (2)
  • is incremented to 2, smaller than 3, execute loop (3)
  • is incremented to 3, equal to 3, loop condition is false, loop is left.

This gives us the 3 loop executions with the indices 0,1,2 as desired.

There is a lot of room for improvement: Give your class a constructor and use a vector, not an array. Here is an example that may give you an idea.

#include <iostream>
#include <string>
#include <vector>
#include <iomanip>

/// A simple data holder for DVD information with a constructor.
class DVD_T
{
  std::string mTitle;
  unsigned int mCost; // in cent
public:
  DVD_T(std::string title, unsigned int cost): mTitle(title), mCost(cost) {}
  void print(std::ostream &os)
  {
    os << "Title: \"" << mTitle 
       << "\", cost: $" << mCost/100 << "." << std::setw(2) << std::setfill('0') << mCost%100;
  }
};

std::vector<DVD_T> &initDVDs()
{
  // This initialization of a static local variable will be run only once.
  static std::vector<DVD_T> DVDs
  {
    // You'll probably want to obtain data from your data array d.
    {"Title 1", 109},
    {"Title 2", 99}
  };

  return DVDs;
}

int main()
{
  // Get reference to initialized vector of DVDs
  std::vector<DVD_T> &DVDs = initDVDs();

  // Print them all. "Look mama, no index!"
  for(auto dvd: DVDs)
  {
    dvd.print(std::cout);
    std::cout << '\n';
  }
}

Output:

Title: "Title 1", cost: $1.09
Title: "Title 2", cost: $0.99
Related