2012-06-04 6 views
-1

Je fais une simulation de quelques modèles Ising (treillis avec 1 ou -1) et je ne veux pas utiliser de fichiers (ne pas entrer dans détails ici, je suppose: D). Donc, la chose est, j'utilise stringstreams pour formater le nom de fichier de données & de données pour ensuite les séparer avec bash. Montrez-vous un exemple de codestd :: stringstream ne nomme pas un type (Global)

#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 ; 
} 

Une sortie régulière de ce programme « sstreams.o » serait

~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 

Vous obtenez la bonne idée? De ce flux de réflexion, ce que j'écris est ./sstreams.o 10 | bash donc on obtient des fichiers bien séparés. Mais le problème est:

Je deviens fatigué d'écrire ces lignes chaque fois que je veux utiliser print2bash()

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

À cause de cela, je veux mettre (oh l'ironie!) les ss comme des variables globales (je ne sais pas si c'est ce genre d'affreux donc le compilateur ne me laisse pas le faire: je ne suis qu'un physicien). Donc, même si j'écris std::stringstream pour les variables ss après les #include s (et using namespace std), je reçois toujours l'erreur

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 

du compilateur. J'espère que vous pouvez m'aider.


EDIT: [RESOLU]

Le problème est que si je voulais déclarer une stringstream de main() il a échoué à cause des membres clear & str où hors contexte afin qu'ils ne peuvent pas être utilisé. En outre, cette utilisation était inutile car stringstream s sont créés avec des contenus vides, comme @jpalecek et @umlaeute l'ont fait remarquer.

J'ai déclaré les stringstream s sur principale et comprennent un clear() + str("") sur print2bash() pour donner le résultat souhaité:

#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 ; 
} 

une sortie régulière de ./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 

Merci pour tout

+1

Ok, je Je ne comprends vraiment pas pourquoi vous faites cela si compliqué. les appels à "clear" et "str" ​​juste après la construction n'ont aucun effet. –

+2

Je ne comprends vraiment pas votre approche globale. Il semble que votre programme C++ génère un script qui fait presque la même chose que votre programme C++. Êtes-vous sûr que c'est le meilleur moyen? –

+2

@ BjörnPollex: il est un physicien, vous devez comprendre cela. – jpalecek

Répondre

3

Vous n'avez pas besoin d'appeler

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

car les objets stringstream sont automatiquement créés avec des contenus vides. Cela vous laisse avec

stringstream ssbash; 
stringstream ssfile; 

que pourrait une déclaration globale, mais ne le font pas, car il ne vous aidera pas. Vous devriez l'effacer chaque fois que vous l'utilisez.

Si vous ne voulez pas répéter la déclaration sur et plus, vous pouvez les remplacer par une macro

#define DECLARE_STREAMS \ 
    stringstream ssbash; \ 
    stringstream ssfile; 

ou mieux

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

utilisé comme ceci: DECLARE_STREAMS(ssbash, ssfile). Mais la meilleure solution (et la plus propre) serait de refactoriser le code qui formate les données en une seule fonction. De cette façon, vous n'auriez pas à vous soucier de répéter la déclaration de flux.

BTW pourquoi avez-vous au lieu d'écrire dans un fichier avec C++ script d'émission que l'écriture est au-delà de moi. C/C++ vous interdit d'avoir du code exécuté en dehors des fonctions (à l'exception des déclarations/définitions de variables)

+1

Merci l'homme. lol pour la dernière ligne. Je vais vous dire pourquoi! Disons que vous voulez écrire dans 20 fichiers différents avec 5 fichiers auxiliaires chacun. C'est 100 fichiers. Garder la trace d'eux est un mal de tête massif, parce que chacun signifie quelque chose et, je ** ai ** besoin d'eux séparés à la fin pour faire l'analyse. De cette façon, avec 'ssfile' pour les noms de fichiers et' ssbash' pour le contenu, il suffit de faire une boucle. Et oui, je suis physicien donc je ne sais pas ce que je fais avec C++. C'est pourquoi je suis là :) – stringparser

+0

'# declare' n'est pas C++, n'est-ce pas? –

+0

@FredLarson: '# declare' est une directive de préprocesseur, qui fait partie de C++. – jpalecek

2

donc ce qui suit est illégale:

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 

si vous avez besoin d'appeler clear() et str(), alors vous doit faire dans une fonction initilializing

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

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

Merci. C'est clair pourquoi je ne pouvais pas. Donc, je ne peux pas le faire à cause du 'clear' et' str' ne sont pas prêts à utiliser.C'est bien... – stringparser