看一看這個,它應該幫助你。
的main.cpp
#include "stdafx.h"
#include "Utility.h"
int main() {
using namespace util;
std::string fileName("sample.txt");
if (fileName.empty()) {
std::cout << "Missing or invalid filename." << std::endl;
return RETURN_ERROR;
}
std::string line;
std::vector<std::string> results;
std::fstream fin;
// Try To Open File For Reading
fin.open(fileName.c_str(), std::ios_base::in);
if (!fin.is_open()) {
std::cout << "Can not open file(" << fileName << ") for reading." << std::endl;
return RETURN_ERROR;
}
// Read Line By Line To Get Data Contents Store Into String To Be Parsed
while (!fin.eof()) {
std::getline(fin, line);
// Parse Each Line Using Space Character As Delimiter
results = Utility::splitString(line, " ");
// Print The Results On Each Iteration Of This While Loop
// This Is Where You Would Parse The Data Or Store Results Into
// Class Objects, Variables Or Structures.
for (unsigned u = 0; u < results.size(); u++) {
std::cout << results[u] << " ";
}
std::cout << std::endl;
}
// Close File Pointer
fin.close();
// Now Print The Full Vector Of Results - This Is To Show You That Each
// New Line Will Be Overwritten And That Only The Last Line Of The File Will
// Be Stored After The While Loop.
std::cout << "\n-------------------------------------\n";
for (unsigned u = 0; u < results.size(); u++) {
std::cout << results[u] << " ";
}
Utility::pressAnyKeyToQuit();
return RETURN_OK;
} // main
sample.txt的
Please help me parse this text file
It spans multiple lines of text
I would like to get each individual word
stdafx.h中 - 其中一些包括可能不需要的文件,他們在這裏爲我有一個更大的解決方案需要他們。
#ifndef STDAFX_H
#define STDAFX_H
#include <Windows.h>
#include <stdio.h>
#include <tchar.h>
#include <conio.h>
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <vector>
#include <array>
#include <memory>
#include <queue>
#include <functional>
#include <algorithm>
// User Application Specific
// #include "ExceptionHandler.h" - One Of My Class Objects Not Used Here
namespace util {
enum ReturnCode {
RETURN_OK = 0,
RETURN_ERROR = 1,
}; // ReturnCode
extern const unsigned INVALID_UNSIGNED;
extern const unsigned INVALID_UNSIGNED_SHORT;
} // namespace util
#endif // STDAFX_H
stdafx.cpp
#include "stdafx.h"
namespace util {
const unsigned INVALID_UNSIGNED = static_cast<const unsigned>(-1);
const unsigned INVALID_UNSIGNED_SHORT = static_cast<const unsigned short>(-1);
} // namespace util
Utility.h
#ifndef UTILITY_H
#define UTILITY_H
namespace util {
class Utility {
public:
static void pressAnyKeyToQuit();
static std::string toUpper(const std::string& str);
static std::string toLower(const std::string& str);
static std::string trim(const std::string& str, const std::string elementsToTrim = " \t\n\r");
static unsigned convertToUnsigned(const std::string& str);
static int convertToInt(const std::string& str);
static float convertToFloat(const std::string& str);
static std::vector<std::string> splitString(const std::string& strStringToSplit, const std::string& strDelimiter, const bool keepEmpty = true);
private:
Utility(); // Private - Not A Class Object
Utility(const Utility& c); // Not Implemented
Utility& operator=(const Utility& c); // Not Implemented
template<typename T>
static bool stringToValue(const std::string& str, T* pValue, unsigned uNumValues);
template<typename T>
static T getValue(const std::string& str, std::size_t& remainder);
}; // Utility
#include "Utility.inl"
} // namespace util
#endif // UTILITY_H
Utility.inl
// ----------------------------------------------------------------------------
// stringToValue()
template<typename T>
static bool Utility::stringToValue(const std::string& str, T* pValue, unsigned uNumValues) {
int numCommas = std::count(str.begin(), str.end(), ',');
if (numCommas != uNumValues - 1) {
return false;
}
std::size_t remainder;
pValue[0] = getValue<T>(str, remainder);
if (uNumValues == 1) {
if (str.size() != remainder) {
return false;
}
}
else {
std::size_t offset = remainder;
if (str.at(offset) != ',') {
return false;
}
unsigned uLastIdx = uNumValues - 1;
for (unsigned u = 1; u < uNumValues; ++u) {
pValue[u] = getValue<T>(str.substr(++offset), remainder);
offset += remainder;
if ((u < uLastIdx && str.at(offset) != ',') ||
(u == uLastIdx && offset != str.size()))
{
return false;
}
}
}
return true;
} // stringToValue
Utility.cpp
#include "stdafx.h"
#include "Utility.h"
namespace util {
// ----------------------------------------------------------------------------
// pressAnyKeyToQuit()
void Utility::pressAnyKeyToQuit() {
std::cout << "\nPress any key to quit" << std::endl;
_getch();
} // pressAnyKeyToQuit
// ----------------------------------------------------------------------------
// toUpper()
std::string Utility::toUpper(const std::string& str) {
std::string result = str;
std::transform(str.begin(), str.end(), result.begin(), ::toupper);
return result;
} // toUpper
// ----------------------------------------------------------------------------
// toLower()
std::string Utility::toLower(const std::string& str) {
std::string result = str;
std::transform(str.begin(), str.end(), result.begin(), ::tolower);
return result;
} // toLower
// ----------------------------------------------------------------------------
// trim()
// Removes Elements To Trim From Left And Right Side Of The str
std::string Utility::trim(const std::string& str, const std::string elementsToTrim) {
std::basic_string<char>::size_type firstIndex = str.find_first_not_of(elementsToTrim);
if (firstIndex == std::string::npos) {
return std::string(); // Nothing Left
}
std::basic_string<char>::size_type lastIndex = str.find_last_not_of(elementsToTrim);
return str.substr(firstIndex, lastIndex - firstIndex + 1);
} // trim
// ----------------------------------------------------------------------------
// getValue()
template<>
float Utility::getValue(const std::string& str, std::size_t& remainder) {
return std::stof(str, &remainder);
} // getValue <float>
// ----------------------------------------------------------------------------
// getValue()
template<>
int Utility::getValue(const std::string& str, std::size_t& remainder) {
return std::stoi(str, &remainder);
} // getValue <int>
// ----------------------------------------------------------------------------
// getValue()
template<>
unsigned Utility::getValue(const std::string& str, std::size_t& remainder) {
return std::stoul(str, &remainder);
} // getValue <unsigned>
// ----------------------------------------------------------------------------
// convertToUnsigned()
unsigned Utility::convertToUnsigned(const std::string& str) {
unsigned u = 0;
if (!stringToValue(str, &u, 1)) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to unsigned";
throw strStream.str();
}
return u;
} // convertToUnsigned
// ----------------------------------------------------------------------------
// convertToInt()
int Utility::convertToInt(const std::string& str) {
int i = 0;
if (!stringToValue(str, &i, 1)) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to int";
throw strStream.str();
}
return i;
} // convertToInt
// ----------------------------------------------------------------------------
// convertToFloat()
float Utility::convertToFloat(const std::string& str) {
float f = 0;
if (!stringToValue(str, &f, 1)) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to float";
throw strStream.str();
}
return f;
} // convertToFloat
// ----------------------------------------------------------------------------
// splitString()
std::vector<std::string> Utility::splitString(const std::string& strStringToSplit, const std::string& strDelimiter, const bool keepEmpty) {
std::vector<std::string> vResult;
if (strDelimiter.empty()) {
vResult.push_back(strStringToSplit);
return vResult;
}
std::string::const_iterator itSubStrStart = strStringToSplit.begin(), itSubStrEnd;
while (true) {
itSubStrEnd = search(itSubStrStart, strStringToSplit.end(), strDelimiter.begin(), strDelimiter.end());
std::string strTemp(itSubStrStart, itSubStrEnd);
if (keepEmpty || !strTemp.empty()) {
vResult.push_back(strTemp);
}
if (itSubStrEnd == strStringToSplit.end()) {
break;
}
itSubStrStart = itSubStrEnd + strDelimiter.size();
}
return vResult;
} // splitString
} // namspace util
在我的小工具庫中我有一個會分裂,可以使用用戶定義的任何分隔字符串的函數。它將搜索該字符分隔符的第一個匹配項,並將其保存到字符串中,並將該字符串推送到一個字符串向量中,並且該字符串每次出現都會繼續此操作,直到完成解析傳遞給它的完整字符串。然後它將返回一個字符串向量給用戶。這對於解析文本文件甚至是需要分解的長字符串數據類型非常有用。現在,如果出現瞭解析文本文件的情況,並假定您需要將多個單詞作爲單個字符串,則可以完成此操作,但您需要做更多工作。例如,一個文本文件可能在一行上有個人記錄。
LastName, FirstName MiddleInitial Age Phone# Address
Cook, John S 33 1-888-323-4545 324 Complex Avenue
,你想的複雜的324大道是一個字符串也不想姓氏之後存儲的逗號。你的代碼來存儲這些信息結構可能是這樣的:
struct PersonalRecord {
std::string firstName;
std::string lastName;
char middleInitial;
unsigned age;
std::string phoneNumber;
std:string address;
};
什麼,你必須做你讀,從您的文件這一行後的while循環相同的迭代,你必須做的是多重解析。
您將首先使用字符串的臨時字符串和向量開始,並使用實用函數splitString,其中的分隔符是逗號。所以這會在字符串的臨時向量中保存2個字符串,第一個是:Cook,第二個是包含前導空格的逗號後面的其餘行。您有temp字符串和temp字符串的原因是您需要在需要時彈出值。因此,在這種情況下,我們必須執行以下操作,但首先,我們如何將多個單詞解析爲一個字符串?我們可以改變文本行的文本文件用雙引號括起來這樣:
文本文件
Cook, John S 33 1-888-323-4545 "324 Complex Avenue"
Evens, Sue A 24 1-888-323-6996 "128 Mission Rd"
Adams, Chris B 49 1-777-293-8234 "2304 Helms Drive"
然後用這個邏輯流程或算法解析它。
的main.cpp
#including "stdafx.h"
#including "Utility.h"
int main() {
using namespace util;
std::string strFilename("personalRecord.txt");
std::ifstream file;
std::string strLine;
std::vector<std::string> vTemp;
std::vector<std::string> vResult;
std::vector<PersonalRecord> vData;
// Open File For Reading
file.open(strFilename.c_str());
// Check For Error Of Opening File
if (!file.is_open()) {
std::cout << "Error opening file (" << strFilename << ")" << std::endl;
return RETURN_ERROR;
}
// Continue Until End Of File
while(!file.eof()) {
// Get Single Full Line Save To String
std::getline(file, strLine);
// Check For Comma
vTemp = Utility::splitString(strLine, ",");
// Save First String For Laster
std::string lastName = vTemp[0];
// Split String Using A Double Quote Delimiter Delimiter
vTemp = Utility::splitString(vTemp[1], "\"");
// Check To See If vTemp Has More Than One String
if (vTemp.size() > 1) {
// We Need To Use Pop Back To Account For Last Double Quote
vTemp.pop_back(); // Remove Last Double Quote
std::string temp = vTemp.back();
vTemp.pop_back(); // Remove Wanted String From vTemp.
// At This Point We Need To Parse vTemp Again Using Space Delimiter
vResult = Utility::splitString(vTemp[0], " ");
// Need To Account For Leading Space In Vector
vResult[0].erase();
// Need To Account For Last Space In Vector
vResult.pop_back();
// Now We Can Push Our Last String Back Into vResult
vResult.push_back(temp);
// Replace The First String " " With Our LastName
vResult[0] = lastName;
} else if (vTemp.size() == 1) {
// Just Parse vTemp Using Space Delimiter
vResult = Utility::splitString(vTemp[0], " ");
}
// Print Out Results For Validity
for (unsigned u = 0; u < vResult.size(); u++) {
std::cout << vResult.at(u) << " ";
}
std::cout << std::endl;
// Here Is Where You Would Populate Your Variables, Structures Or Classes On Each Pass Of The While Loop.
// With This Structure There Should Only Be 8 Entries Into Our vResult
PersonalRecord temp;
temp.lastName = vResult[0];
temp.firstName = vResult[1];
temp.middleInitial = vResult[2][0];
temp.age = Utility::convertToUnsigned(vResult[3]);
temp.phoneNumber = vResult[4];
temp.address = vResult[5];
vData.push_back(temp);
} // while
// Close File
file.close();
std::cout << std::endl << std::endl;
// Print Using Structure For Validity
std::cout << "---------------------------------------\n";
for (unsigned u = 0; u < vData.size(); u++) {
std::cout << vData[u].lastName << " "
<< vData[u].firstName << " "
<< vData[u].middleInitial << " "
<< vData[u].age << " "
<< vData[u].phoneNumber << " "
<< vData[u].address << std::endl;
}
Utility::pressAnyKeyToQuit();
return RETURN_OK;
} // main
所以雙方考慮,都有解析文本或字符串時,必須考慮。你必須考慮到每一個字符,包括你的回車,空格等。所以必須考慮文本文件的格式。 是的splitString()
也將解析標籤,你只需要使用「\ t」標籤等。只要記住,它會在每一次出現分裂。所以,如果你有一個句子有一個冒號「:」,但是你決定使用冒號作爲你的值之間的分隔符,它也會分割這個句子。現在,您可以爲文件中的每行文本制定不同的規則,並且如果您知道自己所在的行,則可以相應地解析每行。這就是爲什麼大多數人更喜歡編寫他們的代碼來讀取和解析二進制文件,因爲編程更容易,然後編寫文本解析器。
我選擇使用PersonalRecord結構向您展示如何從一行文本中提取字符串,並使用我的Utility類中的一些其他函數將它們轉換爲基本類型,如int,float或double。這個類中的所有方法都聲明爲靜態的,並且構造函數是私有的,所以類名可以用作包裝器或命名空間。您無法創建Utility util; // invalid object
的實例。只需包含頭文件,並使用範圍解析運算符::
的類名稱來訪問任何函數,並確保您使用的是namespace util
。
我不能說什麼** iss >>行爲應該是? –
爲什麼getline(cin,t)在你設置了文件內容之後? – Pooya
代碼在語義上是不正確的,你在while循環中返回,所以實際上,while循環只執行一次 – Pooya