【问题标题】:Read mixed type lines from file从文件中读取混合类型行
【发布时间】:2015-04-19 23:33:11
【问题描述】:

得到一个格式如下的输入文件:

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++ 中做到这一点吗?

谢谢!

【问题讨论】:

标签: c++ parsing input


【解决方案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();
    }

“playerData.txt”示例文件存储来自 cpInstance 和 csInstance 结构的数据

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

编辑。我将为您提供“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();
}

【讨论】:

    【解决方案2】:

    试试这样的:

    #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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-22
      • 1970-01-01
      • 1970-01-01
      • 2013-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-06
      相关资源
      最近更新 更多