www.mikrocontroller.net

Forum: Compiler & IDEs basic_ofstream nur mit char?


Autor: Philipp Burch (philipp_burch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

gcc mag mich irgendwie gar nicht. Folgendes Problem:
#include <iostream>
#include <fstream>

using namespace std;

int main(int argc, char **argv) {
    ofstream of("/home/phip/test/a.bin", ios_base::binary);
    basic_ofstream<unsigned char> bof("/home/phip/test/b.bin", ios_base::binary);

    char a[] = {'a', 'b', 'c'};
    unsigned char b[] = {0x61, 0x62, 0x63};

    of.write(a, 3);
    bof.write(b, 3);

    cout << "write of " << (of.good() ? "ok.\n" : "failed.\n");
    cout << "write bof " << (bof.good() ? "ok.\n" : "failed.\n");
}
liefert
write of ok.
write bof failed.
Aber warum? Definiere ich bof als basic_ofstream<char>, dann geht's, 
allerdings entspricht das ja auch exakt ofstream. Warum gibt es da ein 
Problem mit unsigned char (Bzw. mit allem anderen als <char>, auch mit 
<short> schlägt write() fehl)?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein Quelltext sieht m.E. korrekt aus, ich hätte auch
erwartet, dass es klappt.

Ich habe das mal versucht, nachzuvollziehen.
Unter Linux mit dem gcc 4.3.2 habe ich den gleichen Effekt.
Wenn man vor dem Schreiben mit
  bof.exceptions( std::ios::eofbit|std::ios::failbit|std::ios::badbit );
einschaltet, daß bei Fehlern eine Ausnahme gewerfen wird, dann
passiert genau das beim Schreiben in basic_ios.h an dieser Stelle:
  template<typename _Facet>
    inline const _Facet&
    __check_facet(const _Facet* __f)
    {
      if (!__f)
  __throw_bad_cast();
      return *__f;
    }

Weder bei Stroustrup noch bei Josuttis habe ich etwas gesehen,
was da seitens des Aufrufers noch fehlen könnte (außer dass man
bei anderen basic_ofstream<> als char und wchar ggf. explizit die
Datei mit open() öffnen müsste, aber daran liegt es nicht).

Deshalb würde ich mal dreist unterstellen, daß hier die g++-Libs
schwächeln.

Auch wenn es mir schwer fällt zu sagen, aber mit VS2005 klappt
das Schreiben wie erhofft.

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In

  http://www.unc.edu/depts/case/pgi/pgC++_lib/stdlib...

steht geschrieben:

  "Users have to provide specialization for char_traits if they use
  other character types than char and wchar_t."

Wahrscheinlich hängt dein Problem damit zusammen. Ich vermute, dass die
Verwendung anderer Typen als char und wchar_t durch Normalsterbliche gar
nicht vorgesehen ist.

Normalsterbliche nehmen IMHO einfach einen ofstream und casten beim
Aufruf von write den unsigned-char-Zeiger in einen char-Zeiger.

Auch ein auf einen anderen Zeichentyp spezialisierter basic_ostream
versagt spätestens dann, wenn man der write-Methode unterschiedliche
Datentypen binär schreiben möchte, was ja durchaus üblich ist. Dann
hilft sowieso nur noch das Casten des Zeigers.

> Auch wenn es mir schwer fällt zu sagen, aber mit VS2005 klappt das
> Schreiben wie erhofft.

Ich vemute, MS hat das char_traits<char> etwas allgemeiner definiert, so
dass es auch für unsigned char funktioniert. Oder sie haben zusätzlich
ein char_traits<unsigned char> definiert. Wenn ich das obige Zitat aber
richtig verstanden habe, ist so etwas im Standard nicht vorgeschrieben.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja, ich dachte auch schon daran, dass die Spezialisierung für
char_traits fehlt und habe die ausprobiert und eingefügt:
#include <cstring>
namespace std
{
  template<> struct char_traits<unsigned char>
  {
    typedef unsigned char   char_type;
    typedef int             int_type;
    typedef streampos       pos_type;
    typedef streamoff       off_type;
    typedef mbstate_t       state_type;

    static void assign( unsigned char &c1, const unsigned char &c2 )
    {
      c1 = c2;
    }

    static bool eq( const unsigned char &c1, const unsigned char &c2 )
    {
      return c1==c2;
    }

    static bool lt( const unsigned char &c1, const unsigned char &c2 )
    {
      return c1<c2;
    }

    static size_t length( const unsigned char *s )
    {
      return std::strlen( (const char*)s );
    }

    static int compare( const unsigned char *s1,
                        const unsigned char *s2,
                        size_t n
                        )
    {
      return std::memcmp( (const char*)s1,
                          (const char*)s2,
                          n
                          );
    }

    static unsigned char *copy( const unsigned char *s1,
                                const unsigned char *s2,
                                size_t n
                                )
    {
      return (unsigned char*)std::memcpy( (char*)s1,
                                          (const char*)s2,
                                          n
                                          );
    }

    static unsigned char *move( const unsigned char *s1,
                                const unsigned char *s2,
                                size_t n
                                )
    {
      return (unsigned char*)std::memmove( (char*)s1,
                                           (const char*)s2,
                                           n
                                           );
    }

    static unsigned char *assign( unsigned char *s,
                                  size_t n,
                                  unsigned char c
                                  )
    {
      return (unsigned char*)std::memset( (char*)s, (char)c, n );
    }

    static const unsigned char *find( const unsigned char *s,
                                      size_t n,
                                      const unsigned char &c
                                      )
    {
      return (const unsigned char *)std::memchr( (const char *)s,
                                                 (int)c,
                                                 n
                                                 );
    }

    static int eof()
    {
      return EOF;
    }

    static int to_int_type( const unsigned char &c )
    {
      return (int)c;
    }

    static unsigned char to_char_type( const int &i )
    {
      return (unsigned char)i;
    }

    static int not_eof( const int &i )
    {
      return i!=EOF ? i : !EOF;
    }

    static bool eq_int_type( const int &i1, const int &i2 )
    {
      return i1==i2;
    }
  };
}

Das ändert aber nichts am Verhalten...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.