Вот некоторые из моих общих функций, которые я использую при чтении данных из файла вместе с пользовательской функцией для анализа этого конкретного типа данных или набора.Некоторые функции не используются здесь непосредственно в этом примере, но я предоставляю их в любом случае, так как это 3 распространенных способа получения данных из файла, а также два различных способа создания набора токенов из длинной строки.
#include <exception>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <fstream>
#include <algorithm>
// A basic method to split a string based on a single char delimiter
std::vector<std::string> splitString( const std::string& s, char delimiter ) {
std::vector<std::string> tokens;
std::string token;
std::istringstream tokenStream( s );
while( std::getline( tokenStream, token, delimiter ) ) {
tokens.push_back( token );
}
return tokens;
}
// Similar to above but with the ability to use a string as a delimiter as opposed to just a single char
std::vector<std::string> splitString( const std::string& strStringToSplit, const std::string& strDelimiter, const bool keepEmpty = true ) {
std::vector<std::string> tokens;
if( strDelimiter.empty() ) {
tokens.push_back( strStringToSplit );
return tokens;
}
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() ) {
tokens.push_back( strTemp );
}
if( itSubStrEnd == strStringToSplit.end() ) {
break;
}
itSubStrStart = itSubStrEnd + strDelimiter.size();
}
return tokens;
}
// This function will open a file, read a single line
// closes the file handle and returns that line as a std::string
std::string getLineFromFile( const char* filename ) {
std::ifstream file( filename );
if( !file ) {
std::stringstream stream;
stream << "failed to open file " << filename << '\n';
throw std::runtime_error( stream.str() );
}
std::string line;
std::getline( file, line );
file.close();
return line;
}
// This function will open a file and read the file line by line
// storing each line as a string and closes the file then returns
// the contents as a std::vector<std::string>
void getAllLinesFromFile( const char* filename, std::vector<std::string>& output ) {
std::ifstream file( filename );
if( !file ) {
std::stringstream stream;
stream << "failed to open file " << filename << '\n';
throw std::runtime_error( stream.str() );
}
std::string line;
while( std::getline( file, line ) ) {
if( line.size() > 0 )
output.push_back( line );
}
file.close();
}
// This function will open a file and read all of the file's contents and store it into
// a large buffer or a single string and returns that as its output.
void getDataFromFile( const char* filename, std::string& output ) {
std::ifstream file( filename );
if( !file ) {
std::stringstream stream;
stream << "failed to open file " << filename << '\n';
throw std::runtime_error( stream.str() );
}
std::stringstream buf;
buf << file.rdbuf();
output.clear();
output.reserve( buf.str().length() );
output = buf.str();
}
// A function to parse the data based on your data types or data sets
// and the criteria that is needed for its layout, format etc.
void parseDataFromFile( const std::string& fileContents, std::vector<std::string>& output ) {
std::string delimiter( "----------------------------------------" );
output = splitString( fileContents, delimiter );
// More parsing may need to be done here, but this would be according
// to your specific needs and what you intend to do from this point on.
}
int main() {
try {
std::string fileContents;
getDataFromFile( "test.txt", fileContents );
std::vector<std::string> tokens;
parseDataFromFile( fileContents, tokens );
// This is just temp code to display the file as
// a vector of strings that were split by your delimiter
// This is where you would reorder your data and rewrite it
// back to some file, log, stream, cout, etc.
std::cout << "First Token:\n\n";
for( auto& s : tokens ) {
if( s != tokens.back() )
std::cout << s << "\n\nNext Token:\n";
else
std::cout << s << '\n';
}
} catch( std::runtime_error& e ) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Как видно из результатов, которые генерирует эта программа, я успешно показал, как разделить строку в зависимости от типа разделителя, который требуется в вашей ситуации.Отсюда все, что вам нужно сделать, это отсортировать данные на основе ваших критериев.Затем запишите свое содержимое в поток, консоль или другой файл.