简体   繁体   中英

Using a loop with std::strcmp to load lots of settings

In my game I keep track of unlocked levels with a vector std::vector<bool> lvlUnlocked_; .

The simple function to save the progress is this:

void save() {
  std::stringstream ss;
  std::string stringToSave = "";
  std::ofstream ofile("./progress.txt");

  if (ofile.good()) {
    ofile.clear();
    for (std::size_t i = 0; i < levelUnlocked_.size(); ++i) {
      ss << "lvl" << i << "=" << (lvlUnlocked_.at(i) ? "1" : "0") << std::endl;
    }
    stringToSave = ss.str();
    ofile << stringToSave;
    ofile.close();
  }
}

This works and is nice since I can just use a loop to dump the info.

Now to the part where I am stuck, the lower part of my load function (see comment in code below):

void load() {
  std::ifstream ifile("./progress.txt");

  if (ifile.good()) {
    int begin;
    int end;
    std::string line;
    std::string stringKey = "";
    std::string stringValue = "";
    unsigned int result;

    while (std::getline(ifile, line)) {
      stringKey = "";
      stringValue = "";
      for (unsigned int i = 0; i < line.length(); i++) {
        if (line.at(i) == '=') {
          begin = i + 1;
          end = line.length();
          break;
        }
      }
      for (int i = 0; i < begin - 1; i++) {
        stringKey += line.at(i);
      }
      for (int i = begin; i < end; i++) {
        stringValue += line.at(i);
      }

      result = static_cast<unsigned int>(std::stoi(stringValue));

      // usually I now compare the value and act accordingly, like so:
      if (std::strcmp(stringKey.c_str(), "lvl0") == 0) {
        lvlUnlocked_.at(0) = true;
      } else if (std::strcmp(stringKey.c_str(), "lvl1") == 0) {
        lvlUnlocked_.at(1) = true;
      } else if (std::strcmp(stringKey.c_str(), "lvl2") == 0) {
        lvlUnlocked_.at(2) = true;
      }
      // etc....

    }
  }
}

This works fine, but...

the problem is that I have 100+ levels and I want it to be dynamic based on the size of my lvlUnlocked_ vector instead of having to type it all like in the code above.

Is there a way to somehow make use of a loop like in my save function to check all levels?

If you parse your key to extract a suitable integer value, you can just index into the bit-vector with that:

    while (std::getline(ifile, line)) {
        const size_t eq = line.find('=');
        if (eq == std::string::npos)
            // no equals sign
            continue;

        auto stringKey = line.substr(0, eq);
        auto stringValue = line.substr(eq+1);

        if (stringKey.substr(0,3) != "lvl")
            // doesn't begin with lvl
            continue;

        // strip off "lvl"
        stringKey = stringKey.substr(3);

        size_t end;
        std::vector<bool>::size_type index = std::stoi(stringKey, &end);
        if (end == 0 || end != stringKey.length())
            // not a valid level number
            continue;

        if (index >= lvlUnlocked_.size())
            // out of range
            continue;

        // Set it :-)
        lvlUnlocked_[index] = stringValue=="1";
    }

(I've also updated your parsing for "key=value" strings to more idiomatic C++.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM