2010-07-18 17 views
7

Görevlerin cout'u kullanarak ilerlemesini güncelleyen bir görev izleme kodluyorum. Satır başına bir görev ilerleme göstermek istiyorum, bu yüzden konsolun birkaç satırını geri almak zorundayım.Cout'tan satırlar nasıl geri alınır?

\b tek satırlık bir iş yaptığından, ancak satırlar arasında \n silemediği için "birkaç" üzerinde ısrar ediyorum.

std::cout.seekp(std::cout.tellp() - str.length()); denedim, ancak tellp() -1 (başarısızlık) değerini döndürür.

+2

Yapamazsınız. 'cout' konsolu temsil etmiyor. Bir çıktı akışını temsil eder. Bu, ona yazabileceğiniz anlamına gelir, ancak zaten yazılanlar hakkında hiçbir şey yapamazsınız. 'cout', çıktıyı platformun kullandığı çıktı aygıtına yazdırmak içindir (örneğin, mutlaka bir konsol penceresi). Özellikle konsolu kullanmanız gerekiyorsa, konsol penceresini bilen OS'ye özgü bir kütüphane kullanmanız gerekir. – jalf

+1

Niçin tamamlanmış görevlerin listesini silmek istiyorsun? Her satırda bir görev ilerleme öğesi yazdırmanız yeterlidir ve birisi programınızı çalıştırırsa ve stdout'u bir günlük dosyasına gönderirse daha iyi çalışır. – jamesdlin

+0

Biliyorum, ama çok fazla hat olacak, kullanıcıyı infos altında boğmak istemiyorum, sadece durumu ver ve kaçtığım her görevin ilerlemesi yüzdesini. –

cevap

16

Geçerli satırın başına atlamak için cout << '\r';'u yapabilirsiniz, ancak yukarı doğru hareket etmek sisteme özeldir. Unix için bkz. man termcap ve man terminfo (ve cursor_up için arama). ANSI uyumlu terminallerde (Unix'te mevcut en modern terminaller gibi), bu yukarı doğru hareket eder: cout << "\e[A";.

cout numaralı telefonu aramayı denemeyin, çoğu zaman görünmezdir (bir dosyaya yeniden yönlendirildiğinde hariç). ncurses kullanarak, diğer cevaplar belirtildiği gibi

(veya argo) kitaplığı Unix terminal I/O için iyi bir özet sağlar.

+0

Teşekkürler, birkaç satır izlemekten vazgeçtim ve yerine 79 boşluk doldurdum. –

8

Yapabilirseniz ncurses gibi bir çıktı biçimlendirme kitaplığı kullanın; Bu, terminal manipülasyonunu önemli ölçüde basitleştirir.

5

Ne C ne de C++ böyle bir şey tanımlar. Açık terminal manipülasyonuna ihtiyacınız var. Unix'te curses'u kullanabilirsiniz. Windows için ne olduğu hakkında hiçbir fikriniz yok.

1

Bunun eski bir yayın olduğunu biliyorum, ancak kabul edilenler, bir programa veya dosyaya cout'un eklendiği durumları kapsamıyor ve bu benim google aramalarımın en üstünde yer alıyor. Aşağıdakiler, hem piped hem de non-piped stdout'u biraz farklı davranışlarla ele alacaktır.

#include <iostream> 
#include <functional> 
#include <stdio.h> 

#ifdef _WIN32 
#include <io.h> 
#else 
#include <unistd.h> 
#define _isatty isatty 
#define _fileno fileno 
#endif 

const std::function<void(const size_t&)> progress_printer(_isatty(_fileno(stdout)) == 1 ? 
    [](const size_t& i) { 
     std::cout << "\rNumber " << i << std::flush; 
    } : 
    [](const size_t& i) { 
     static std::ios::off_type last(-1); 
     if(last != -1) 
      std::cout.seekp(last, std::ios::beg); 
     last = std::cout.tellp(); 
     std::cout << "Number " << i << std::endl; 
    } 
); 

Bu, Windows'ta denenmemiş, ancak çalışmalıdır. Dosya tanıtıcısı veya tty olup olmadığını algılar. Eğer öyleyse, pos, son kez yazdırıldığından ya da yeni satırdan beri değişmediyse sadece '\ r' yazıyor. Eğer yeni bir satır değilse, basıldıktan sonraki son yere doğru arar.

Dosyalarda tty'ye göre farklı davranır. Bir dosya için, baskılar arasındaki akışa bir şey çıktığında, yeni satırlardan sonra bile yazılanların bir kısmının veya tamamının üzerine yazılabilir. Ttys için sadece mevcut satırın başlangıcındaki karakterleri yazar.

+0

eski ama hala altın – LRP

İlgili konular