std :: stringstream没有命名类型(全局)

时间:2012-06-04 13:42:39

标签: c++ stringstream

我正在模拟几个Ising模型(格子有1或-1),我不想使用文件(这里不打算详细说明,我猜:D)。所以,问题是,我正在使用stringstreams来格式化数据和放大器。数据的文件名然后用bash分隔它们。给你看一个示例代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>    
#include <iostream>
#include <sstream>
#include <string>    
using namespace std;
void print2bash(string file, string data);

int main(int argc, char *argv[]){

    int i, j, n = atoi(argv[1]);
    // I want to put this outside main() {
    stringstream ssbash;    ssbash.clear(); ssbash.str(""); 
    stringstream ssfile;    ssfile.clear(); ssfile.str("");
    //} 
    //  So I don't have to do ss.clear and ss.str("") every time before using them

    ssfile << "this_" << n << "_is_the_filename.dat" << endl;
    for(i = 0; i < n ; i++){
        for(j = 0; j < n; j++)
            ssbash << i*n+j << "\t";
        ssbash << endl;
    }

    print2bash( ssfile.str(), ssbash.str() );

    return 0;
}
// print2bash(); prints string data; to string file; 
//               This will be used to separate data 
//               afterwards ( i.e. ./Ising.o <arguments> | bash )  
void print2bash(string file, string data){

    stringstream ssbash;    ssbash.clear(); ssbash.str(data);       
    stringstream output;    output.clear(); output.str("");
    string line;

    output << "for((i=0;i<1;i++)) do "<< endl; // Buffer all to bash at once
    while( getline(ssbash,line) )
        output << "    echo \"" << line << "\";" << endl;

    output << "done >> " << file; // Appending
    cout << output.str() << endl;

    ssbash.clear(); ssbash.str("");

    return ;
}

这个“sstreams.o”程序的常规输出将是

~work/Ising$ ./sstreams.o 5
for((i=0;i<1;i++)) do 
    echo "0 1 2 3 4 ";
    echo "5 6 7 8 9 ";
    echo "10 11 12 13 14 ";
    echo "15 16 17 18 19 ";
    echo "20 21 22 23 24 ";
done >> this_5_is_the_filename.dat

你明白了吗?从这个思维流程中,我实际写的是./sstreams.o 10 | bash,因此可以得到很好的分离文件。但问题是:

每次我想使用print2bash()时,我都厌倦了写这行(讽刺的是哦!)

stringstream ssbash;    ssbash.clear(); ssbash.str(""); 
stringstream ssfile;    ssfile.clear(); ssfile.str("");

因此,我想把ss作为全局变量(不知道这是不是很糟糕,所以编译器不允许我这样做:我只是一个物理学家)。所以,即使我在std::stringstream s(和#include)之后为ss变量写using namespace std,我仍然会收到错误

error: ‘ssbash’ does not name a type
error: ‘ssbash’ does not name a type
error: ‘ssfile’ does not name a type
error: ‘ssfile’ does not name a type

来自编译器。希望你能帮助我。


编辑: [已解决]

问题在于,如果我想从stringstream声明main(),则由于成员clear而导致其失败str在上下文之外,因此无法使用它们。除此之外,这种使用是不必要的,因为stringstream是用空内容创建的,正如@jpalecek和@umlaeute指出的那样。

我已将stringstream声明为主要内容,并在clear()上添加str("") + print2bash()以提供所需结果:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>    
#include <iostream>
#include <sstream>
#include <string> 
#include <vector>

using namespace std;

stringstream ssbash, ssfile;

void print2bash(string file, string data);

int main(int argc, char *argv[]){

    int i, j, n = atoi(argv[1]), p, np = atoi(argv[2]);
    vector< vector<int> > chain;    chain.resize(n*n);

    for( p = 0; p < np; p++){

        ssfile << "chain_p="<< p << "_filename.dat" << endl;
        for(i = 0; i < n ; i++){
            for(j = 0; j < n; j++){

                chain[p].push_back( i*n + j );
                ssbash << i*n+j << "\t";
            }
            ssbash << endl;
       }
       print2bash( ssfile.str(), ssbash.str() );
    }

    return 0;
}
void print2bash(string file, string data){

    ssbash.str(data);
    stringstream output;
    string line;

    output << "for((i=0;i<1;i++)) do "<< endl; // Buffer all to bash at once
    while( getline(ssbash,line) )
       output << "    echo \"" << line << "\";" << endl;

    output << "done >> " << file; // Appending 
    cout << output.str() << endl;

    ssfile.clear(); ssfile.str("");
    ssbash.clear(); ssbash.str("");

    return ;
}

常规输出./sstreams.o

~/work/Ising$ ./sstreams.o 4 2
for((i=0;i<1;i++)) do 
    echo "0 1   2   3   ";
    echo "4 5   6   7   ";
    echo "8 9   10  11  ";
    echo "12    13  14  15  ";
done >> chain_p=0_filename.dat

for((i=0;i<1;i++)) do 
    echo "0 1   2   3   ";
    echo "4 5   6   7   ";
    echo "8 9   10  11  ";
    echo "12    13  14  15  ";
done >> chain_p=1_filename.dat

感谢您的一切

2 个答案:

答案 0 :(得分:3)

您无需致电

ssbash.clear(); ssbash.str("");

因为stringstream对象是使用空内容自动创建的。那就离开了你

stringstream ssbash;
stringstream ssfile;

可以是全球声明,但不要,因为它不会帮助你。每次使用时都必须清除它。

如果您不喜欢一遍又一遍地重复声明,可以用宏替换它们

#define DECLARE_STREAMS \
  stringstream ssbash; \
  stringstream ssfile;

或更好

#define DECLARE_STREAMS(a, b) \
  stringstream a; \
  stringstream b;

使用如下:DECLARE_STREAMS(ssbash, ssfile)

但最好(也是最干净)的解决方案是重构将数据格式化为单个函数的代码。这样,您就不必担心重复流声明了。

BTW为什么你不是用C ++写一个文件而不是写一个文件来写作文字超出我的范围。

答案 1 :(得分:2)

C / C ++禁止你在函数之外执行代码(除了变量声明/定义)。

因此以下是非法的:

int main(int argc, char**argv) {
   return 0;
}
stringstream ssbash; // OK
ssbash.clear(); // ouch; procedural programming outside of context
ssbash.str(""); // ouch; procedural programming outside of context

如果你需要调用clear()和str(),那么必须在初始化函数中执行

static stringstream ssbash, ssfile;
void initSS(void) {
   ssbash.clear(); ssbash.str("");
   ssfile.clear(); ssfile.str("");
}

int main(int argc, char**argv) {
   initSS();
   // ....
   return 0;
}