【问题标题】:How to parse a line from the text file如何从文本文件中解析一行
【发布时间】:2014-02-03 03:18:12
【问题描述】:

所以我们有一个包含以下数据的文本文件:

年份 - 品牌 - 型号 - 价格

2011 雪佛兰 Tahoe 30588 美元

所有内容之间只有 1 个空格。价格前面有一个美元符号 ($)。即使它不在数据文件中,我们仍然必须在代码中包含里程。我不知道为什么。

如何从文本文件中获取这些信息?

我尝试了很多方法,但似乎都不起作用。

这是获取信息的代码:

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <ctime>
#include "car.h"
using namespace std;

const int number=3;
const int maxPrice=25000;

int main()
{
    int a;
    string b; string c;
    float d; 
    float e;

    car cars [number];
    int i, j;
    float temp; //Price
    int temp2; //Year
    string temp3; //Make
    string temp4; //Model
    float temp5; //Miles        

    ifstream inFile; //declaring the File
    inFile.open("carData.txt");

    for(i=0; i<number; i++)
    {
        //cout << "Enter the YEAR of the car: ";
        inFile >> a;
        cars[i].setYear(a);
        //cout << "Enter the MAKE of the car: ";
        getline(inFile,b);
        cars[i].setMake(b);
        //cout << "Enter the MODEL of the car: ";
        getline(inFile,c);
        cars[i].setModel(c);
        //cout << "Enter the number of MILES on the car: ";
        inFile >> d; 
        cars[i].setMiles(d);
        //cout << "Enter the PRICE of the car: ";
        inFile >> e;
        cars[i].setPrice(e);
        //cout << " " << endl;
    }

    // ...
}

主要内容远不止于此,这只是为了获取所有数据。我真的整天都在为这件事烦恼。我见过很多不同的方法。

【问题讨论】:

  • 你能缩进你的代码吗?
  • 什么意思?它是缩进的
  • 不是。位是但不是主要的。同时检查错误
  • “缩进”是什么意思?它是代码格式。我只展示了我整个代码的一个块。
  • 您的问题被标记为 C,但像 inFile &gt;&gt; a; 这样的示例代码暗示了 C++。你想要哪个一个

标签: c++ int text-files ifstream getline


【解决方案1】:

如果您使用标准解析函数,例如 std::fscanf,那么您可以 带走你的很多痛苦。您可以了解更多关于 *scanf() 和朋友的信息 来自http://en.wikipedia.org/wiki/Scanf_format_stringhttp://www.cplusplus.com/reference/cstdio/fscanf/

我通常写 C(或 python,我不挑剔;>)所以我会想出一些东西 像这样:

infile = open("datafile"); 
res = 0;
while (res != EOF) {
    res = fscanf(infile, "%d %d %s %s %d",
        &price, &year, &model, &model, &miles);
    if (res < 0) {
        /* error condition from fscanf() */
        (void) fprintf(stderr, "error (%d) from fscanf: %s\n",
            res, strerror(res));
        exit(res);
    }
}

[顺便说一句,像这样的练习通常需要“英里”(即 在您提供的数据 sn-p 中,它缺少最后一列)是因为 他们通常希望您以此为基础,根据里程或 行驶里程 vs 价格 vs 年龄]。

【讨论】:

    【解决方案2】:

    好的,所以我知道这有点晚了,但是如果你还没有这样做的话,这里有一种方法可以在 c++ 中实现你想要的结果

    问题在于 std::getline 会将参数字符串放入整行

    所以如果你有这样的东西

    std::getline(inFile, temp3)
    

    temp3 的值是:“年份 - 品牌 - 型号 - 价格”。

    这也将光标设置到下一行,所以如果你重复这个功能

    std::getline(inFile, temp3)
    

    那么 temp3 将等于 "" 因为第一行之后的行是空的(至少在您用作示例的文件中)。 现在要解决这个问题,您需要使用一个 stringstream,它是一个流,但从 a 读取它的值,请鼓声,字符串。

    所以基本思路是这样的: 1->转到包含信息的行 2->使用字符串流读取数据()

    这是该想法的实现:

    #include <iostream>
    #include <string>
    #include <fstream>
    #include <sstream>
    
    using namespace std;
    
    int main()
    {
        int a; 
        string b; string c;
        float d; 
        float e;
        //This assumes that the array is correctly initialized 
        car cars [number];
        string tempLine;
    
        ifstream inFile; 
        inFile.open("carData.txt");  
    
        //get the cursor past the first line that contains the column names
        std::getline(inFile, tempLine)
    
        //get the cursor past the second line that is blank
        std::getline(inFile, tempLine)
    
        //Now we are at the line that interests us
        //I am assuming that the next lines don't have a blank line between them
        unsigned int = 0;
        int numberOfMiles;
    
        while(std::getline(inFile, tempLine) && i<number)
        {
             std::stringstream iss(tempLine)
             string tempPrice; //this will be the price value with the dollar sign
    
             //you can also write in expanded form this read, but this works just fine
             iss>>a>>b>>c>>numberOfMiles>>tempPrice; //notice that the price is now a string 
    
             tempPrice.erase(0,1)//this eliminates the dollar($) sign
    
             std::stringstream iss1(tempPrice)//new stringstream as we need to read this string 
    
             iss1>>temp;//I believe this is your price variable 
    
             cars[i].setYear(a);
             cars[i].setMake(b);
             cars[i].setModel(c);
             cars[i].setMiles(numberOfMiles);
             cars[i].setPrice(temp); //i am assuming that this is how the function in called
    
             i++;
        }
    
    }
    

    希望这会有所帮助。

    【讨论】:

    • 考虑如果一行包含:2007 Chevrolet Monte Carlo $4995 或任何其他由两个或多个单词组成的模型名称会发生​​什么。
    • @Edward 2007 Mitsubishi Motors Evo Lancer $7889 也是如此,在这些情况下,无法确定哪些数据进入哪个变量。我相信,构建字典或其他方式来确定任何连续的单词代表什么数据是矫枉过正的。一个解决方案可以是一个定界符,例如“,”,并简单地检查从字符串流中读取的每个内容,为定界符保留一个计数器 c,并将数据手风琴放在该计数器上(c=1-> 读取年份,c=2- >制作)。鉴于示例文件,我认为最好坚持使用假定的结构进行解析。
    • 另一种方法是从前面解析数据,选择年份,然后从后面解析数据,选择价格,然后将剩下的部分划分为模型和制造。在我看来,让程序在没有任何诊断消息的情况下直接失败并不是最好的选择。
    • @Edward Fair 但是你仍然有问题要确定有多少词进入了品牌,有多少词进入了模型。
    • @Edward 在代码中,唯一的方法是创建一个字典,或者其他可能会想到的关联容器,这肯定会使响应混乱。在我看来,真正的解决方案是使用分隔符,正如我所说,如果我要为具有该结构(Year、Make、Model、Price)的文件编写代码,它将在给出的示例中失败问这个问题的人。这就是为什么我选择不使答案进一步复杂化的原因。我本可以抛出一些异常,但这会使代码混乱,我不希望这样
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-07
    • 2012-08-21
    • 1970-01-01
    相关资源
    最近更新 更多