Waarom heeft deze code met printf en cout de verwachte output?

Ik heb de volgende code:

int main ()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);    

    for (int i = 0; i < 3; i++) {
        cout << i << " ";
        printf("%d ", i);
    }

    cout << endl;
    return 0;
}

De verwachte output van deze code is:

0 0 1 1 2 2

maar in plaats daarvan drukt het:

0 1 2
0 1 2

Dit probleem treedt op in de GNU G ++ 4.9.2-compiler

12
U hebt zelf de synchronisatie uitgeschakeld en gevraagd waarom ze niet gesynchroniseerd zijn%)
toegevoegd de auteur RiaD, de bron
U hebt zelf de synchronisatie uitgeschakeld en gevraagd waarom ze niet gesynchroniseerd zijn%)
toegevoegd de auteur RiaD, de bron
U hebt zelf de synchronisatie uitgeschakeld en gevraagd waarom ze niet gesynchroniseerd zijn%)
toegevoegd de auteur RiaD, de bron
Afzonderlijke buffers?
toegevoegd de auteur Kerrek SB, de bron
Afzonderlijke buffers?
toegevoegd de auteur Kerrek SB, de bron
@KerrekSB dat is het precies en ik wil het antwoord niet van u stelen. printf en cout gebruiken afzonderlijke buffers die op verschillende tijdstippen worden leeggemaakt. In het geval van de bovenstaande code was cout waarschijnlijk in de rij gespoeld en werd printf aan het einde van het gesprek leeggemaakt. Vervang de spatie in de printf door iets anders (_) en je zult het zien.
toegevoegd de auteur IdeaHat, de bron
@KerrekSB dat is het precies en ik wil het antwoord niet van u stelen. printf en cout gebruiken afzonderlijke buffers die op verschillende tijdstippen worden leeggemaakt. In het geval van de bovenstaande code was cout waarschijnlijk in de rij gespoeld en werd printf aan het einde van het gesprek leeggemaakt. Vervang de spatie in de printf door iets anders (_) en je zult het zien.
toegevoegd de auteur IdeaHat, de bron
@KerrekSB dat is het precies en ik wil het antwoord niet van u stelen. printf en cout gebruiken afzonderlijke buffers die op verschillende tijdstippen worden leeggemaakt. In het geval van de bovenstaande code was cout waarschijnlijk in de rij gespoeld en werd printf aan het einde van het gesprek leeggemaakt. Vervang de spatie in de printf door iets anders (_) en je zult het zien.
toegevoegd de auteur IdeaHat, de bron
Voeg fflush (stdout) toe?
toegevoegd de auteur Columbo, de bron
Voeg fflush (stdout) toe?
toegevoegd de auteur Columbo, de bron
Voeg fflush (stdout) toe?
toegevoegd de auteur Columbo, de bron
Deze vraag is niet logisch; door standaard streams expliciet te de-synchroniseren met stdio, vraag je waarom ze zich gedragen alsof ze gedesynchroniseerd zijn?
toegevoegd de auteur T.C., de bron
Deze vraag is niet logisch; door standaard streams expliciet te de-synchroniseren met stdio, vraag je waarom ze zich gedragen alsof ze gedesynchroniseerd zijn?
toegevoegd de auteur T.C., de bron
Deze vraag is niet logisch; door standaard streams expliciet te de-synchroniseren met stdio, vraag je waarom ze zich gedragen alsof ze gedesynchroniseerd zijn?
toegevoegd de auteur T.C., de bron
@ T.C. De vraag heeft niet veel zin als je precies weet wat er gebeurt, ik bedoel, wat de aanroep van ios_base :: sync_with_stdio (false) eigenlijk doet. Misschien is deze regel hier alleen voor het verbeteren van de prestaties van I/O-bewerkingen met cin/cout
toegevoegd de auteur Reynaldo Aguilar, de bron
@ T.C. De vraag heeft niet veel zin als je precies weet wat er gebeurt, ik bedoel, wat de aanroep van ios_base :: sync_with_stdio (false) eigenlijk doet. Misschien is deze regel hier alleen voor het verbeteren van de prestaties van I/O-bewerkingen met cin/cout
toegevoegd de auteur Reynaldo Aguilar, de bron
@ T.C. De vraag heeft niet veel zin als je precies weet wat er gebeurt, ik bedoel, wat de aanroep van ios_base :: sync_with_stdio (false) eigenlijk doet. Misschien is deze regel hier alleen voor het verbeteren van de prestaties van I/O-bewerkingen met cin/cout
toegevoegd de auteur Reynaldo Aguilar, de bron

15 antwoord

Een mogelijke verklaring hiervoor is dat cout en printf afzonderlijke buffers gebruiken. cout voert op het terminalscherm uit als het wordt leeggemaakt met de opdracht endl of als de buffer vol is (doorgaans 512 bytes).

Ik ben niet zeker van printf (dus voel je vrij om me te corrigeren als ik het mis heb), maar het volgt ook een vergelijkbaar gedrag. Dus wat er gebeurt, is dat aan het einde van het programma beide buffers worden doorgespoeld, en dus wordt de uitvoer die u ziet, bereikt.

Ik heb de code op mijn computer (GCC 4.8.1) en de onderstaande wijziging uitgevoerd

cout << i << " . ";
printf("%d ", i);

De uitvoer die ik waarnam, was 0 1 2 0. 1. 2. wat erop lijkt te wijzen dat printf als eerste in mijn geval spoelt. Ik heb geen idee of het ontwerp is (ergens in de standaard genoemd), of dat het van de context afhangt.

10
toegevoegd
Vrij zeker dat cout ook flushes voor nieuwe regels is, hoewel de meeste herspins dat niet doen.
toegevoegd de auteur Mooing Duck, de bron
@MooingDuck: van wat ik heb gelezen, spoelt cout door voor nieuwe regels bij uitvoer naar een interactief apparaat, zoals de terminal, maar spoelt niet weg bij het schrijven naar een bestand.
toegevoegd de auteur therainmaker, de bron

Een mogelijke verklaring hiervoor is dat cout en printf afzonderlijke buffers gebruiken. cout voert op het terminalscherm uit als het wordt leeggemaakt met de opdracht endl of als de buffer vol is (doorgaans 512 bytes).

Ik ben niet zeker van printf (dus voel je vrij om me te corrigeren als ik het mis heb), maar het volgt ook een vergelijkbaar gedrag. Dus wat er gebeurt, is dat aan het einde van het programma beide buffers worden doorgespoeld, en dus wordt de uitvoer die u ziet, bereikt.

Ik heb de code op mijn computer (GCC 4.8.1) en de onderstaande wijziging uitgevoerd

cout << i << " . ";
printf("%d ", i);

De uitvoer die ik waarnam, was 0 1 2 0. 1. 2. wat erop lijkt te wijzen dat printf als eerste in mijn geval spoelt. Ik heb geen idee of het ontwerp is (ergens in de standaard genoemd), of dat het van de context afhangt.

10
toegevoegd
Vrij zeker dat cout ook flushes voor nieuwe regels is, hoewel de meeste herspins dat niet doen.
toegevoegd de auteur Mooing Duck, de bron
@MooingDuck: van wat ik heb gelezen, spoelt cout door voor nieuwe regels bij uitvoer naar een interactief apparaat, zoals de terminal, maar spoelt niet weg bij het schrijven naar een bestand.
toegevoegd de auteur therainmaker, de bron

Een mogelijke verklaring hiervoor is dat cout en printf afzonderlijke buffers gebruiken. cout voert op het terminalscherm uit als het wordt leeggemaakt met de opdracht endl of als de buffer vol is (doorgaans 512 bytes).

Ik ben niet zeker van printf (dus voel je vrij om me te corrigeren als ik het mis heb), maar het volgt ook een vergelijkbaar gedrag. Dus wat er gebeurt, is dat aan het einde van het programma beide buffers worden doorgespoeld, en dus wordt de uitvoer die u ziet, bereikt.

Ik heb de code op mijn computer (GCC 4.8.1) en de onderstaande wijziging uitgevoerd

cout << i << " . ";
printf("%d ", i);

De uitvoer die ik waarnam, was 0 1 2 0. 1. 2. wat erop lijkt te wijzen dat printf als eerste in mijn geval spoelt. Ik heb geen idee of het ontwerp is (ergens in de standaard genoemd), of dat het van de context afhangt.

10
toegevoegd
Vrij zeker dat cout ook flushes voor nieuwe regels is, hoewel de meeste herspins dat niet doen.
toegevoegd de auteur Mooing Duck, de bron
@MooingDuck: van wat ik heb gelezen, spoelt cout door voor nieuwe regels bij uitvoer naar een interactief apparaat, zoals de terminal, maar spoelt niet weg bij het schrijven naar een bestand.
toegevoegd de auteur therainmaker, de bron

Standaard werkt de C stdio printf, enz. En de C ++ io-streams worden gesynchroniseerd, wat betekent dat ze onderling uitwisselbaar zijn. Aan het begin van uw code hebt u de synchronisatie met ios_base :: sync_with_stdio (false) verwijderd, maar weet u niet zeker of uw huidige intentie was om deze ios_base :: sync_with_stdio (true) te schrijven die de twee io-bibliotheken synchroniseert.

8
toegevoegd

Standaard werkt de C stdio printf, enz. En de C ++ io-streams worden gesynchroniseerd, wat betekent dat ze onderling uitwisselbaar zijn. Aan het begin van uw code hebt u de synchronisatie met ios_base :: sync_with_stdio (false) verwijderd, maar weet u niet zeker of uw huidige intentie was om deze ios_base :: sync_with_stdio (true) te schrijven die de twee io-bibliotheken synchroniseert.

8
toegevoegd

Standaard werkt de C stdio printf, enz. En de C ++ io-streams worden gesynchroniseerd, wat betekent dat ze onderling uitwisselbaar zijn. Aan het begin van uw code hebt u de synchronisatie met ios_base :: sync_with_stdio (false) verwijderd, maar weet u niet zeker of uw huidige intentie was om deze ios_base :: sync_with_stdio (true) te schrijven die de twee io-bibliotheken synchroniseert.

8
toegevoegd

Probeer dit

    cout << i << " " <
5
toegevoegd

Probeer dit

    cout << i << " " <
5
toegevoegd

Probeer dit

    cout << i << " " <
5
toegevoegd

Als u wilt dat de uitvoer std :: cout en printf worden gesynchroniseerd, moet u het volgende gebruiken:

std::ios_base::sync_with_stdio(true);

niet

std::ios_base::sync_with_stdio(false);

Zie het werken op http://ideone.com/7sgH2I .

3
toegevoegd

Als u wilt dat de uitvoer std :: cout en printf worden gesynchroniseerd, moet u het volgende gebruiken:

std::ios_base::sync_with_stdio(true);

niet

std::ios_base::sync_with_stdio(false);

Zie het werken op http://ideone.com/7sgH2I .

3
toegevoegd

Als u wilt dat de uitvoer std :: cout en printf worden gesynchroniseerd, moet u het volgende gebruiken:

std::ios_base::sync_with_stdio(true);

niet

std::ios_base::sync_with_stdio(false);

Zie het werken op http://ideone.com/7sgH2I .

3
toegevoegd

U mist waarschijnlijk flush() std :: cout . printf() heeft hier een ander gedrag tegenover. Ook moeten de IO-buffers worden gesynchroniseerd. Als u uw code wijzigt in

int main() {
    ios_base::sync_with_stdio(true);//Synchronizing the IO buffers
                                    //must be enabled
    cin.tie(NULL);    

    for (int i = 0; i < 3; i++) {
        cout << i << " ";
        cout.flush();//<<<<<<<<<<
        printf("%d ", i);
    }

    cout << endl;
    return 0;
}

het zou zich moeten gedragen zoals je verwachtte. Bekijk de werkende demo hier alstublieft.

1
toegevoegd
@ReynaldoAguilar Ik heb het gerepareerd.
toegevoegd de auteur πάντα ῥεῖ, de bron
Het produceert dezelfde output
toegevoegd de auteur Reynaldo Aguilar, de bron

U mist waarschijnlijk flush() std :: cout . printf() heeft hier een ander gedrag tegenover. Ook moeten de IO-buffers worden gesynchroniseerd. Als u uw code wijzigt in

int main() {
    ios_base::sync_with_stdio(true);//Synchronizing the IO buffers
                                    //must be enabled
    cin.tie(NULL);    

    for (int i = 0; i < 3; i++) {
        cout << i << " ";
        cout.flush();//<<<<<<<<<<
        printf("%d ", i);
    }

    cout << endl;
    return 0;
}

het zou zich moeten gedragen zoals je verwachtte. Bekijk de werkende demo hier alstublieft.

1
toegevoegd
@ReynaldoAguilar Ik heb het gerepareerd.
toegevoegd de auteur πάντα ῥεῖ, de bron
Het produceert dezelfde output
toegevoegd de auteur Reynaldo Aguilar, de bron

U mist waarschijnlijk flush() std :: cout . printf() heeft hier een ander gedrag tegenover. Ook moeten de IO-buffers worden gesynchroniseerd. Als u uw code wijzigt in

int main() {
    ios_base::sync_with_stdio(true);//Synchronizing the IO buffers
                                    //must be enabled
    cin.tie(NULL);    

    for (int i = 0; i < 3; i++) {
        cout << i << " ";
        cout.flush();//<<<<<<<<<<
        printf("%d ", i);
    }

    cout << endl;
    return 0;
}

het zou zich moeten gedragen zoals je verwachtte. Bekijk de werkende demo hier alstublieft.

1
toegevoegd
@ReynaldoAguilar Ik heb het gerepareerd.
toegevoegd de auteur πάντα ῥεῖ, de bron
Het produceert dezelfde output
toegevoegd de auteur Reynaldo Aguilar, de bron