从文件中读取混合类型行

时间:2015-04-19 23:33:12

标签: c++ parsing input

获得格式如下的输入文件:

0 1 Hello world!
1 2 Stack Overflow is a very useful website.

我必须将其解析为以下结构数组:

struct Message {
    int source; //eg. 0
    int dest; //eg. 1
    std::string content; // eg. "Hello world!\n"
}

但我缺乏好看的代码。

我目前的解决方案是逐行读取文件,然后使用sscanf解析它:

我目前的解决方案是读取文件的每一行,然后使用sscanf解析它:

std::ifstream f("input");
int src, dest;
char line[1000], text[1000];
while(getline(f, line, 1000)) {
    sscanf(line, "%d%d,%999[^\n]", &src, &dest, text);
    // Process the values
}

我不喜欢它是将iostream阅读与stdio sscanf混合。此外,在我的程序中,第二个整数后面的空格和行尾的\ n字符应该是文本的一部分。我使用追加来解决它,但我很确定有一个更有效的解决方案。

如果没有繁琐的代码,您能否告诉我如何在C ++中实现这一目标?

谢谢!

2 个答案:

答案 0 :(得分:1)

我设法创建了一个工作代码,它可以成功地将文件中的数据直接加载到给定的结构中。为了做到这一点,你必须1)通过另一个函数创建文件,或者从文件浏览器的级别手动创建文件,2)数据必须以与结构相同的方式排序,3)以避免与错误数据相关的任何问题读取,每行植入一个结构元素。

我会给你自己的例子,我在过去的几个小时里一直在努力。

“character.h”标题文件

#ifndef CHARACTER_H
#define CHARACTER_H
#include <iostream>

class Character {
public:
    struct CharacterParameters {
        std::string name;
        std::string race;
        std::string playerClass;
        double height;
        double weight;
        int age;
    };
    struct CharacterStatistics {
        double maxHealth;
        double currentHealth;
        double maxStamina;
        double currentStamina;
        double maxCarryWeight;
        double currentCarryWeight;
        double currentCharacterWeight;
        double basicHealthRegen;
        double basicStaminaRegen;
        double healthRegenBonus;
        double staminaRegenBonus;
        double maxSpeed; // modified by items
        double currentSpeed;
        double currentForce;
        double basicAcceleration;
        double modifiedAcceleration; // currentCharacterWeight * currentSpeed / currentCharacterWeight
    };
    Character::CharacterParameters cpInstance;
    Character::CharacterStatistics csInstance;
    static void CreateNewPlayer();
    static void DisplayCurrentSettings();
    static void SaveDataToFile();
    static void ReadDataFromFile();
private:

};
#endif

“character.cpp”文件

<code ommited>
    Character * newPlayer = new Character;
    void Character::ReadDataFromFile() {
        Character::CharacterParameters cpInstance;
        Character::CharacterStatistics csInstance;
        ifstream playerData;
        playerData.open("playerData.txt");
        playerData >> newPlayer->cpInstance.name;
        playerData >> newPlayer->cpInstance.race;
        playerData >> newPlayer->cpInstance.playerClass;
        playerData >> newPlayer->cpInstance.height;
        playerData >> newPlayer->cpInstance.weight;
        playerData >> newPlayer->cpInstance.age;
        playerData >> newPlayer->csInstance.maxHealth;
        playerData >> newPlayer->csInstance.currentHealth;
        playerData >> newPlayer->csInstance.maxStamina;
        playerData >> newPlayer->csInstance.currentStamina;
        playerData >> newPlayer->csInstance.maxCarryWeight;
        playerData >> newPlayer->csInstance.currentCarryWeight;
        playerData >> newPlayer->csInstance.currentCharacterWeight;
        playerData >> newPlayer->csInstance.maxSpeed;
        playerData >> newPlayer->csInstance.currentSpeed;
        playerData >> newPlayer->csInstance.basicAcceleration;
        playerData >> newPlayer->csInstance.currentForce;
        playerData >> newPlayer->csInstance.modifiedAcceleration;
        playerData >> newPlayer->csInstance.basicHealthRegen;
        playerData >> newPlayer->csInstance.basicStaminaRegen;
        playerData >> newPlayer->csInstance.healthRegenBonus;
        playerData >> newPlayer->csInstance.staminaRegenBonus;
        playerData.close();
    }
存储来自cpInstance和csInstance结构的数据的

“playerData.txt”示例文件

Player
Human
Knight
1.77318
58.6618
21
100
100
100
100
90
0
58.6618
12
0
2
117.324
2
5
5
0
0

EDIT。我将给你一个“character.cpp”的附加部分,其中函数填充给定的结构,以及将它们保存到文件中。

random_device generator;
uniform_real_distribution<double> heightDistribution(1.5, std::nextafter(2, DBL_MAX));
uniform_real_distribution<double> weightDistribution(45, std::nextafter(120, DBL_MAX));
void Character::CreateNewPlayer() {
    Character::CharacterParameters cpInstance;
    Character::CharacterStatistics csInstance;
    char tempRace, tempClass;
    string tempString;
    int tempInt;
    bool isCorrect = false;

    newPlayer->cpInstance.height = heightDistribution(generator);
    newPlayer->cpInstance.weight = weightDistribution(generator);
    newPlayer->csInstance.maxHealth = 100.0;
    newPlayer->csInstance.currentHealth = newPlayer->csInstance.maxHealth;
    newPlayer->csInstance.maxStamina = 100.0;
    newPlayer->csInstance.currentStamina = newPlayer->csInstance.maxStamina;
    newPlayer->csInstance.maxCarryWeight = 90.0;
    newPlayer->csInstance.currentCarryWeight = 0.0;
    newPlayer->csInstance.currentCharacterWeight = newPlayer->cpInstance.weight;
    newPlayer->csInstance.maxSpeed = 12.0;
    newPlayer->csInstance.currentSpeed = 0.0;
    newPlayer->csInstance.basicAcceleration = 2.0;
    newPlayer->csInstance.currentForce = newPlayer->csInstance.currentCharacterWeight * newPlayer->csInstance.basicAcceleration;
    newPlayer->csInstance.modifiedAcceleration = newPlayer->csInstance.currentForce / newPlayer->csInstance.currentCharacterWeight;
    newPlayer->csInstance.basicHealthRegen = 5.0;
    newPlayer->csInstance.basicStaminaRegen = 5.0;
    newPlayer->csInstance.healthRegenBonus = 0.0;
    newPlayer->csInstance.staminaRegenBonus = 0.0;

    do {
        cout << "Please enter your name: "; cin >> tempString;
    } while (tempString.length() > 10);
    newPlayer->cpInstance.name = tempString;
    do {
        cout << "Enter your age: "; cin >> tempInt;
    } while (tempInt > 99);
    newPlayer->cpInstance.age = tempInt;
    cout << "Choose your race (H | V): "; cin >> tempRace;
    while (isCorrect != true) {
        switch (tempRace) {
        case 'H':
        case 'h':
            newPlayer->cpInstance.race = "Human";
            isCorrect = true;
            break;
        case 'V':
        case 'v':
            newPlayer->cpInstance.race = "Vampire";
            isCorrect = true;
            break;
        default:
            cout << "You have selected a wrong character. Please try again.\n";
            cout << "Choose your race (H | V): "; cin >> tempRace;
            break;
        }
    }
    isCorrect = false;
    cout << "Who you want to be (K | M | A): "; cin >> tempClass;
    while (isCorrect != true) {
        switch (tempClass) {
        case 'K':
        case 'k':
            newPlayer->cpInstance.playerClass = "Knight";
            isCorrect = true;
            break;
        case 'M':
        case 'm':
            newPlayer->cpInstance.playerClass = "Mage";
            isCorrect = true;
            break;
        case 'A':
        case 'a':
            newPlayer->cpInstance.playerClass = "Asassin";
            isCorrect = true;
            break;
        default:
            cout << "You have selected a wrong class. Please try again.";
            cout << "Who you want to be (K | M | A): "; cin >> tempClass;
            break;
        }
    }
}

void Character::SaveDataToFile() {
    ofstream playerData;
    playerData.open("playerData.txt");
    playerData << newPlayer->cpInstance.name << endl;
    playerData << newPlayer->cpInstance.race << endl;
    playerData << newPlayer->cpInstance.playerClass << endl;
    playerData << newPlayer->cpInstance.height << endl;
    playerData << newPlayer->cpInstance.weight << endl;
    playerData << newPlayer->cpInstance.age << endl;
    playerData << newPlayer->csInstance.maxHealth << endl;
    playerData << newPlayer->csInstance.currentHealth << endl;
    playerData << newPlayer->csInstance.maxStamina << endl;
    playerData << newPlayer->csInstance.currentStamina << endl;
    playerData << newPlayer->csInstance.maxCarryWeight << endl;
    playerData << newPlayer->csInstance.currentCarryWeight << endl;
    playerData << newPlayer->csInstance.currentCharacterWeight << endl;
    playerData << newPlayer->csInstance.maxSpeed << endl;
    playerData << newPlayer->csInstance.currentSpeed << endl;
    playerData << newPlayer->csInstance.basicAcceleration << endl;
    playerData << newPlayer->csInstance.currentForce << endl;
    playerData << newPlayer->csInstance.modifiedAcceleration << endl;
    playerData << newPlayer->csInstance.basicHealthRegen << endl;
    playerData << newPlayer->csInstance.basicStaminaRegen << endl;
    playerData << newPlayer->csInstance.healthRegenBonus << endl;
    playerData << newPlayer->csInstance.staminaRegenBonus << endl;
    playerData.close();
}

答案 1 :(得分:0)

尝试这样的事情:

#include <iostream>
#include <fstream>
using namespace std;

int main() {
    std::ifstream f("input");

    int src, dst;
    char line[1000] = {0};
    while (f >> src >> dst) {
        f.get(line, 1000, '\n');
        std::cout << src << ' ' << dst << line << std::endl;
    }
    return 0;
}