2009-08-31 11 views
3

J'ai une structure de données définie commedonnées personnalisées iostream

struct myDataStruct 
{ 
    int32_t header; 
    int16_t data[8]; 
} 

et je veux prendre un flux de caractères et de le transformer en un flux myData. Quelle classe de flux devrais-je étendre? Je voudrais créer une classe de flux personnalisé afin que je puisse faire des choses comme

myDataStruct myData; 
myDataStruct myDataArray[10]; 

myDataStream(ifstream("mydatafile.dat")); 
myDataStream.get(myData); 
myDataStream.read(myDataArray, 10); 
+0

Voulez-vous avoir une entrée formatée (forme textuelle) ou lire à partir d'une représentation binaire des données (les noms de champs ressemblent à un message) –

+0

les données représentées sont binaires. Chaque paquet de données commence par une séquence d'en-tête et contient 8 échantillons de données. Je veux transformer cela en 8 flux d'échantillons. Ceux-ci pourraient alors être utilisés dans un autre processus ou écrits dans un fichier binaire. – HazyBlueDot

Répondre

5

Au lieu de myDataStream.get(myData), ce que vous faites est la surcharge operator>> pour votre type de données:

std::istream& operator>>(std::istream& is, myDataStruct& obj) 
{ 
    // read from is into obj 
    return is; 
} 

Si vous voulez lire dans un tableau, il suffit d'écrire une boucle:

for(std::size_t idx=0; idx<10; ++idx) 
{ 
    myDataStruct tmp; 
    if(is >> tmp) 
    myDataArray[idx] = tmp; 
    else 
    throw "input stream broken!"; 
} 

en utilisant un modèle de fonction, vous devez également en mesure de surcharger l'opérateur pour les tableaux sur la droite si de (mais ceci je n'ai jamais essayé):

template< std::size_t N > 
std::istream& operator>>(std::istream& is, myDataStruct (&myDataArray)[N]) 
{ 
    // use loop as above, using N instead of the 10 
} 

Mais je ne peux pas décider si c'est magnifique ou méprisable.

+1

Ou surcharger l'opérateur >> (std :: istream & est, std :: vector & obj) pour les tableaux et cacher la boucle aussi (ne fonctionnera pas aussi facile pour les tableaux C) – Eugene

+0

@Eugene: Merci pour le commentaire , J'ai prolongé mon message sur une idée que ce commentaire m'a donné. – sbi

+0

Puisque nous ajoutons des idées (et même si je crois que la question traite de la représentation binaire et pas d'entrée/sortie formatée), vous pouvez essayer les algorithmes std :: copy/std :: copy_n si vous faites confiance à l'exactitude de l'entrée. –

0

Si vous travaillez avec une entrée non formatée, vous devriez probablement lire directement sous forme binaire. Habituellement, vous utiliseriez une directive spécifique au compilateur pour créer des structures de données sans remplissage, puis simplement lire/écrire à partir d'un fichier.

// Gcc 
#pragma pack(1) // option 1: pragmas 
struct frame { 
    std::uint32_t header; 
    std::uint16_t data[8]; 
} __attribute((packed)); // option 2: packed attribute 
#pragma pack(0) 

bool operator==(data const & lhs, data const & rhs) 
{ 
    bool result = lhs.header == rhs.header; 
    for (int i = 0; i < 8; ++i) 
    { 
     result &= lhs.data[i] == rhs.data[i]; 
    } 
    return result; 
} 

int main() 
{ 
    frame data = { 10, 1, 2, 3, 4, 5, 6, 7, 8 }; 

    std::ofstream out("data.bin", ofstream::binary); 
    out.write(reinterpret_cast<char*>(&data), sizeof(data)); 
    out.close(); 

    std::ifstream in("data.bin", ifstream::binary); 
    frame readed; 
    in.read(reinterpret_cast<char*>(&readed), sizeof(readed)); 
    in.close(); 

    std::cout << (readed == data) << std::endl; // 1 
} 

La directive du compilateur pour désactiver le rembourrage pour VS peut être différent (je crois que la directive pragma fonctionne aussi bien dans gcc et VS, mais je l'ai toujours utilisé l'attribut).