[C++] Verschil tussen std::cout en printf

Pagina: 1
Acties:

  • yiko
  • Registratie: September 2003
  • Laatst online: 20-04-2025
Ik zit hier nu met iets dat ik niet helemaal begrijp. Ik heb bezig om met behulp van libxml2 een xml file te gaan lezen. Ik heb nu een dood simpele class gemaakt om via de libxml2 functies een bepaalde xml file te gaan dumpen naar stdout.

Ik heb volgende code om een xmlNodePtr te gaan dumpen (recursief).
C++:
1
2
3
4
5
6
7
8
9
10
void XmlDumper::DumpNode( xmlDocPtr doc , xmlNodePtr node )
{
        while( node != NULL ) {
                xmlChar * nodeText = xmlNodeListGetString( doc , node , 1 );
                std::cout << "(1)<" << node->name << ">" << node->content << "</" << node->name << ">" << std::endl;
                printf( "(2)<%s>%s</%s>\n" , node->name , node->content , node->name );
                XmlDumper::DumpNode( doc , node->xmlChildrenNode );
                node = node->next;
        }
}
Het vreemde is dat ik de lijn met (1) nooit te zien krijg, terwijl de lijn met (2) wel goed tevoorschijn komt. Er moet dus iets verkeerds zijn met std::cout, maar ik zie niet wat, aangezien de printf wel vrolijk de inhoud print.
De members node->name en node->content zijn van het type "xmlChar *" , waarbij xmlChar een gewone define is van "unsigned char".

Wat doe ik verkeerd ?

  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
Krijg je de *hele lijn* met (1) niet te zien, of krijg je alleen de inhoud van de variabelen niet afgedrukt voor lijn (1)?

Maakt wel een verschil denk ik.

  • yiko
  • Registratie: September 2003
  • Laatst online: 20-04-2025
De ganse lijn wordt niet getoond.
Als ik een node heb met de naam "test" en de inhoud "boe" , krijg ik tezien :
code:
1
(2)<test>boe</test>

Terwijl het zou moeten zijn :
code:
1
2
(1)<test>boe</test>
(2)<test>boe</test>

  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
Aha. Eh, probeer std::cout eens handmatig te flushen? Misschien omdat er twee 'streams' op stdout zitten, dat ze niet automatisch beiden geflushed worden?

Dus:
C++:
1
cout << "testing" << flush;

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02-05 01:32
endl doet impliciet een flush, dus dat kan het niet zijn. Maar het is geen geheim dat het mixen van C en C++ I/O problemen oplevert, hoewel ik wel verwacht zou hebben dat dit zou werken. Werkt het wel als je alle C-style I/O eruit gooit?

[ Voor 62% gewijzigd door Soultaker op 07-04-2005 23:06 ]


  • yiko
  • Registratie: September 2003
  • Laatst online: 20-04-2025
Soultaker schreef op donderdag 07 april 2005 @ 23:06:
endl doet impliciet een flush, dus dat kan het niet zijn. Maar het is geen geheim dat het mixen van C en C++ I/O problemen oplevert, hoewel ik wel verwacht zou hebben dat dit zou werken. Werkt het wel als je alle C-style I/O eruit gooit?
Bedoel je dat mixen van C en C++ problemen geeft op vlak van I/O, of dat het mixen van C I/O en C++ I/O voor problemen zorgt ? (btw: libxml2 is C en mijn app is C++ )

Ik ben ondertussen al iets verder gekomen. Als ik node->content niet meer afbeeld, dan is alles pico bello in orde. Zelfs met mixen tussen printf en std::cout. Dus er lijkt mij iets niet pluis te zijn met node->content, precies alsof er een aantal backspace characters of iets dergelijks in zitten.

* yiko prutst even verder

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
void XmlDumper::DumpNode( xmlDocPtr doc , xmlNodePtr node )
{
        while( node != NULL ) {
                if ( node->type == XML_ELEMENT_NODE ) {         
                        std::cout << "<" << node->name << ">";
                        XmlDumper::DumpNode( doc , node->xmlChildrenNode );
                        std::cout << "</" << node->name << ">" << std::endl;
                } else if( node->type == XML_TEXT_NODE ){
                        std::cout << "\"" << node->content << "\"" << std::endl;
                }
                node = node->next;
        }
}

Ondertussen ook bijgeleerd dat een node van het type XML_ELEMENT_NODE geen content heeft. Deze is dan gewoon 0x0 , maar vind het maar eigenaardig dat std::cout daar over valt. Printf gaat in de plaats "(null)" afbeelden.
Enfin, dit loopt nu toch al beter. Ik krijg alle elementnodes te zien, en de inhoud ervan.
Het lijkt erop dat ik nu verder kan. Alvast bedankt voor de hulp.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02-05 01:32
yiko schreef op donderdag 07 april 2005 @ 23:54:
Bedoel je dat mixen van C en C++ problemen geeft op vlak van I/O, of dat het mixen van C I/O en C++ I/O voor problemen zorgt ? (btw: libxml2 is C en mijn app is C++ )
Het mixen van I/O zorgt voor I/O problemen, omdat beide libraries hun eigen buffering enzo doen. Welk raar gedrag je krijgt is nogal platformafhnkelijk (in principe is het gedrag van die libraries alleen afzonderlijk van elkaar gespecificeerd, afaik). Verder gaat C en C++ gewoon goed samen natuurlijk.
[..]
Ondertussen ook bijgeleerd dat een node van het type XML_ELEMENT_NODE geen content heeft. Deze is dan gewoon 0x0 , maar vind het maar eigenaardig dat std::cout daar over valt. Printf gaat in de plaats "(null)" afbeelden.
Ah, volgens de standaard mag je geen null-pointers geven. (Of het gedrag als je dat wel doet gestandaardiseerd is weet ik niet, blijkbaar gaat je stream stuk en print 'ie vervolgens niets meer.) Als je iets alternatiefs wil printen moet je dat dus zelf doen. (std::cout << (str ? str : "(null)") << std::endl; of zoiets.)

[ Voor 6% gewijzigd door Soultaker op 08-04-2005 00:10 ]


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Je kan een #define oid zetten, zodat je C en C++ io door elkaar kunt gebruiken. Ik weet even niet uit mn hoofd wat dat was. Of een compile flag oid.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
C en C++ werken gewoon samen. Def fout is waarschijnlijk (zoals Soultaker zegt) dat je een 0-pointer probeert te printen. Dat is Undefined Behavior, in zowel C als C++. Dat printf dan "(null)" laat zien is een valide implementatie van UB, niets laten zien ook, en een BSOD zou dat ook zijn.

Standaard kun je IOstreams en C stdio door elkaar gebruiken zonder problemen, die zijn gesynchorniseerd. Met de method sync_with_stdio(false) kun je dat uitzetten.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

MSalters schreef op vrijdag 08 april 2005 @ 09:45:
Standaard kun je IOstreams en C stdio door elkaar gebruiken zonder problemen, die zijn gesynchorniseerd. Met de method sync_with_stdio(false) kun je dat uitzetten.
Die bedoelde ik idd :) Had er ooit iets over gelezen, maar wist niet meer waar. "Standard C++ I/O Streams and Locales" was het.

Verwijderd

MSalters schreef op vrijdag 08 april 2005 @ 09:45:
C en C++ werken gewoon samen. Def fout is waarschijnlijk (zoals Soultaker zegt) dat je een 0-pointer probeert te printen. Dat is Undefined Behavior, in zowel C als C++. Dat printf dan "(null)" laat zien is een valide implementatie van UB, niets laten zien ook, en een BSOD zou dat ook zijn.

Standaard kun je IOstreams en C stdio door elkaar gebruiken zonder problemen, die zijn gesynchorniseerd. Met de method sync_with_stdio(false) kun je dat uitzetten.
In oudere compilers was het trouwens precies andersom. Dan moest je het expliciet aanzetten. Deed je dat niet dan kreeg je de output in willekeurige volgorde op je scherm.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02-05 01:32
Inderdaad, ik herinner me ook er problemen mee te hebben gehad (vooral met invoer, dacht ik). Maar het kan zijn dat ik nog andere dingen fout deed.
Pagina: 1