Wyświetlanie dwóch pasków w tym samym czasie

0

Witam.

Ostatnio mi przyszedł chęć napisania takie symulatora paska postępu w wersji konsolowej. Program piszę sobie z nudów i jako odskocznię od assemblera.
Wykorzystałem Wielowątkowść i pojawił się pewien problem który bardziej dotyczy według mnie strumienia wyjścia niż samych wątków.

Efekt jaki chcę uzyskać to taki:
#########

Obydwa elementy mają się wyświetlać w konsoli w tym samym czasie w takim właśnie układzie + taka w cudzysłowie animacja.

A oto kod który napisałem:

#include<iostream>
#include<thread>
using namespace std;
void Zwloka(int sekunda)
{
    static time_t czas=time(NULL)
    while(time(NULL)-czas<sekunda);
    czas=time(NULL);
}
void Petla()
{
    for(int i=0;i<10;i++)
    {
        cout<<"#"<<flush;
        Zwloka(1);
    }
}
int main()
{
    thread obj(Petla);
    thread obj1(Petla);
    
    obj.join();
    obj1.join();
}

Lecz wynikiem działania tego programu jest zła bo wyświetla obydwa elementy lecz w jednej lini. Według mnie problemem tu jest zródło wyjścia czyli cout bo oby dwa wątki robią się w tym samym czasie lecz może i też się mylę.

Bardzo proszę o pomoc i życzę miłego dnia.

6

Jeśli cię dobrze rozumiem co chcesz uzyskać, to mam dla ciebie wiadomość.
Wątki tu nic nie zmieniają. Tego nie da się zrobić za pomocą std::cout i czegokolwiek w standardzie C++/C.

Musisz skorzystać z jakiejś dodatkowej biblioteki np ncurses.

Niektóre terminale wspierają znaki specjalne (idź linię w górę, idź do początku linii) i w nich std::cout może dać jakaś namiastkę "progress bar", ale nie będzie to zbyt niezawodne.
Problemem nie jest std::cout ale sama natura standardowego wyjścia.

1

https://stackoverflow.com/questions/54250401/how-to-control-a-cursor-position-in-c-console-application

  1. jak wyżej zauważono i w podanym linku to zależy od os i libek
  2. https://en.cppreference.com/w/cpp/thread/sleep_for
  3. Kiepskie nazwy funkcji
  4. Jako ciekawostka zapoznaj się z std::chrono
2

j/w + dodatkowo: https://en.cppreference.com/w/cpp/thread/sleep_for zamiast busy-waitingu na syscallu. Select czy inny poll też powinny dać radę (to tak poza konkursem).

1
MarekR22 napisał(a):

Tego nie da się zrobić za pomocą std::cout i czegokolwiek w standardzie C++/C.

Doprawdy?

#include <iostream>
#include <sstream>
#include <iomanip>
#include <thread>
#include <vector>
using namespace std;

void Zwloka(int sekunda)
{
    static time_t czas=time(NULL);
    while(time(NULL)-czas<sekunda);
    czas+=sekunda;
}

void Petla(char ch)
{
    for(int i=0;i<10;++i)
    {
        cout<<ch<<flush;
        Zwloka(1);
    }
}

vector<int> vals(3);

void PetlaSep(int idx)
{
    for(int i=0;i<10;++i)
    {
    	++vals[idx];
    	stringstream sout;
    	sout<<'\r';
        for(int k=0;k<vals.size();++k) sout<<setw(10)<<string(vals[k],'A'+k)<<' ';
        cout<<sout.str()<<flush;
        Zwloka(1);
    }
}

int main()
{
 	{
		thread A([&](){ PetlaSep(0); }),B([&](){ PetlaSep(1); }),C([&](){ PetlaSep(2); });

	    A.join();
	    B.join();
	    C.join();
	}
 	cout<<endl<<endl;
	{
		thread A([](){ Petla('A'); }),B([](){ Petla('B'); }),C([](){ Petla('C'); });
	
	    A.join();
	    B.join();
	    C.join();
 	}
    return 0;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1