2

Im taking input in from a text file called Enemies.txt. But there is a problem in that it will only print out the first enemy in the file.

Here is my code:

void Enemies :: loadEnemies()
{
    string fileName = "Enemies\\Enemies.txt";
    ifstream infile(fileName);
    string garbage;
    int loadEnemyID;
    string loadEnemyName;
    int loadEnemyStrength;
    int loadExperienceGain;
    string loadWeapon;
    string loadRoom;
    while(infile >> garbage >> garbage >> loadEnemyID
     >> garbage >> garbage >> garbage >> loadEnemyName
     >> garbage >> garbage >> loadEnemyStrength
     >> garbage >> garbage >> garbage >> loadExperienceGain
     >> garbage >> garbage >> garbage >> loadWeapon
     >> garbage >> garbage >> loadRoom >> garbage)
    {
    cout << "Enemy ID: \t\t" << loadEnemyID <<"\n";
    cout << "Enemy Name: \t\t"<< loadEnemyName << "\n";
    cout << "Enemy Strength: \t"<< loadEnemyStrength << "\n";
    cout << "Experience Gain: \t" << loadExperienceGain << "\n";
    cout << "Weapon: \t\t" << loadWeapon << "\n";
    cout << "Room: \t\t\t" << loadRoom << "\n";
    int id = weapon.getWeaponID();
    int weight = weapon.getWeight();
    int damage = weapon.getDamage();
    Weapons w1 (id,loadWeapon, weight,damage);
    int roomID = room.getRoomID();
    string roomExits = room.getRoomExits();
    Rooms r1 (roomID,loadRoom, roomExits);
    Enemies e1 (loadEnemyID,loadEnemyName,loadEnemyStrength,loadExperienceGain,w1,r1);
    enemiesList.Append(e1);
    }
}

Enemies.txt

Enemy ID: 1.
Enemy Name: Wolves.
Enemy Strength: 5.
Experience Gain: 186.
Weapon Name: Claws.
Room Name: 1.

Enemy ID: 2.
Enemy Name: Cave Bear.
Enemy Strength: 10.
Experience Gain: 302.
Weapon Name: Claws.
Room Name: 4.

Enemy ID: 3.
Enemy Name: Viking.
Enemy Strength: 6.
Experience Gain: 254.
Weapon Name: Longsword.
Room Name: 0.

Enemy ID: 4.
Enemy Name: Criminal.
Enemy Strength: 6.
Experience Gain: 198.
Weapon Name: War Axe.
Room Name: 0.

Enemy ID: 5.
Enemy Name: Ninja.
Enemy Strength: 6.
Experience Gain: 211.
Weapon Name: Katana.
Room Name: 0.

Enemy ID: 6.
Enemy Name: Wild Boar.
Enemy Strength: 3.
Experience Gain: 111.
Weapon Name: Claws.
Room Name: 0.

But the funny thing is i have similar code for weapons and it works perfectly.

void Weapons :: loadWeapons()
    {
    string fileName = "Weapons\\Weapons.txt";
    ifstream infile(fileName);
    string garbage;
    int loadWeaponID;
    string loadWeaponName;
    int loadDamage;
    int loadWeight;
    while(infile >> garbage >> loadWeaponID >> garbage >> garbage
        >> garbage >> loadWeaponName >> garbage >> loadDamage >> garbage
        >> garbage >> loadWeight >> garbage)
    {
        //cout << "Weapon ID: \t\t"<< loadWeaponID<< "\n";
        //cout << "Weapon Name: \t\t"<< loadWeaponName << "\n";
        //cout << "Damage: \t\t" << loadDamage <<"\n";
        //cout << "Weight: \t\t" << loadWeight << "\n";
        Weapons w1 (loadWeaponID,loadWeaponName,loadDamage,loadWeight);
        weaponsList.Append(w1);
    }
    }

Weapons.txt ID: 1. Weapon Name: Katana. Damage: 20. Weight: 6.

ID: 2.
Weapon Name: Longsword.
Damage: 17.
Weight: 9.

ID: 3.
Weapon Name: WarAxe.
Damage: 22.
Weight: 20.

ID: 4.
Weapon Name: Staff.
Damage: 9.
Weight: 6.

ID: 5.
Weapon Name: Staff.
Damage: 3.
Weight: 0.
4
  • Now, I know this isn't strictly C++, but why is it so terrible to use the fscanf-function? It's far easier to read, use and debug...at least in my opinion. Anyway, where are you reading the newline between datasets? Plus, you're having one too many garbage at the enemy name. Actually it's just two garbage for all datapoints. Commented May 9, 2013 at 23:08
  • Your weapon one actually counts correctly. Commented May 9, 2013 at 23:08
  • @RefugnicEternium Thanks for the advice. The infile >> garbage at the end of the while reads in the line between enemies... Commented May 9, 2013 at 23:11
  • @chris and does the enemy on not, no ? Commented May 9, 2013 at 23:11

1 Answer 1

4

In your second and last enemy, you have a name that consists of two words:

Enemy Name: Cave Bear.

This messes up the parsing when it tries to read in the strength on the next line.

I would recommend using a different parsing method, like getline and split, instead of trying to abuse operator>>. That way, you can put whatever you want on the right side, and it won't mess up the parsing.

Edit:

Also, for some reason, you need to remove the last >> garbage from the parse, or it won't work either. However, I still strongly recommend you switch to something else, because the fact that this strange thing happens shows how easily breakable it is.


To do getline and split-like parsing, you would do something like this:

std::string line;
while(std::getline(file, line)) {
    std::stringstream ss(line);
    std::string left, right;
    std::getline(ss, left, ':'); // Read until the colon
    std::getline(ss, right, '.'); // Read until the period
    std::cout << left << ": " << right << std::endl;
}
Sign up to request clarification or add additional context in comments.

5 Comments

Maybe not split, seeing as how C++ doesn't have one (though Boost does), but going from the colon to the period should work.
@NeedForSleep it's the "Cave Bear" line that's messing up their parsing, not the "Wild Boar" line (although that one would be a problem as well).
@chris Well, you can build your own kind of split functionality... I agree. Maybe I'll put up an example...
That works as well. There's a good question on how to split strings on the site. I don't think the std::split proposal made it in for C++14.
I just tested that... I dont think thats it i removed the space in between Cave Bear and it still doesnt loop. But if the space was a problem it should be fixed right ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.