Russian Qt Forum
Ноябрь 24, 2024, 16:45 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Вывод в консоль  (Прочитано 20075 раз)
8Observer8
Гость
« : Июль 31, 2014, 20:02 »

Привет!

Столкнулся со странным поведением. В примере ниже вывожу в консоль имена файлов и папок текущего каталога:

Код
C++ (Qt)
#include <iostream>
#include <QDir>
#include <QStringList>
#include <QDebug>
 
int main()
{
   QDir dir( QString( "./" ) );
   QStringList list = dir.entryList();
   foreach (QString s, list) {
       qDebug() << s;
       std::cout << s.toStdString() << std::endl;
   }
}
 

Ожидаю увидеть:
Цитировать
"."
.
".."
..
"debug"
debug
"Makefile"
Makefile
"Makefile.Debug"
Makefile.Debug
"Makefile.Release"
Makefile.Release
"release"
release

Bижу:
Цитировать
"."
.
".."
"debug"
"Makefile"
"Makefile.Debug"
..
debug
Makefile
Makefile.Debug
Makefile.Release
release
"Makefile.Release"
"release"

Заранее спасибо за ответ!
« Последнее редактирование: Июль 31, 2014, 20:07 от 8Observer8 » Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #1 : Июль 31, 2014, 20:10 »

UPDATE.
Не в тему...
« Последнее редактирование: Июль 31, 2014, 21:28 от gil9red » Записан

8Observer8
Гость
« Ответ #2 : Июль 31, 2014, 20:24 »

Точки не интересуют Улыбающийся Почему не по парам?
Записан
8Observer8
Гость
« Ответ #3 : Июль 31, 2014, 20:32 »

Другой пример:

Код
C++ (Qt)
 
#include <iostream>
#include <QDir>
#include <QStringList>
#include <QDebug>
 
int main()
{
   QDir dir( QString( "./" ) );
   QStringList list = dir.entryList( QDir::NoDotAndDotDot | QDir::Dirs );
   foreach (QString s, list) {
       qDebug() << s;
       std::cout << s.toStdString() << std::endl;
   }
}
 

Output
Цитировать
"debug"
debug
release
"release"

А должно быть:
Цитировать
"debug"
debug
"release"
release
Записан
Serr500
Гость
« Ответ #4 : Июль 31, 2014, 20:37 »

А с чего Вы решили, что так должно быть? Почему Вы думаете, что qDebug совпадает с std::cout?
Записан
8Observer8
Гость
« Ответ #5 : Июль 31, 2014, 20:59 »

Инструкции должны выполняться поочереди: сначала qDebug, потом std::cout
Записан
Serr500
Гость
« Ответ #6 : Июль 31, 2014, 21:03 »

А они по очереди и выполняются.  Подмигивающий

Подсказки Вы не поняли. Попробую по другому.

1) Для чего нужен std::flush?
2) qDebug() << "..." в итоге обращается к qt_message_print, который выводит в stderr через printf.
Записан
Serr500
Гость
« Ответ #7 : Июль 31, 2014, 21:17 »

Ладно уж, я сегодня добрый.

Операторы вывода в консоль выполняют вывод не сразу. Они сохраняют выводимые строки в свой внутренний буфер, который потом сбрасывают (flush), после чего вывод появляется в консоли. Сброс происходит не сразу. Если выводить в разные потоки, то сброс может выполняться в обратном порядке, поэтому строки также могут поменять порядок. Как я уже сказал, qDebug выводит в stderr, который отличается от std::cout.

В качестве примера попробуйте выполнить следующий код:
Код:
    std::cout << "String 1";
    fprintf(stderr, "String 2");

    fflush(stderr);
    std::cout << std::flush;

Несмотря на то, что вывод "String 1" выполняется раньше вывода "String 2", в консоли мы увидим строки в обратном порядке.
« Последнее редактирование: Июль 31, 2014, 21:26 от Serr500 » Записан
Hrundel
Гость
« Ответ #8 : Июль 31, 2014, 23:45 »

[off-top]

Вот и пообщались "хакер" и "хакер" Веселый
Записан
8Observer8
Гость
« Ответ #9 : Август 01, 2014, 13:17 »

Спасибо! Всё равно, как это неправильно... Я как пользователь фреймворка, если написал qDebug() первым, он должен так и сработать. Почему же интересно разработчики не учли и flush() не вызывается.

Если вызвать "fflush(stderr);" и "std::cout.flush();" то всё равно выводит непарно:

Код
C++ (Qt)
 
#include <iostream>
#include <QDir>
#include <QStringList>
#include <QDebug>
 
int main()
{
   QDir dir( QString( "./" ) );
   QStringList list = dir.entryList( ); // QDir::NoDotAndDotDot | QDir::Dirs
   foreach (QString s, list) {
       qDebug() << s;
       fflush(stderr);
       std::cout << s.toStdString() << std::endl;
       std::cout.flush();
   }
}
 
Записан
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #10 : Август 01, 2014, 19:13 »

Предполагаю, что, так как твоё приложение и терминал это разные процессы, которые работают асинхронно, считывание двух потоков std::out и std::err терминалом происходит не синхронно, вот ты и видишь разницу.

Возможно это поведение зависит от используемого эмулятора терминала и операционки.

Вариант решения - перехватить вывод qDebug с помощью qInstallMsgHandler() и направить его в std::out.
Записан

Гугль в помощь
8Observer8
Гость
« Ответ #11 : Август 01, 2014, 19:18 »

Спасибо! Стало понятней. Так-то это не особо важно. Просто интересно было узнать, что примерно происходит Улыбающийся
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.185 секунд. Запросов: 23.