2016-01-12 3 views
0

Допустим, у меня есть string foo("lorem ipsum"). Теперь я хочу напечатать максимальное количество символов от foo, скажем, x, который гарантированно будет меньше foo.size().Прецизионный модификатор потока для струн

Это очень континент в printf:

printf("%.*s", x, foo.data()); 

Но единственный способ, которым я могу найти, чтобы сделать это в потоке, чтобы построить временный string:

cout << string(foo, x); 

Есть манипулятором, что позволит мне установить точность потоков, или создает временное string все, что доступно мне?

+1

Я не знаю «maniuplator way», чтобы сделать это, но ['string_view'] (http://en.cppreference.com/w/cpp/experimental/basic_string_view) - это путь сюда , Однако это еще не стандарт. – leemes

+0

@NathanOliver Что вы говорите, что это не работает с 'string'? http://ideone.com/quH7cl –

+0

@NathanOliver Ах да, 'setw' только для числовых значений. Даже если это не так, поле ширины указывает минимум в 'printf'. Это поле точности задает максимум. Поэтому 'setprecision' - это то, что мы бы искали, если бы оно действительно работало для' string' (это не так). –

ответ

2

Там нет "поток Манипулятор" отрезать строки после заданной ширины.

Что вы ищете, это в основном string_view(1), то есть какая-то легкая подстрочная обертка, способная работать.

Следующая строка напечатает первые x символы foo без копирования его на временную строку, пока гарантии вы упоминаете (x >= foo.size()) имеет место:

cout << string_view(foo.data(), x); 

В случае, если гарантия не выполняется больше, используйте setw, чтобы заполнить поле пробелами, когда строка короче, чтобы напечатать фиксированное поле длиной x символов. string_view конструктор необходим правильно гранично-ограниченную длину, так как он не знает размер «реальной» std::string объекта, таким образом, мы используем min ограничить x длине строки:

cout << setw(x) << string_view(foo.data(), min(x, foo.size())); 

Если вы не хотите или не можете использовать string_view, вы можете написать свою собственную легкую упаковку только для печати подстроки с помощью ostream.

class substr { 
    const std::string & s; 
    std::size_t len; 

    friend std::ostream& operator<<(std::ostream& os, const substr &ss) { 
     std::copy(ss.s.begin(), ss.s.begin() + std::min(ss.len, ss.s.size()), 
        std::ostream_iterator<char>(os)); 
     return os; 
    } 
public: 
    substr(const std::string & s, std::size_t len) : s(s), len(len) {} 
}; 

Использование затем:

cout << substr(foo, x); 

Live Example


(1) Этот класс является экспериментальной и еще не в стандарте. Насколько я знаю, он, вероятно, будет в C++ 17 и доступен как std::experimental::string_view в <experimental/string_view>, так как g ++ 4.9 при использовании -std=c++1y или 17.

2

Это не манипулятор потока, но вы можете использовать std::copy и скопировать количество символов в выходной поток. Это позволяет избежать создания временной строки.

int main() { 
    std::string s = "this is a test"; 
    std::copy(s.begin(), s.begin() + 7, std::ostream_iterator<char>(std::cout)); 
    return 0; 
} 

Выход:

this is 

Live Example

+0

Удручает думать, что это так хорошо, как мы можем делать с потоками. –