Как std::setw работает со строковым выводом?

Я пытаюсь использовать заданную ширину setw для вывода строки в выходной файл, однако я не могу заставить ее работать. У меня есть с собой следующий пример.

// setw example
#include <iostream>     
#include <iomanip>      
#include <fstream>

int main () {
    std::ofstream output_file;
    output_file.open("file.txt");
    output_file << "first" <<std::setw(5)<< "second"<< std::endl;
    output_file.close();
  return 0;
}

Редактировать: В приведенных выше строках я ожидал, что между first и second будет много пробелов, что-то вроде first second

Я почти не вижу пробелов, вывод выглядит как firstsecond Думаю, я пропустил работу setw()

Примечание. Для целых чисел это работает нормально:

output_file << 1 <<std::setw(5)<< 2 << std::endl;

Что я делаю не так??.


person AwaitedOne    schedule 15.02.2017    source источник
comment
Попробуйте использовать его для строки меньше, чем пять символов (длина "second" – шесть символов). Обратите внимание, что ...<< setw(5) << 123456 <<... тоже не работает.   -  person Some programmer dude    schedule 15.02.2017
comment
Я не могу заставить его работать. - Возможно, ваш вопрос имел бы больше смысла, если бы мы все знали (а) каково ваше определение работы, и (б) что происходит на самом деле и чем оно отличается от (а). Вы надеетесь на какое-то усечение в выводе? Если да, то в вашем вопросе должно быть указано это.   -  person WhozCraig    schedule 15.02.2017
comment
@Someprogrammerdude Спасибо!! Если мне нужен пробел между first и second, почему он должен быть six chars long , так что дело не в пространстве.   -  person AwaitedOne    schedule 15.02.2017
comment
@WhozCraig Спасибо, на самом деле у меня нет пробелов между first и second.   -  person AwaitedOne    schedule 15.02.2017
comment
Позвольте мне выразиться по-другому: поместите примеры того, что вы надеетесь получить и что вы фактически получаете, для вывода в вашем вопросе . Я подозреваю, что проблема в том, что вы просто не понимаете, как std::setw функции манипулятора.   -  person WhozCraig    schedule 15.02.2017
comment
@WhozCraig Пожалуйста, найдите правку выше.   -  person AwaitedOne    schedule 15.02.2017
comment
Редактирование показывает, что вам просто нужно больше места, почему бы не использовать \t или \t\t или \t\t\t.   -  person Agaz Wani    schedule 15.02.2017
comment
ширина 2 явно меньше 5, тогда как second не   -  person phuclv    schedule 15.02.2017


Ответы (1)


Я подозреваю, что ваше понимание std::setw просто неверно. Я думаю, вам нужно что-то большее, что-то вроде комбинации:

  • std::setw для настройки ширины поля
  • std::setfill для установки символа заполнения
  • std::left, std::right, std::internal для установки позиции записи в пределах указанная ширина поля.

Что происходит в вашем коде:

  • Использует std::setw(5) для установки ширины поля в пять символов.
  • Отправляет "first" в поток длиной пять символов, поэтому установленная ширина поля полностью используется. Никакого дополнительного заполнения не происходит.
  • Отправляет "second" в поток длиной шесть символов, так что опять же, вся ширина поля используется (и фактически нарушается). Опять же, заполнение не происходит

Если вы хотите иметь что-то вроде этого (с номерами столбцов выше, чтобы показать позиции):

 col: 0123456789012345678901234567890123456789
      first     second    third     fourth

Обратите внимание, что каждое слово начинается на границе, кратной 10. Один из способов сделать это — использовать:

  • Выходная позиция std::left (поэтому заливка, если таковая имеется, идет справа для достижения желаемой ширины). Это значение по умолчанию для строк, но никогда не помешает убедиться.
  • Заполняющий символ std::setfill(' '). Опять же по умолчанию.
  • Ширина поля std::setw(10) Почему такое большое число? Смотри ниже

Пример

#include <iostream>
#include <iomanip>

int main ()
{
    std::cout << std::left << std::setfill(' ')
              << std::setw(10) << "first"
              << std::setw(10) << "second"
              << std::setw(10) << "third"
              << std::setw(10) << "fourth" << '\n';
    return 0;
}

Вывод (добавлены номера столбцов)

0123456789012345678901234567890123456789
first     second    third     fourth

Итак, что произойдет, если мы изменим выходное местоположение на std::right? Ну, с той же программой, изменив только первую строку на:

std::cout << std::right << std::setfill(' ')

мы получили

0123456789012345678901234567890123456789
     first    second     third    fourth

Наконец, один конструктивный способ увидеть, где применяются символы-заполнители, — это просто изменить символ-заполнитель на что-то видимое (т. е. на что-то кроме пробела). В последних двух примерах вывод, изменение заполняющего символа на std::setfill('*') приводит к следующему выводу:

Первый

first*****second****third*****fourth****

Второй

*****first****second*****third****fourth    

Обратите внимание, что в обоих случаях, поскольку ни один из отдельных элементов вывода не нарушил значение std::setw, общий размер строки вывода для каждого из них одинаков. Все, что изменилось, это то, где были применены заливки и выровнены выходные данные в соответствии со спецификацией std::setw.

person WhozCraig    schedule 15.02.2017
comment
WhozCraig спасибо за ответ, но он не помогает мне понять некоторые из наиболее непоследовательных поведений C++ std::setw , о которых я спрашиваю здесь: stackoverflow.com/questions/49824962/ - person George 2.0 Hope; 13.04.2018