我正在嘗試將我的檔案內容按升序排序為雙倍
我的輸入檔案包含例如這些行:
105 350 4.41386e-06 4.41386e-06
115 300 4.58965e-06 4.58965e-06
15 150 1.6457e-06 1.6457e-06
255 550 5.33661e-05 5.33661e-05
25 150 3.21907e-06 3.21907e-06
35 550 2.57952e-05 2.57952e-05
45 150 1.78332e-06 1.78332e-06
我希望我的輸出檔案具有以下內容:
15 150 1.6457e-06 1.6457e-06
25 150 3.21907e-06 3.21907e-06
35 550 2.57952e-05 2.57952e-05
45 150 1.78332e-06 1.78332e-06
105 350 4.41386e-06 4.41386e-06
115 300 4.58965e-06 4.58965e-06
255 550 5.33661e-05 5.33661e-05
由于我只是 C 編碼的初學者,如果嘗試過這些行來完成該任務:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
int main()
{
std::ifstream textfile( "Limit.txt" );
std::string text_input;
std::vector< std::string > sort_vec;
std::ofstream outfile1;
TString outfile_name1 = "Limits.txt";
if ( textfile.is_open() )
{
outfile1.open( outfile_name1 );
while ( std::getline( textfile,text_input ) )
{
sort_vec.push_back(text_input);
}
textfile.close();
}
std::sort( std::begin( sort_vec ), std::end( sort_vec ), std::less<string>() );
for ( const auto & e : sort_vec )
{
outfile1 << e << "\n";
}
outfile1.close();
}
但我無法得到我想要的結果。
可以請幫助我通過。
uj5u.com熱心網友回復:
由于每行中的空格和不同長度的資料,將行作為字串的字典排序可能會產生意想不到的結果或完全錯誤。
因此,我建議將行拆分為 4 個部分,使用>>運算子使用普通的 IO-extract-functionality 非常簡單。
一行的資料可以存盤在一個結構中。這在某種程度上是直觀的、可讀的和可理解的。為了存盤整個串列,我們可以使用一個std::vector這樣的結構。
除了使用結構外,我們還可以使用std::tupleJarod42 提出的 a。Astd::tuple具有比較運算子,允許稍后對一行進行超簡單的排序。
反正。讓我們從一個結構開始,它有更多的可能性,如下所示。
- 定義結構
- 打開檔案并檢查是否可以打開
- 定義
std::vector上述結構的a - 創建一個結構的臨時實體,可以將資料讀入其中
- 在一個回圈中,從檔案中提取資料并存盤在結構元素中
- 將每個剛剛讀取的資料推回
vector(我們將其稱為資料庫) - 使用 lambda 運算式進行排序以完全控制事物的排序方式
- 向用戶顯示結果
這可以通過多種方式進行編碼。看看下面的潛在示例:
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <iomanip>
struct Data {
int i1{};
int i2{};
double d1{};
double d2{};
};
int main() {
// Open the source textfile and check, if it could be opened
std::ifstream textfile("Limit.txt");
if (textfile) {
// Here we will store all data
std::vector<Data> database{};
// Temporary storage for 1 line
Data data{};
// Read all lines and add data to the database
while (textfile >> data.i1 >> data.i2 >> data.d1 >> data.d2)
database.push_back(data);
// Sort database and use a lambda to do it as wished
std::sort(database.begin(), database.end(), [](const Data& d1, const Data& d2) {
return d1.i1 == d2.i1 ? (d1.i2 == d2.i2 ? (d1.d1 == d2.d1 ? d1.d2 < d2.d1 : d1.d1 < d2.d1) : d1.i2 < d2.i2) : d1.i1 < d2.i1; });
// Debug output
for (const Data& d : database)
std::cout << std::left << std::setw(4) << d.i1 << std::setw(4) << d.i2 << std::setw(12) << d.d1 << d.d2 << '\n';
}
else std::cerr << "\n*** Error! Could not open source file\n\n";
}
但這還不是全部。
如您所知,C 是一種面向物件的語言。我們可以將資料與函式一起存盤在一個結構中(結構是一個類),對這些資料進行操作。
因此,我們可以添加輸入和輸出函式以及排序所需的小于運算子。
那么 main 函式會明顯更簡單。
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <iomanip>
struct Data {
int i1{};
int i2{};
double d1{};
double d2{};
// Methods / operators
// Input
friend std::istream& operator >> (std::istream& is, Data& data) {
return is >> data.i1 >> data.i2 >> data.d1 >> data.d2;
}
// Output
friend std::ostream& operator << (std::ostream& os, const Data& d) {
return os << std::left << std::setw(4) << d.i1 << std::setw(4)
<< d.i2 << std::setw(12) << d.d1 << d.d2;
}
// Comparison
bool operator < (const Data& other) {
return i1 == other.i1 ? (i2 == other.i2 ? (d1 == other.d1 ? d2 < other.d1 : d1 < other.d1) : i2 < other.i2) : i1 < other.i1;
}
};
int main() {
// Open the source textfile and check, if it could be opened
std::ifstream textfile("Limit.txt");
if (textfile) {
// Here we will store all data
std::vector<Data> database{};
// Temporary storage for 1 line
Data data{};
// Read all lines and add data to the database
while (textfile >> data)
database.push_back(data);
// Sort database
std::sort(database.begin(), database.end());
// Debug output
for (const Data& d : database)
std::cout << d << '\n';
}
else std::cerr << "\n*** Error! Could not open source file\n\n";
}
優點:簡單易懂。良好的排序控制。缺點:復雜的排序標準
uj5u.com熱心網友回復:
正如評論中指出的那樣,這里的問題是std::less<std::string>按字典順序對字串進行排序(即與字典中出現的順序相同)。
這不是預期的行為,因為排序將按字符而不是按值執行。
為了實作正確的行為,您需要創建一個自定義比較器,該比較器將提取double值以基于它執行排序。
例如(使用 lambda):
std::sort(sort_vec.begin(), sort_vec.end(), [](const std::string & lhs, const std::string & rhs){
double ld, rd;
std::stringstream{lhs} >> ld;
std::stringstream{rhs} >> rd;
return ld < rd;
});
它可以解決問題(此處為現場示例)
uj5u.com熱心網友回復:
由于您想要基于從左到右的列進行分層排序,因此有多種方法可以使用std::sort.
一種方法是將值讀入std::tuple并應用于std::sort這些元組的向量。元組類將自動對元組的組件進行從左到右的字典比較。
基本上模仿了您的資料的std::tuple<int, int, double, double>一行。
#include <iostream>
#include <string>
#include <vector>
#include <tuple>
#include <sstream>
std::string test =
"105 350 4.41386e-06 4.41386e-06\n"
"115 300 4.58965e-06 4.58965e-06\n"
"15 150 1.6457e-06 1.6457e-06\n"
"255 550 5.33661e-05 5.33661e-05\n"
"25 150 3.21907e-06 3.21907e-06\n"
"35 550 2.57952e-05 2.57952e-05\n"
"45 150 1.78332e-06 1.78332e-06\n"
"105 35 4.41386e-06 4.41386e-06\n"
"115 300 4.58965e-06 4.58965e-09\n"
"15 150 1.6457e-04 1.6457e-04\n"
"255 550 5.33661e-05 5.33661e-02";
using DataLine = std::tuple<int, int, double, double>;
using VectorDataLine = std::vector<DataLine>;
int main()
{
std::istringstream textfile(test);
VectorDataLine sort_vec;
DataLine data_line;
while ( textfile >> std::get<0>(data_line) >>
std::get<1>(data_line) >>
std::get<2>(data_line) >>
std::get<3>(data_line))
{
sort_vec.push_back(data_line);
}
std::sort( std::begin( sort_vec ), std::end( sort_vec ));
for ( const auto & e : sort_vec )
{
std::cout << std::get<0>(e) << ' ' <<
std::get<1>(e) << ' ' <<
std::get<2>(e) << ' ' <<
std::get<3>(e) << "\n";
}
}
輸出:
15 150 1.6457e-06 1.6457e-06
15 150 0.00016457 0.00016457
25 150 3.21907e-06 3.21907e-06
35 550 2.57952e-05 2.57952e-05
45 150 1.78332e-06 1.78332e-06
105 35 4.41386e-06 4.41386e-06
105 350 4.41386e-06 4.41386e-06
115 300 4.58965e-06 4.58965e-09
115 300 4.58965e-06 4.58965e-06
255 550 5.33661e-05 5.33661e-05
255 550 5.33661e-05 0.0533661
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/444764.html
