使用不同类型的分隔符从.txt文件读取输入 [英] Reading input from .txt file with different kinds of delimiters

查看:184
本文介绍了使用不同类型的分隔符从.txt文件读取输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试读取.txt文件并检索x和y坐标,城市ID和城市名称。

I am trying to read a .txt file and retrieve x and y coordinates, a city ID, and city name.

[1, 1]-3-Big_City
//expected : x = 1,  y = 1, city_ID = 3, city_name = Big_City

[2, 8]-2-Mid_City
//expected : x = 2,  y = 8, city_ID = 2, city_name = Mid_City

如何读取和存储 x y city_ID city_name

How do I read and store the x, y, city_ID, and city_name

我有一个while循环可以打印出整行,但是我确实不知道如何使用不需要的符号来定界以获取所需的值。

I have a while loop that can print out the whole line, but I do not know how to delimit using the unwanted symbols to get the required values.

while(getline(inputFile, aLine))
{
    getline(inputFile, aLine, '[');
    x = aLine;

    getline(inputFile, aLine, ',');
    y = aLine;

    // stuck here has getline 3rd parameter only accepts character and not string
    getline(inputFile, aLine, ']-');
    city_ID = aLine;

    ....

    cout << x << " " << y << " " << city_ID
}

我得到的输出也不是我所期望的。

The output I get is also not what I expected. The first line would be missing and the others are not shown.

推荐答案

现在是下一种方法。这是使用面向对象的习惯用法和现代的C ++算法。

And now the next approach. This is using Object Oriented idioms and modern C++ algorithms.

我们拥有某种程度上属于同一类的数据和方法。为此,在C ++中有一些类(结构)。因此,您可以定义一个具有成员变量和方法的类,该类可以与类变量一起使用。一切都作为一个对象。

We have data and methods which belong somehow together. For this there are classes (structs) in C++. So you can define a class, with member variables and methods, which can work with the class varaibles. Everything works as one object.

另外。该类知道如何读取或打印其值。而且只有班级应该知道这一点。

Additionally. The class knows, how to read or print its values. And only the class should know that. This wisdom is encapsulated.

然后,我们要搜索嵌入在字符串中某个地方的有趣数据。该字符串始终包含特定模式。在您的情况下,您有3个整数和一个字符串作为有趣的数据,以及介于两者之间的分隔符(无论它们是什么)。

And, next, we want to search interesting data embedded somewhere in a string. The string contains always a certain pattern. In your case your have 3 integers and one string as interesting data and some delimiters in between, whatever they are.

要匹配此类模式并搜索字符串中有趣的部分,C ++具有 std :: regex 。它们非常强大,因此定义起来有点复杂。

To match such patterns and search for interesting parts of a string, C++ has std::regex. They are extremely powerful and hence a little bit complicated to define.

在以下示例中,我将使用 const std :: regex re(R((\d +)。*?(\d + )。*?(\d +)。*?([\w _] +))); 。这定义了4组子匹配项(在方括号中)以及介于两者之间的内容。因此,任何定界符,空格或任何可能的东西。

In the below example I will use const std::regex re(R"((\d+).*?(\d+).*?(\d+).*?([\w_]+))");. This defines 4 groups of submatches (in brackets) and something in between. So any delimiter, space or whatever is possible.

如果您想更加严格,则只需更改模式即可检测源数据中的错误。请参见 const std :: regex re(R(\ [(\d +)\,\(\d +)\] \-(\d +)\-( [\w _] +))); 。这是一种更严格的方法。发生错误时将不会读取输入文件。

If you want to be more strict, you can simply change the pattern and you can detect errors in the source data. See const std::regex re(R"(\[(\d+)\,\ (\d+)\]\-(\d+)\-([\w_]+))");. This is a more strict approach. The inputfile will not be read in case of error. Or only the beginning with the valid data.

请参见以下示例:

#include <string>
#include <regex>
#include <iterator>
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <ios>

std::istringstream testFile{ R"([12, 34]-56-Big_City1
[789 , 910 ] - 11 -  Big_City2
(55; 88} + 22 *** Big_City3
[77, 666]-555-Big_City4)" };



const std::regex re(R"((\d+).*?(\d+).*?(\d+).*?([\w_]+))");


struct CityData
{
    // Define the city's data
    int xCoordinate{};
    int yCoordinate{};
    int cityId{};
    std::string cityName{};

    // Overload the extractor operator >> to read and parse a line
    friend std::istream& operator >> (std::istream& is, CityData& cd) {

        // We will read the line in this variable
        std::string line{};                 

        // Read the line and check, if it is OK
        if (std::getline(is, line)) {

            // Find the matched substrings
            std::smatch sm{};
            if (std::regex_search(line, sm, re)) {
                // An convert them to students record
                cd.xCoordinate = std::stoi(sm[1]);
                cd.yCoordinate = std::stoi(sm[2]);
                cd.cityId = std::stoi(sm[3]);
                cd.cityName = sm[4];
            }
            else {
                is.setstate(std::ios::failbit);
            }
        }
        return is;
    }

    friend std::ostream& operator << (std::ostream& os, const CityData& cd) {
        return os << cd.xCoordinate << ' ' << cd.yCoordinate << ' ' << cd.cityId;
    }
};

int main()
{
    // Define the variable cityData with the vectors range constructor. Read complete input file and parse data
    std::vector<CityData> cityData{ std::istream_iterator<CityData>(testFile),std::istream_iterator<CityData>() };

    // Print the complete vector to std::cout
    std::copy(cityData.begin(), cityData.end(), std::ostream_iterator<CityData>(std::cout,"\n"));

    return 0;
}

请注意: main 仅包含2个与CityData相关的语句。

Please note: main contains only 2 statements related to CityData. The class knows how to operations should be done.

而且,由于无法在SO上使用文件,因此我从 std :: istringstream读取数据。这与从文件读取相同。

And, because I cannot use file on SO, I read the data from "std::istringstream". This is the same as reading from a file.

这篇关于使用不同类型的分隔符从.txt文件读取输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆