Đây tui viết cho cậu từ A->Z luôn T_T, sorry cậu nếu code hơi dài 1 phần vì tui lâu rùi không code nên ngứa tay, thứ 2 bài này khó chịu, tui cũng cố làm cho nó đơn giản mà không ra gì. Thôi thì làm cho ra làm, cậu đọc chỗ nào không hiểu thì nói tui sẽ giải thích.
Utility.h
- Trong đây có 4 hàm, đọc vào 1 line ở mọi định dạng, 1 hàm dừng màn hình,
1 hàm để mở file đọc vào, 1 hàm để chuyển chuỗi sang số. Vì mấy hàm này nó mang ý nghĩa công cụ hơn nên tui quăng hết nó vào 1 namspace tên là util.
C++ Code:
#include <fstream> #include <string> #include <fstream> #include <sstream> namespace util { template< typename T > T readLine( std::ifstream& is ) { std::string line; std::getline( is, line ); std::istringstream iss( line ); T result; iss >> result; return result; } void pauseScreen() { } bool openInputFile( std::ifstream& inf ) { std::string file_name; inf.open( file_name.c_str() ); if( inf.fail() ) { return 0; } return 1; } int convertToInt( const std::string& s ) { int value; std::istringstream is( s.c_str() ); is >> value; return value; } }
Còn đây là class Token, dùng để cắt chuỗi, code này tui lấy xài vì tui tìm không ra các class Token ( cổ điển của tui ) T_T, vì tui thấy class này viết cũng rất tốt, nhưng đọc hơi dài 1 tí thôi, đọc cũng dễ hiểu.
C++ Code:
#ifndef TOKEN_H #define TOKEN_H #include <cstdio> #include <cstdlib> #include <iostream> #include <string> class StringTokenizer { public: StringTokenizer( const std::string& _str, const std::string& _delim ); ~StringTokenizer() { }; int countTokens(); bool hasMoreTokens(); std::string nextToken(); int nextIntToken(); double nextFloatToken(); std::string nextToken( const std::string& delim ); std::string remainingString(); std::string filterNextToken( const std::string& filterStr ); private: std::string token_str; std::string delim; }; #endif
Token.cpp
C++ Code:
#include "Token.h" StringTokenizer::StringTokenizer(const std::string& _str, const std::string& _delim) { if( ( _str.length() == 0 ) || ( _delim.length() == 0 ) ) return; token_str = _str; delim = _delim; unsigned int curr_pos = 0; while( true ) { if( ( curr_pos = token_str.find( delim, curr_pos ) ) != std::string::npos ) { curr_pos += delim.length(); while( token_str.find( delim,curr_pos ) == curr_pos ) { token_str.erase( curr_pos, delim.length() ); } } else break; } if( token_str.find( delim, 0 ) == 0 ) { token_str.erase( 0,delim.length() ); } curr_pos = 0; if( ( curr_pos = token_str.rfind( delim ) ) != std::string::npos ) { if( curr_pos != ( token_str.length() - delim.length() ) ) return; token_str.erase( token_str.length() - delim.length(), delim.length() ); } } int StringTokenizer::countTokens() { unsigned int prev_pos = 0; int num_tokens = 0; if( token_str.length() > 0 ) { num_tokens = 0; unsigned int curr_pos = 0; while( true ) { if ((curr_pos = token_str.find(delim,curr_pos)) != std::string::npos) { num_tokens++; prev_pos = curr_pos; curr_pos += delim.length(); } else break; } return ++num_tokens; } else { return 0; } } bool StringTokenizer::hasMoreTokens() { return( token_str.length() > 0 ); } std::string StringTokenizer::nextToken() { if( token_str.length() == 0 ) return ""; std::string tmp_str = ""; unsigned int pos = token_str.find( delim, 0 ); if( pos != std::string::npos ) { tmp_str = token_str.substr( 0, pos ); token_str = token_str.substr( pos + delim.length(), token_str.length() - pos ); } else { tmp_str = token_str.substr( 0, token_str.length() ); token_str = ""; } return tmp_str; } int StringTokenizer::nextIntToken() { return atoi( nextToken().c_str() ); } double StringTokenizer::nextFloatToken() { return atof( nextToken().c_str() ); } std::string StringTokenizer::nextToken( const std::string& delimiter ) { if (token_str.length() == 0) return ""; std::string tmp_str = ""; unsigned int pos = token_str.find( delimiter, 0 ); if( pos != std::string::npos ) { tmp_str = token_str.substr( 0, pos); token_str = token_str.substr( pos + delimiter.length(), token_str.length() - pos ); } else { tmp_str = token_str.substr( 0, token_str.length() ); token_str = ""; } return tmp_str; } std::string StringTokenizer::remainingString() { return token_str; } std::string StringTokenizer::filterNextToken( const std::string& filterStr ) { std::string tmp_str = nextToken(); unsigned int currentPos = 0; while( ( currentPos = tmp_str.find( filterStr,currentPos ) ) != std::string::npos ) { tmp_str.erase( currentPos, filterStr.length() ); } return tmp_str; }
Còn đây là lớp chính :
TenOfTen.h
C++ Code:
#include <vector> #include "Token.h" #include "Utility.h" class TenOfTen { private : /* Table of all 2D arrays */ std::vector< std::vector< std::vector< std::string > > > table; int table_size; private : void printSingleTable( const std::vector< std::vector< std::string > >& v ) const; public : TenOfTen(); void showData( std::ostream& out ) const; void showSpecificValue( const unsigned& what_table, const unsigned& row, const unsigned& col ) const; void showRoutine() const; void readDataFromFile( std::ifstream& inf ); bool anotherValue( const char* message ) const; };
TenOfTen.cpp
C++ Code:
TenOfTen::TenOfTen() :table_size( 0 ) { } void TenOfTen::printSingleTable( const std::vector< std::vector< std::string > >& v ) const { for( std::vector< std::vector< std::string > > ::const_iterator ot = v.begin(); ot != v.end(); ++ot ) { for( std::vector< std::string > ::const_iterator it = ot->begin(); it != ot->end(); ++it ) { } } } void TenOfTen::showSpecificValue( const unsigned& what_table, const unsigned& row, const unsigned& col ) const { << "][" << col << "] = "; } bool TenOfTen::anotherValue( const char* message ) const { std::string user_answer; while( 1 ) { if( user_answer[ 0 ] == 'Y' || user_answer[ 0 ] == 'y' ) return true; else if( user_answer[ 0 ] == 'N' || user_answer[ 0 ] == 'n' ) return false; } } void TenOfTen::showRoutine() const { unsigned what_table; unsigned dx, dy; do { do { if( what_table < 0 || what_table > table.size() ) { } else { printSingleTable( table[ what_table ] ); } }while( what_table < 0 || what_table > table.size() ); do { if( dx < 0 || dx > table[ what_table ].size() || dy < 0 || dy > table[ what_table ][ dx ].size() ) { } }while( dx < 0 || dx > table[ what_table ].size() || dy < 0 || dy > table[ what_table ][ dx ].size() ); showSpecificValue( what_table, dx, dy ); }while( anotherValue( "\nAnother value ( y , n ) ? " ) ); } void TenOfTen::showData( std::ostream& out ) const { unsigned tab; out << "TABLE SIZE = " << table.size(); for( tab = 0; tab < table.size(); ++tab ) { out << "\n--------\n"; out << "TABLE #" << tab; out << "\n-------\n"; printSingleTable( table[ tab ] ); } } void TenOfTen::readDataFromFile( std::ifstream& inf ) { std::string one_line; std::string tmpstr; int count; int g_row; int g_col; int index; if( util::openInputFile( inf ) ) { g_row = util::readLine< int >( inf ); for( int x = 0; x < g_row; ++x ) { g_col = util::readLine< int >( inf ); std::vector< std::vector< std::string > > level2; for( int y = 0; y < g_col; ++y ) { std::getline( inf, one_line ); StringTokenizer strtok = StringTokenizer( one_line , " " ); count = strtok.countTokens(); std::vector< std::string > level1; for( index = 0; index < count; ++index ) { tmpstr = strtok.nextToken(); level1.push_back( tmpstr.substr( 1 ) ); } level2.push_back( level1 ); } table.push_back( level2 ); } } table_size = table.size(); }
class này thì chỉ đơn giản là gom mấy cái tool ở trên để cho nó vào 1 cái table có gồm nhiều table con, và mỗi table con là 1 vector cấp 2. Tuy nó dài nhưng bảo đảm cậu là tui viết rất kĩ và nó cũng khá uyển chuyển, dù cậu có bao nhiêu dòng và cột. Nếu thắc mắc chỗ nào thì cho tui biết, tui sẽ giải thích.
Và cuối cùng là main thôi
C++ Code:
int main() { std::ifstream inf; TenOfTen client; client.readDataFromFile( inf ); util::pauseScreen(); system( "cls" ); client.showRoutine(); return 0; }