问题描述
我目前正在尝试为我的 C++ 类创建一个表示高温和低温的烛台图。在这个作业中,我们提供了一个包含两个数据列的 txt 文件,格式如下:
月平均低温高温 (F)
XY
XY
XY
我已成功读取txt文件,但对如何选择特定数据感到困惑。我想基本上跳过第一句话并存储其余变量以创建图形。这就是我遇到的问题。
最后,我需要显示文本文件的第一行,以及显示图形。我非常希望得到您的帮助。
如果有更有效的方法,我很想了解更多!
解决方法
你应该把大问题分解成小问题,然后先解决最小的问题。此外,您应该使用 buildinC++ 功能。 An,在 C++ 中,您应该使用面向对象的方法。
这意味着,将数据及其相关功能存储在一个对象中。所以,数据和方法,对这些数据进行操作。
我建议构建 2 个类(或结构)。 On 保持只有一对低温和高温。
第二个类,包含标题行和一个低温-高温对列表(实现为 std::vector
)。
我们在示例中需要的方法是从流中提取和插入流。
为此,我们使用众所周知的运算符 <<
和 >>
并将它们添加到我们的类中。在这里,我们将执行所有必要的 IO 操作。
因此,如果我们按照上述方法将大问题拆分为较小的部分,那么我们将更容易理解和可读性更好的代码。
最后但并非最不重要的一点是,我们将使用标准库中的现有函数,例如 std::copy
。
istream_iterator
和 std::ostream_iterator
将简单地调用底层提取运算符 >>
和插入运算符 <<
。
完整程序的示例(许多可能的解决方案之一)如下所示:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
// A data struct that can hold a low and a high temperatur and knows,how reaad and write its data
struct LowHighTemperature {
// The data
double low{};
double high{};
// The extractor operator for reading values from a stream
friend std::istream& operator >> (std::istream& is,LowHighTemperature& lht) {
return is >> lht.low >> lht.high;
}
// The inserter operator for writing values to a stream
friend std::ostream& operator << (std::ostream& os,const LowHighTemperature& lht) {
return os << lht.low << '\t' << lht.high;
}
};
// A list with high and low temperatures and a header line
struct TemperatureList {
// The data
std::string header{};
std::vector<LowHighTemperature> lowHighTemperature{};
// The extractor operator for reading values from a stream
friend std::istream& operator >> (std::istream& is,TemperatureList& tl) {
// Delete potentioally pre existing data
tl.lowHighTemperature.clear();
// Read the header line
if (std::getline(is,tl.header))
// Now read all temperatures
std::copy(std::istream_iterator<LowHighTemperature>(is),{},std::back_inserter(tl.lowHighTemperature));
return is;
}
// The inserter operator for writing values to a stream
friend std::ostream& operator << (std::ostream& os,const TemperatureList& tl) {
// Show header
os << tl.header << '\n';
// Show temperatures
std::copy(tl.lowHighTemperature.begin(),tl.lowHighTemperature.end(),std::ostream_iterator<LowHighTemperature>(os,"\n"));
return os;
}
};
// Please store the path to your temperatures source file here
const std::string temperatureFileName{ "r:\\temperatures.txt" };
int main() {
// Open source file and check,if it is open
if (std::ifstream temperaturFileStream{ temperatureFileName }; temperaturFileStream) {
// Here we will store the list with all temperatures and the header
TemperatureList temperatureList{};
// Read all data from file stream
temperaturFileStream >> temperatureList;
// For debug purposes,you show the result on the screen
std::cout << temperatureList;
}
else {
std::cerr << "\n\nError: Could not open '" << temperatureFileName << "'\n";
}
return 0;
}
您可以添加您自己计算所需的任何其他方法。
您可以通过 temperatureList.lowHighTemperature[0]
我希望你明白。
,您使用 std::getline()
阅读了 C++ 中的一行。请注意,检查所有输入函数的返回值以检测错误或丢失的数据或媒体问题等是一种很好的做法。getline()
以及输入 operator>>()
返回输入流。 Streams 有一个方便的 bool 转换:当遇到错误时(读取错误,文件结束),转换产生 false
;如果流正常,则为 true。这种具有这些语义的转换经过精心设计,以便于检查输入操作是否成功:
std::string header;
if(!std::getline(infile,header)) {
std::cerr << "Couldn't read first line\n";
exit(1);
}
// keep line for later output.
// Now read the number pairs. The numbers must be pairs but they actually don't
// have to be on a single line (but it doesn't hurt either).
int a,b;
// The read could fail for other reasons as well;
// a more robust program would look at the status bits of the stream
// and,if an error occurred,print an error message.
while (infile >> a >> b) { // will be false when EOF is reached
{
// print your tree or whatever
}