Посмотрите на это, она должна помочь вам.
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 Complex Avenue, чтобы быть в одной строке и вы не хотите, запятая сохраненную после последнего имени.Ваша структура в коде, чтобы хранить эту информацию может выглядеть следующим образом:
struct PersonalRecord {
std::string firstName;
std::string lastName;
char middleInitial;
unsigned age;
std::string phoneNumber;
std:string address;
};
Что вы должны сделать после того, как вы читаете эти строки в из файла на той же итерации цикла в то время как вы должны сделать многократный разбор.
Сначала вы должны начать с использования временной строки и вектора строк и использовать функцию утилиты splitString с разделителем, являющимся запятой. Таким образом, это спасло бы 2 строки в временном векторе строк, которые были бы первым: Кук, а второй - остальная часть строки после запятой, включая ведущее пространство. Причина, по которой у вас есть временная строка и временный вектор строк, заключается в том, что вам нужно будет вывести значения по мере необходимости. Таким образом, в этом случае нам нужно было бы сделать следующее, но сначала, как мы разрешаем случай с несколькими словами одной строкой? Мы можем изменить строку текста в текстовом файле, чтобы быть заключен в двойные кавычки, как, например:
текстовый файл
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, чтобы показать вам, как вы можете извлекать строки из строки текста и преобразовывать их в базовые типы, такие как int, float или double, используя некоторые из моих других функций в моем классе Utility. Все методы в этом классе объявляются как static, а конструктор - private, поэтому имя класса действует как обертка или пространство имен, так сказать. Вы не можете создать экземпляр Utility util; // invalid object
. Просто включите заголовочный файл и используйте имя класса с оператором разрешения области ::
для доступа к любой из функций и убедитесь, что вы используете namespace util
.
Я не могу сказать, что такое ** iss >> слово ** должно быть? –
Почему getline (cin, t) после того, как вы установили t, чтобы иметь содержимое вашего файла? – Pooya
код не является семантически правильным, вы возвращаетесь в цикле while, так что фактически цикл while выполняется только один раз – Pooya