c++stringstream(古くて使いやすい)

8841 ワード

前言:
以前stringstreamというクラスに触れたことがないとき、よく使われる文字列とデジタル変換関数はsscanfとsprintf関数です.最初はこの2つの関数がくわえられていると思っていましたが、結局cに属しています.c++にはストリームの概念が導入され,ストリームによる文字列と数字の変換が容易になった.ここでは、前のことをまとめて、新学を紹介します.
一般的な書式列:
%%%はパーセント記号を印刷し、変換しません.%c整数は対応するASCII文字に変換されます.%d整数は10進位に回転する.%f倍精度数字を浮動小数点数に変換します.%o整数は8進位に変換されます.%s整数は文字列に変換されます.%x整数は小文字16進位に変換されます.%X整数を大文字16進位に変換します.%n sscanf(str,"%d%n",&dig,&n),%nは、合計何ビットの文字を変換したかを表す
sprintf関数
sprintf関数のプロトタイプはint sprintf(char*str,const char*format,...)である.文字列をフォーマットします.具体的な機能は次のとおりです.
(1)数値変数を文字列に変換する.
(2)整数変数の16進数と8進数文字列を得る.
(3)複数の文字列を接続する.
int main(){
    char str[256] = { 0 };
    int data = 1024;
    // data      
    sprintf(str,"%d",data);
    //  data     
    sprintf(str,"0x%X",data);
    //  data    
    sprintf(str,"0%o",data);
    const char *s1 = "Hello";
    const char *s2 = "World";
    //     s1 s2
    sprintf(str,"%s %s",s1,s2);
    cout<<str<<endl; 
    return 0;
} 

sscanf関数
sscanf関数のプロトタイプはint sscanf(const char*str,const char*format,...)です.パラメータstrの文字列をパラメータformat文字列に基づいてデータを変換してフォーマットし、変換後の結果を対応するパラメータ内に保存します.具体的な機能は以下の通りです.
(1)フォーマットに従って文字列からデータを抽出する.整数、浮動小数点数、文字列などを文字列から取り出す.
(2)指定された長さの文字列をとる
(3)指定文字までとる文字列
(4)指定した文字セットのみを含む文字列をとる
(5)指定した文字セットまで取った文字列
もちろん、sscanfはフォーマット列「%[]」形式をサポートすることができ、興味のあることは検討することができます.
int main(){
    char s[15] = "123.432,432";
    int n;
    double f1;
    int f2;
    sscanf(s, "%lf,%d%n", &f1, &f2, &n);
    cout<<f1<<" "<<f2<<" "<<n;
    return 0;
} 

出力結果:123.432 432 11、すなわち11ビットの文字が変換された.
stringstreamクラス:
ライブラリは、istringstream、ostringstream、stringstreamの3種類を定義し、それぞれストリームの入出力操作に使用されます.
  1.stringstream::str(); returns a string object with a copy of the current contents of the stream.
  2.stringstream::str (const string& s); sets s as the contents of the stream, discarding any previous contents.
  3.stringstreamクリア、stringstream s;s.str("");
  4.任意のタイプの変換を実現
    template    out_type convert(const in_value&t){stringstream stream;stream<>result;//resultに値return resultを書き込む;}
int main(){
    string s = "1 23 # 4";
    stringstream ss;
    ss<<s;
    while(ss>>s){
        cout<<s<<endl;
        int val = convert<int>(s);
        cout<<val<<endl;
    }
    return 0;
}

出力:1 1 23 23#0 4
  
ちなみに、今日もstringstreamというクラスを使って、ツリーのシーケンス化と逆シーケンス化をしました.
タイトルリンク:http://www.lintcode.com/zh-cn/problem/binary-tree-serialization/
ツリーのシーケンス化と逆シーケンス化
アルゴリズムを設計し,コードを記述して二叉木をシーケンス化し,逆シーケンス化する.ツリーを1つのファイルに書き込むことを「シーケンス化」と呼び、ファイルを読み込んで同じツリーを再構築することを「逆シーケンス化」と呼ぶ.ツリーを逆シーケンス化またはシーケンス化する方法には制限はありません.ツリーを文字列にシーケンス化し、文字列を元のツリー構造に逆シーケンス化できることを確認する必要があります.
考え方:
二叉木のシーケンス化は、空のサブツリーが'#'で表される順に巡回することによって確立される.逆シーケンス化の場合は、'#'に遭遇すると再帰構造が停止します.またシーケンス化の場合は整数をstringstreamで文字列に変換し,逆シーケンス化は文字列をstringstreamで整数に変換する.
/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */
class Solution {
public:
    /**
     * This method will be invoked first, you should design your own algorithm 
     * to serialize a binary tree which denote by a root node to a string which
     * can be easily deserialized by your own "deserialize" method later.
     */
    bool first;
    
    template<typename out_type, typename in_value>
    out_type convert(const in_value & t){
        stringstream stream;
        stream<<t;//     
        out_type result;//        
        stream>>result;// result    
        return result;
    }
    
    void pre_order(TreeNode *root, string &s){
        if(root){
            string tmp = convert<string>(root->val);
            if(!first)
                s+= " "+tmp;
            else {
                first = false;
                s+=tmp;
            }
            pre_order(root->left, s);
            pre_order(root->right, s);
        } else {
            if(first)
                s+='#';
            else {
                first = false;
                s+=" #";
            }
        }
    }
    string serialize(TreeNode *root) {
        // write your code here
        string s="";
        first = true;
        pre_order(root, s);//       
        return s;
    }
    
    stringstream ss;
    void buildT(TreeNode * &T){
        string s;
        ss>>s;
        if(s == "#") return ;
        int val = convert<int>(s);
        T = new TreeNode(val);
        buildT(T->left);
        buildT(T->right);
    }
    
    /**
     * This method will be invoked second, the argument data is what exactly
     * you serialized at method "serialize", that means the data is not given by
     * system, it's given by your own serialize method. So the format of data is
     * designed by yourself, and deserialize it here as you serialize it in 
     * "serialize" method.
     */
    TreeNode *deserialize(string data) {
        // write your code here
        TreeNode *T = NULL;
        ss.str("");
        ss<<data;
        buildT(T);
        return T;
    }
};