简体   繁体   English

如何从文件中读取用空格分隔的数字

[英]How to read numbers separated with space from a file

I have a text file with numbers in it, the first number is some number written in different number systems, then there is a space, and then there is another number - which is a base the first number is written in. So for example:我有一个包含数字的文本文件,第一个数字是用不同数字系统编写的某个数字,然后是一个空格,然后是另一个数字 - 这是第一个数字写入的基数。例如:

1011011 2 
1212011 3 
1AB13 12 
etc...

I must convert all the numbers in the file to a decimal system using a function that I already have.我必须使用我已经拥有的 function 将文件中的所有数字转换为十进制系统。 It takes two variables, the first one is a number written in different numeric system, and the other one is the base of that system, and then it converts that number to decimal and writes it in another file.它需要两个变量,第一个是用不同数字系统编写的数字,另一个是该系统的基数,然后将该数字转换为十进制并将其写入另一个文件。

How do I read the data from the file so the first number goes to the first variable and the base to the second variable?如何从文件中读取数据,以便第一个数字进入第一个变量,而基数进入第二个变量?

You can read a number as a string, and then its base as a number, by std::ifstream::operator>> .您可以通过std::ifstream::operator>>将数字读取为字符串,然后将其基数读取为数字。 Then you can do your conversion to base 10.然后,您可以转换为基数 10。

#include <fstream>
#include <iostream>

std::ifstream ifs("test.txt");
std::string num;
int base;
while (ifs >> num >> base)
{
    std::cout << num << " in base " << base << "\n";
}

There are many possible solutions.有许多可能的解决方案。 Some are better, some are not so good.有些更好,有些不太好。 It depends a little bit on your requirements.这取决于您的要求。

In any case I do prefer a more object oriented approach in C++.无论如何,我确实更喜欢 C++ 中更面向 object 的方法。 So, we have data, like a string consisting of a number and a base.因此,我们有数据,例如由数字和基数组成的字符串。 We want to split this somehow and extract a base.我们想以某种方式拆分它并提取一个基础。 At the end we want to calculate a decimal number out of that.最后,我们想从中计算出一个十进制数。

So, we can define a small class, eg NumberAndBase.因此,我们可以定义一个小的 class,例如 NumberAndBase。 This class knows, how to read and write its data.这个 class 知道如何读写它的数据。 And nobody else should know that.没有其他人应该知道这一点。 That can be somehow encapsulated.这可以以某种方式封装。 As a solution, we will overwrite the inserter and extractor operator of our tiny class.作为一种解决方案,我们将覆盖我们微型 class 的插入器和提取器运算符。

We can then simple read and write the data like this:然后我们可以像这样简单地读写数据:

    NumberAndBase nab{};
    std::cin >> nab;
    std::cout << nab << "\n\n";

This works of course with every iostream .这当然适用于每个iostream std::cin and std::cout are just examples here. std::cinstd::cout只是这里的例子。

But you want to read more data that are stored in a file.但是您想读取存储在文件中的更多数据。 So you can do this by simply reading the data and put them in a std::vector .因此,您可以通过简单地读取数据并将它们放入std::vector来做到这一点。 Like so:像这样:

std::vector<NumberAndBase> data{ std::istream_iterator<NumberAndBase>(sourceFile), std::istream_iterator<NumberAndBase>() };

This defines a variable data and uses its range constructor.这定义了一个变量 data 并使用它的范围构造函数。 For begin and end, we will use the std::istream_iterator .对于开始和结束,我们将使用std::istream_iterator This will call the inserter operator of the class and read and convert all values.这将调用 class 的插入器运算符并读取和转换所有值。

Now I will show you a complete example.现在我将向您展示一个完整的示例。 Please note.请注意。 I do not have files on SO, so I use an std::istringstream instead, But you can of course exchange this with any std::ifstream , or whatever std::istream you want.我没有关于 SO 的文件,所以我使用std::istringstream代替,但你当然可以将它与任何std::ifstream或任何你想要的std::istream交换。

#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <iomanip>
#include <vector>

unsigned long yourConversionFunction(std::string& s, unsigned int b) { 
    return std::stoul(s, 0, b); 
}

struct NumberAndBase {

    NumberAndBase() {}
    explicit NumberAndBase(std::string& s) : numberAsString(s), base(), result() { convert(s); }
    explicit NumberAndBase(std::string& s, unsigned int b) : numberAsString(s), base(b), result() { result = yourConversionFunction(s,b); }

    unsigned long convert(std::string& s) { 
        std::istringstream iss(s); iss >> numberAsString >> base;
        result = yourConversionFunction(numberAsString, base);
        return result;
     }

    // Extractor. Read number and base, separated by space
    friend std::istream& operator >> (std::istream& is, NumberAndBase& nab) {
        std::string line{};
        if (std::getline(is, line)) nab.convert(line);
        return is;
    }
    // Inserter: Show result
    friend std::ostream& operator << (std::ostream& os, const NumberAndBase& nab) {
        return os << std::left << std::setw(16) << nab.numberAsString << " (" << std::setw(2) << nab.base << ")  -->  " << nab.result;
    }

    // Data
    std::string numberAsString{};
    unsigned int base{ 10 };
    unsigned long result{ 0 };

};


std::istringstream sourceFile{ R"(10011010010    2
1200201        3
103102         4
14414          5
5414           6
3412           7
2322           8
1621           9
1234           10
a22            11
86a            12
73c            13
642            14
574            15
4d2            16
44a            17
3ea            18
37i            19
31e            20)" };

int main() {
    // Read all data
    std::vector<NumberAndBase> data{ std::istream_iterator<NumberAndBase>(sourceFile), std::istream_iterator<NumberAndBase>() };

    // Show result
    std::copy(data.begin(), data.end(), std::ostream_iterator<NumberAndBase>(std::cout, "\n"));

    return 0;
}

You could of course combine the 2 statements in main into one (if you just want to show the result)您当然可以将 main 中的 2 个语句合并为一个(如果您只想显示结果)

int main() {
    std::copy(
        std::istream_iterator<NumberAndBase>(sourceFile),
        std::istream_iterator<NumberAndBase>(),
        std::ostream_iterator<NumberAndBase>(std::cout, "\n"));
    return 0;
}

As said.正如所说。 One of the many possible solutions.许多可能的解决方案之一。 I addedd also some constructors and stuff (not needed in this example, just to give you an idea).我还添加了一些构造函数和东西(在这个例子中不需要,只是为了给你一个想法)。 This could be adapted to your needs.这可以适应您的需要。

Just to be complete: Result of program只是为了完整:程序的结果

10011010010      (2 )  -->  1234
1200201          (3 )  -->  1234
103102           (4 )  -->  1234
14414            (5 )  -->  1234
5414             (6 )  -->  1234
3412             (7 )  -->  1234
2322             (8 )  -->  1234
1621             (9 )  -->  1234
1234             (10)  -->  1234
a22              (11)  -->  1234
86a              (12)  -->  1234
73c              (13)  -->  1234
642              (14)  -->  1234
574              (15)  -->  1234
4d2              (16)  -->  1234
44a              (17)  -->  1234
3ea              (18)  -->  1234
37i              (19)  -->  1234
31e              (20)  -->  1234

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM