首页 > 解决方案 > 重新排列拆分字符串的顺序并放入变量中

问题描述

我有一个文本文件,其中包含来自 3 个域的 http 请求(第一部分来自 reddit.com,第二部分来自 stackoverflow.com,最后来自 google.com)。我的任务是重新排列 txt 文件中 http 请求的顺序。例如,顺序将变为,google 将在第一个,然后是 reddit,stackoverflow 将是 txt 文件中的最后一个数据。

我的想法是使用 CreateFile 函数打开文件并使用 ReadFile 函数读取内容。然后我将使用分隔符“------”分割字符串。然后将 3 个拆分字符串放入 3 个变量中以操作数据。

我的想法可行还是有其他方法可以解决这个问题?还如何将 3 个拆分字符串放入 3 个变量中

先感谢您!

文本文件内部

HTTP/1.1 301 Moved Permanently
Retry-After: 0
Location: https://www.reddit.com/
Content-Length: 0
Accept-Ranges: bytes
Date: Mon, 19 Nov 2018 01:47:39 GMT
Via: 1.1 varnish
Connection: close
X-Served-By: cache-pao17440-PAO
X-Cache: HIT
X-Cache-Hits: 0k
X-Timer: S1542592059.341058,VS0,VE0
Cache-Control: private, max-age=3600
Server: snooserv

----------------------------------------
HTTP/1.1 301 Moved Permanently
Content-Type: text/html; charset=UTF-8
Location: https://stackoverflow.com/
Content-Length: 149
Accept-Ranges: bytes
Date: Mon, 19 Nov 2018 01:47:41 GMT
Via: 1.1 varnish
Connection: close
X-Served-By: cache-pao17443-PAO
X-Cache: MISS
X-Cache-Hits: 0
X-Timer: S1542592061.319674,VS0,VE69
Vary: Fastly-SSL
X-DNS-Prefetch-Control: off
Set-Cookie: prov=27060b9e-21ce-fcb4-5b43-bf2f40747e6c;        domain=.stackoverflow.com; expires=Fri, 01-Jan-2055 00:00:00 GMT; path=/; HttpOnly

<head><title>Document Moved</title></head>
<body><h1>Object Moved</h1>This document may be found <a      HREF="https://stackoverflow.com/">here</a></body>
----------------------------------------
HTTP/1.0 411 Length Required
Content-Type: text/html; charset=UTF-8
Referrer-Policy: no-referrer
Content-Length: 1564
Date: Mon, 19 Nov 2018 01:47:48 GMT

<!DOCTYPE html>
<html lang=en>
  <meta charset=utf-8>
  <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
  <title>Error 411 (Length Required)!!1</title>
  <style>

标签: c++variablessplit

解决方案


以下是我在从文件中读取数据时使用的一些常用函数以及用于解析该特定数据类型或集合的自定义函数。本例中没有直接使用其中的一些函数,但我还是提供了它们,因为这是从文件中检索数据的 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;
}

正如您从该程序生成的输出中看到的那样,我已经成功地展示了如何根据您的情况需要的分隔符类型来拆分字符串。从这里您需要做的就是根据您的标准对数据进行排序。然后将您的内容记录到流、控制台或其他文件中。


推荐阅读