【问题标题】:Navigate through string and read parts of the lines into class fields浏览字符串并将部分行读入类字段
【发布时间】:2015-01-19 21:31:58
【问题描述】:

我想将我的字符串分成几个部分。让我解释一下我拥有什么以及我想要什么。这就是我得到的,一个看起来像这样的文本文件:

Name: 
Some Name
Country: 
Some Country
Info: 
Some info about me, my job, etc.

现在我用这段代码读取这个文件:

std::ifstream t("file.txt");
std::stringstream buffer;
buffer << t.rdbuf();
std::string temp = buffer.str();

好的,它工作正常,我的临时字符串中有整个文件,但现在我想在我的类中分配这些特殊部分,如下所示:

class MyPerson
{
public:
    std::string name;
    std::string country;
    std::string info;
}

所以在我读取文本文件并将其分配给临时字符串后,我想做这样的事情:

if (temp.find("Name:") != std::string::npos)
{
    // I need some code to read the next lines until i encounter "Country:"
    // so I can assign it to "name" from MyPerson
    // name = theSubstring
}

if (temp.find("Country:") != std::string::npos)
{
    // same as above but "Info:"
    // country = theSubstring
}

if (przepis.find("Info:") != std::string::npos)
{
    // till end
    // info = theSubstring
}

任何想法如何解决这个问题?重要提示:应该尽可能简单,不要使用 boost。

【问题讨论】:

  • 那么输入中的“姓名”、“国家”等记录可以跨越多行吗?无关:您可以使用std::getline 作为更好的替代方法,立即将整行输入读入std::string
  • @5gon12eder 好的,但是我的临时变量中有整个字符串,所以如何将下一个从“名称:”到“国家/地区”的“n”行写入名称变量?
  • 您无需一次性将所有内容都放入 Temp 中。您可以分步从流中读取。但是,如果您出于某种原因真的想将所有内容都读为大读,那么您可以使用 istringstream 类从该字符串中读取部分内容。这是一个从您提供的字符串中读取的流。
  • 你并没有真正回答我之前的问题,但我猜答案是“是”。一次读一行,检查它是否引入了一个新部分,如果没有,将它与你目前阅读的内容连接起来。
  • 但这会让你回到流中。如果你不想那样,你就有点靠自己了。您可以尝试通过换行符将巨大的临时字符串拆分为字符串数组,然后逐个检查每个项目。我的意思是,成对的。

标签: c++ string substring readfile


【解决方案1】:

假设您的数据始终采用以下格式:

header1:
one line of data
header2:
one line of data
...

然后您可以使用std::getline 安全地逐行读取文件。遍历输入流,成对读取行,以便您始终获得有关当前“数据块”的完整信息,然后处理该块并读取下一行。

伪代码:

open the ifstream to a file
loop {
    header = try to read 1 line from ifstream
    if stream is at end of file
        quit. done! all file was read
    if stream is broken
        quit. WTF!

    data = try to read 1 line from ifstream
    if stream is at end of file
        quit. what? why did it happen? DATA should be after a HEADER
    if stream is broken
        quit. WTF!

    // now you have a HEADER and DATA
    if header == 'Name:'
        myObject.Name = data
    if header == 'Foo:'
        myObject.Foo = data
    if header == 'Bar:'
        myObject.Bar = data
    ...
}

注意流状态检查,它们并不明显,而且上面的代码只是伪代码,条件会有点不同。

以上描述不需要您一次阅读整个文本。它直接从流中读取,这是正常的方法。如果您更改数据为字符串,您可以通过istringstring 类将字符串“转换”为临时流,然后以与上述相同的方式从中读取。

OTOH,如果您坚持阅读整个文本而不是稍后使用流,那么您需要实际解析字符串。您需要首先按“换行符”字符拆分字符串,存储它们,然后将它们配对,然后遍历这些对并处理它们。或者,如果您甚至不想这样做,那么您可以在一个巨大的字符扫描循环中使用三个索引(旧位置、下一行结束、下一行结束)并处理即时拦截..

【讨论】:

    猜你喜欢
    • 2020-08-04
    • 2017-08-01
    • 2012-01-15
    • 2018-12-23
    • 1970-01-01
    • 1970-01-01
    • 2012-12-04
    • 2015-03-05
    • 1970-01-01
    相关资源
    最近更新 更多