![](/img/trans.png)
[英]How do I read a full name that is separated by a space from a file in C++?
[英]How do I read a full name that is separated by a comma from a file in C++?
我試圖從我要求用戶輸入的文件中讀取用逗號分隔的全名。在示例中,我將提交它是關於美國前十位總統的。 這是我的代碼(我有所有必要的庫,我只是顯示主要的 function 以便我可以知道我錯在哪里):
int main()
{
const int NUMBER_OF_PRESIDENTS = 50;
int n = 0;
string president[NUMBER_OF_PRESIDENTS];
string fileName;
ifstream inputFile;
cout << "Enter name of input file ";
getline(cin, fileName);
inputFile.open(fileName.c_str());
if (inputFile.fail()) {
cout << "This file does not exist.";
}
if (inputFile >> president[n]) {
n++;
}
cout << n << " lines of text read from the input file.\n"
<< "Here are the unsorted names:\n"
<< "--------------------------- \n";
for (int i = 0; i < n; i++) {
cout << "[" << (i+1) << "] " << president[i] << endl;
}
return 0;
}
用戶輸入一個 txt 文件名“firstTen.txt”,並顯示以下 txt:
Washington, George
Adams, John
Jefferson, Thomas
Madison, James
Monroe, James
Adams, John Quincy
Jackson, Andrew
Van Buren, Martin
Harrison, William Henry
Tyler, John
從輸入文件 stream 讀取時,您應該像這樣讀取整行:
if (getline(inputFile, president[n])) {
n++;
}
代替:
if (inputFile >> president[n]) {
n++;
}
要遍歷所有名稱,您可以執行以下操作:
int index = 0;
while (getline(inputFile, president[index])) {
index++;
}
請注意,由於您稍后使用n
進行循環,因此您應該使用另一個變量進行索引。
inputFile >> president[n]
最多只能讀取第一個空白字符。 但是, std::getline
會讀取包括任何空格在內的整行。
您還需要遍歷輸入文件中的行,因此請執行以下操作:
while (getline(inputFile, president[n])) {
n++;
}
使用ifstream
從文件中讀取數據。
要逐行閱讀,您可以這樣做:
for( std::string line; getline( input, line ); )
{
...for each line in input...
}
你也可以這樣做
if (file.is_open()) {
std::string line;
while (std::getline(file, line)) {
// your logic
}
file.close();
}
我會使用“更現代”的 C++ 方法。
我們想閱讀有關總統的數據。 因此,我們創建了一個微小的 class “總統”,只包含名字和姓氏。 因為 class 知道如何讀寫它的數據,我們將覆蓋插入器和提取器操作符。
基本上你想讀一個 csv 文件。
仍然所有人都在鏈接到“我如何閱讀和解析 C++?2 中的 CSV 文件?SO。但是,問題是從 2009 年開始,現在已經超過 10 年了。大多數答案也很老而且非常復雜。所以,也許是時候了改變。
在現代 C++ 中,您擁有迭代范圍的算法。 你會經常看到類似“someAlgoritm(container.begin(), container.end(), someLambda)”的東西。 這個想法是我們迭代一些相似的元素。
在您的情況下,我們遍歷輸入字符串中的標記,並創建子字符串。 這稱為標記化。 我們這樣做是為了從以逗號分隔的文件中獲取名稱和名字。
正是為了這個目的,我們有std::sregex_token_iterator
。 而且因為我們有為此目的而定義的東西,我們應該使用它。
這東西是一個迭代器。 用於迭代字符串,因此是正則表達式。 開始部分定義了我們將操作的輸入范圍,然后有一個std::regex
用於在輸入字符串中應該匹配/不應該匹配的內容。 匹配策略的類型由最后一個參數給出。
所以,既然我們了解了迭代器,我們就可以將標記從迭代器復制到我們的目標,即std::string
的std::vector
。 由於我們不知道我們有多少列,我們將使用std::vector
的范圍構造函數。 簡單的。
下一步。 我們想從文件中讀取。 該文件還包含某種相同的數據。 相同的數據是行。
如上所述,我們可以迭代相似的數據。 如果是文件輸入或其他。 為此, C++ 具有std::istream_iterator
。 這是一個模板,作為模板參數,它獲取應讀取的數據類型,作為構造函數參數,它獲取對輸入 stream 的引用。 沒關系,如果輸入 stream 是std::cin
或std::ifstream
或std::istringstream
。 所有類型的流的行為都是相同的。
由於我們沒有 SO 文件,因此我使用(在下面的示例中) std::istringstream
來存儲輸入 csv 文件。 當然,您可以通過定義std::ifstream sourceFile(filename)
打開文件。 沒問題。
使用std::istream_iterator
,我們遍歷輸入並讀取相似的數據。 在我們的例子中,一個問題是我們想要迭代特殊數據而不是一些內置數據類型。 為此,我們使用 class 總統和覆蓋的提取器和插入器操作符-
所以我們定義了一個變量president並使用它的范圍構造函數並給它一個范圍的開始和一個范圍的結束。 而且,在我們的具體示例中,我們使用std::istream_iterator
的開始和結束迭代器。
如果我們結合以上所有內容,閱讀完整的 CSV 文件是單行的,它是調用其構造函數的變量的定義。
請查看生成的代碼:
#include <iostream>
#include <sstream>
#include <string>
#include <regex>
#include <vector>
#include <iterator>
const std::regex re(",");
std::istringstream sourceFile{R"(
Washington, George
Adams, John
Jefferson, Thomas
Madison, James
Monroe, James
Adams, John Quincy
Jackson, Andrew
Van Buren, Martin
Harrison, William Henry
Tyler, John)"};
struct President {
// Data, at this moment: "name" and "firstName"
std::string name{};
std::string firstName{};
// Overwrite extractor
friend std::istream& operator >> (std::istream& is, President& p) {
// We will read one line
std::string line{};
if (getline(is, line)) {
// Iterator to iterate over the comma separated field in the input string
std::vector<std::string> data {std::sregex_token_iterator(line.begin(), line.end(), re, -1),std::sregex_token_iterator()};
// Read name and first name. Easy to add more
p.name = data[0];
p.firstName = data[1];
}
return is;
}
// Overwrite inserter operator
friend std::ostream& operator << (std::ostream& os, const President& p) {
return os << p.firstName << " " << p.name;
}
};
int main()
{
// Read the complete source file into a std::vector
std::vector<President> president {std::istream_iterator<President>(sourceFile),std::istream_iterator<President>()};
// Show result on console
std::copy(president.begin(), president.end(), std::ostream_iterator<President>(std::cout, "\n"));
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.