1
votes

Impossible de lire le fichier texte avec une grille booléenne en vecteurs de vecteurs

J'ai un fichier texte qui se compose d'une grille booléenne comme la structure comme indiqué. Maintenant, j'essaye de lire le fichier texte dans une grille vector > . Mais je suis incapable de le faire. Mon code se termine sans aucune erreur et l'exécution ne se déplace pas dans la boucle while .

Le fichier texte contient l'exemple ci-dessous:

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
using namespace std;

vector<vector<bool> >read_grid(const string &filename)
{
    vector<vector<bool> > gridvector;
    // Open the File
    ifstream in(filename.c_str());
    string str;
    bool tempb;// Check if object is valid
    if(!in)
    {
        cout<< "Cannot open the File : "<<filename<<endl;
        return gridvector;
    }

    // Read the next line from File untill it reaches the end.
    while (getline(in, str))
    {
        istringstream iss(str);
        vector<bool> myvector;
        while(iss>>tempb)
        {
            myvector.push_back(tempb);
        }

        gridvector.push_back(myvector);
    }

    //Close The File
    in.close();
    return gridvector;
}
 void display_grid(vector< vector<bool> >& grid) 
{
// this generates an 8 x 10 grid and sets all cells to ’0’
//vector<vector<bool> >grid(8, vector<bool>(10, 1));// printing the grid
    for(int x = 0; x < grid.size(); x++)
    {
        for(int y = 0;y < grid[x].size();y++)
        {
         // cout<<grid[x].size()<<'\n';
            cout << grid[x][y];
        }
        cout << endl;
    }
   cout<<"grid at position [1][2] is: "<< grid[1][2]<<'\n';
}
int main ()
{
    const string b_file = "intial_grid.txt";
    vector< vector<bool> > grid_copy = read_grid(b_file);
    display_grid(grid_copy);
    return 0;
}
00000000000000001111111110000
000000100000000010100000100
0000000000000000111111111000
00000000000000011111111111000
0001000000000011111111111110
00000000000000011000000011000
00000000000000100010001000100
00000000000000100000100000
00100011111111111111111001110
00000000000011111000100000001


12 commentaires

Où les choses commencent-elles exactement à mal tourner? Que se passe-t-il si vous n'utilisez pas une fonction distincte (pensez à exemple reproductible minimal )? Veuillez également formater / indenter votre code de manière cohérente, de préférence en utilisant un formateur automatique. En tant que nouvel utilisateur, suivez également la visite et lisez Comment demander .


Je ne sais pas où cela va mal mais je vois que le contrôle ne va pas à l'intérieur pendant que (iss << tempb) du tout


Vérifiez std :: bitset


Une question, se pourrait-il que les bits avec 0 soient ignorés pour l'optimisation? et devons-nous préciser que nous voulons les inclure? J'ai eu un problème similaire et je l'ai résolu de cette façon


Non @vincenzopalazzo, j'ai besoin de lire toutes les lignes et colonnes de zéros et de uns dans une grille de vecteur


" Il sort avec 'état de sortie -1'. " - cela signifie que votre code plante avant d'atteindre la fin de main () . Exécutez le code dans un débogueur et découvrez ce qui se passe réellement


J'utilise un compilateur en ligne mais je vais faire le débogage @RemyLebeau


pouvez-vous poster la méthode display_grid (), s'il vous plaît?


Je viens de faire @vincenzopalazzo


Remarque vector est tellement différent d'un vecteur qu'il obtient sa propre page de documentation . Beaucoup de pièges là-dedans.


Dans votre cas, iss >> tempb échouera car il attend une valeur booléenne, c'est-à-dire un peu, mais reçoit à la place une chaîne de 0 et 1.


merci @CaptainDaVinci toute solution à ce problème sera très utile


3 Réponses :


0
votes

L'erreur 'exit status -1' est causée à la fonction display_grid () , les composants sont vectoriels et l'accès au vecteur est verctorVariable.at ();

une autre erreur est while (iss >> tempb) parce que votre résultat est toute ligne, vous résolvez ce problème avec ce code

void display_grid(vector< vector<bool> >& grid)
{
// this generates an 8 x 10 grid and sets all cells to ’0’
//vector<vector<bool> >grid(8, vector<bool>(10, 1));// printing the grid

    for(int x = 0; x < grid.size(); x++)
    {
        cout<<"addin another elemen";
        for(int y = 0;y < grid[x].size();y++)
        {
             cout<<"addin another elemen";

            cout << grid.at(x).at(y);
        }
        cout << endl;
    }

    //cout<<"grid at position [1][2] is: "<< grid[1][2]<<'\n';
}


4 commentaires

mais où est-ce que je pousse les valeurs booléennes dans myvector dans le code ci-dessus?


Merci pour grid_display mais le code d'entrée, je ne pense pas que cela fonctionnera pour stocker les valeurs booléennes dans le vecteur


Je ne pense pas que le at dans grid.at (x) .at (y) soit utile ici. Les boucles for garantissent que x et y sont dans les limites.


Si vous allez lire des caractères individuels à partir d'une ligne, il n'y a aucun intérêt à utiliser istringstream . Vous pouvez parcourir la ligne directement: for (char c: str)



3
votes

Le flux de chaînes renvoie vrai en cas de lecture réussie et faux en cas d'erreur.

Dans votre cas, iss >> tempb échouera car il attend une valeur booléenne, c'est-à-dire un peu, mais reçoit à la place une chaîne de 0 et 1.

Vous pouvez vérifier cela après la première lecture de iss >> tempb ,

// Read the next line from File untill it reaches the end.
    while (getline(in, str))
    {
        istringstream iss(str);
        vector<bool> myvector;
        char bit;
        while(iss >> bit)
        {
            myvector.push_back(bit == '1' ? true : false);
        }

        gridvector.push_back(myvector);
    }

Vous pouvez à la place parcourir les caractères individuellement.

if (iss.fail()) {
    cout << "Failed to read\n";
}


1 commentaires

Cela fonctionne beaucoup, je suis capable d'obtenir un vecteur de vecteur avec un fichier lu.



1
votes

La réponse est donnée et acceptée. Les erreurs ont été mentionnées dans les commentaires.

Quoi qu'il en soit, je voudrais montrer une approche "plus" C ++, en utilisant des algorithmes std.

L'idée est que nous voulons lire une ligne avec des valeurs booléennes . J'ai donc conçu un nouveau type de données, une classe, qui contient de telles données et sait également comment les lire. À mon humble avis, les données et les méthodes devraient être regroupées dans une classe.

Cela réduira également considérablement les lignes de code dans la fonction main et globalement. Dans la définition de la variable et via le constructeur de plage, toutes les données seront lues.

J'ai ajouté une sortie de débogage supplémentaire, afin que le résultat puisse être visualisé. Bien sûr, l'accès aux données à l'aide de l'opérateur d'index [] [] fonctionnera également.

Veuillez consulter:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <sstream>

std::istringstream testData(
R"#(00000000000000001111111110000
000000100000000010100000100
0000000000000000111111111000
00000000000000011111111111000
0001000000000011111111111110
00000000000000011000000011000
00000000000000100010001000100
00000000000000100000100000
00100011111111111111111001110
00000000000011111000100000001
)#");


// We want to have a data type for one line with boolean values in a string
struct Line {
    // We overwrite the extractor operator >> . With that we can easily read a complete line
    friend std::istream& operator >> (std::istream& is, Line& l) { 
        std::string line{}; l.lineOfBool.clear(); getline(is, line);
        std::transform(line.begin(), line.end(), std::back_inserter(l.lineOfBool), [](const char c) { return (c == '1') ? true : false; });
        return is; }

    // Type cast operator to expected value
    operator std::vector<bool>() const { return lineOfBool; }
    // The data
    std::vector<bool> lineOfBool{};
};

int main()
{
    // Define the variable that will hold all bool data of the complete file. The range constructor will read the file 
    std::vector<std::vector<bool>> fileAsStrings{std::istream_iterator<Line>(testData),std::istream_iterator<Line>() };

    // For debug purposes: Copy all Data to std::cout
    std::for_each(fileAsStrings.begin(), fileAsStrings.end(), [](const std::vector<bool> & l) {std::copy(l.begin(), l.end(), std::ostream_iterator<bool>(std::cout, " ")); std::cout << '\n'; });

    return 0;
}

Remarque: je lis depuis un istringstream, initialisé avec une chaîne brute. Donc, aucune différence avec la lecture d'un fichier.

Peut-être que quelqu'un trouvera cette solution utile.


2 commentaires

Pourquoi pas std :: transform (line.begin (), line.end (), l.lineOfBool.begin (), [] (const char c) {return (c == '1')? True: false;}); de cette façon, il n'est pas nécessaire d'appeler l.lineOfBool.clear () sur chaque ligne.


@CaptainDaVinci. Correct. Merci! Encore mieux! +1