Forum: Compiler & IDEs basic_ofstream nur mit char?


von Philipp B. (philipp_burch)


Lesenswert?

Hallo zusammen,

gcc mag mich irgendwie gar nicht. Folgendes Problem:
1
#include <iostream>
2
#include <fstream>
3
4
using namespace std;
5
6
int main(int argc, char **argv) {
7
    ofstream of("/home/phip/test/a.bin", ios_base::binary);
8
    basic_ofstream<unsigned char> bof("/home/phip/test/b.bin", ios_base::binary);
9
10
    char a[] = {'a', 'b', 'c'};
11
    unsigned char b[] = {0x61, 0x62, 0x63};
12
13
    of.write(a, 3);
14
    bof.write(b, 3);
15
16
    cout << "write of " << (of.good() ? "ok.\n" : "failed.\n");
17
    cout << "write bof " << (bof.good() ? "ok.\n" : "failed.\n");
18
}
liefert
1
write of ok.
2
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)?

von Klaus W. (mfgkw)


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
1
  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:
1
  template<typename _Facet>
2
    inline const _Facet&
3
    __check_facet(const _Facet* __f)
4
    {
5
      if (!__f)
6
  __throw_bad_cast();
7
      return *__f;
8
    }

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.

von yalu (Gast)


Lesenswert?

In

  http://www.unc.edu/depts/case/pgi/pgC++_lib/stdlibcr/cha_3696.htm

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.

von Klaus W. (mfgkw)


Lesenswert?

ja, ich dachte auch schon daran, dass die Spezialisierung für
char_traits fehlt und habe die ausprobiert und eingefügt:
1
#include <cstring>
2
namespace std
3
{
4
  template<> struct char_traits<unsigned char>
5
  {
6
    typedef unsigned char   char_type;
7
    typedef int             int_type;
8
    typedef streampos       pos_type;
9
    typedef streamoff       off_type;
10
    typedef mbstate_t       state_type;
11
12
    static void assign( unsigned char &c1, const unsigned char &c2 )
13
    {
14
      c1 = c2;
15
    }
16
17
    static bool eq( const unsigned char &c1, const unsigned char &c2 )
18
    {
19
      return c1==c2;
20
    }
21
22
    static bool lt( const unsigned char &c1, const unsigned char &c2 )
23
    {
24
      return c1<c2;
25
    }
26
27
    static size_t length( const unsigned char *s )
28
    {
29
      return std::strlen( (const char*)s );
30
    }
31
32
    static int compare( const unsigned char *s1,
33
                        const unsigned char *s2,
34
                        size_t n
35
                        )
36
    {
37
      return std::memcmp( (const char*)s1,
38
                          (const char*)s2,
39
                          n
40
                          );
41
    }
42
43
    static unsigned char *copy( const unsigned char *s1,
44
                                const unsigned char *s2,
45
                                size_t n
46
                                )
47
    {
48
      return (unsigned char*)std::memcpy( (char*)s1,
49
                                          (const char*)s2,
50
                                          n
51
                                          );
52
    }
53
54
    static unsigned char *move( const unsigned char *s1,
55
                                const unsigned char *s2,
56
                                size_t n
57
                                )
58
    {
59
      return (unsigned char*)std::memmove( (char*)s1,
60
                                           (const char*)s2,
61
                                           n
62
                                           );
63
    }
64
65
    static unsigned char *assign( unsigned char *s,
66
                                  size_t n,
67
                                  unsigned char c
68
                                  )
69
    {
70
      return (unsigned char*)std::memset( (char*)s, (char)c, n );
71
    }
72
73
    static const unsigned char *find( const unsigned char *s,
74
                                      size_t n,
75
                                      const unsigned char &c
76
                                      )
77
    {
78
      return (const unsigned char *)std::memchr( (const char *)s,
79
                                                 (int)c,
80
                                                 n
81
                                                 );
82
    }
83
84
    static int eof()
85
    {
86
      return EOF;
87
    }
88
89
    static int to_int_type( const unsigned char &c )
90
    {
91
      return (int)c;
92
    }
93
94
    static unsigned char to_char_type( const int &i )
95
    {
96
      return (unsigned char)i;
97
    }
98
99
    static int not_eof( const int &i )
100
    {
101
      return i!=EOF ? i : !EOF;
102
    }
103
104
    static bool eq_int_type( const int &i1, const int &i2 )
105
    {
106
      return i1==i2;
107
    }
108
  };
109
}

Das ändert aber nichts am Verhalten...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.