C++ ładniejsze utworzenie stringa

0

Dzień dobry
Chcę mieć stringa, do którego wstawiam 3 różny liczby (zmienne typu int - id użytkownika, liczbę złota do wymiany i liczbę srebra (też na wymianę).
Ten string jest potem używany do funkcji okienka
Na razie robię to tak:

std::string str = "Czy chcesz przyjac do grupy uzytkownika o id = ";
str += std::to_string(id);
str += " i wymieniac z nim ";
str += std::to_string(gold);
str += " zlota za ";
str += std::to_string(silver);
str += " srebra?";

Zastanawiam się, czy można to zrobić jakoś 'ładniej' tzn. aby nie było 6 linijek +=

3

C++ nie znam ale w innych językach nazywa się to interpolacja stringów. Dla C++ też cos jest

1

std::ostringstream albo funkcje typu sscanf/snscanf sprintf/snprintf (jest więcej wariantów)

1

Najprostszy jest chyba ostringstream.

#include <string>
#include <sstream>
std::ostringstream oss;
oss << "Czy chcesz przyjąć do grupy użytkownika o id = " << id << " i wymieniać z nim " << gold << " złota za " << silver << " srebra?";
std::string str = oss.str();

PS. używaj polskich liter - to nie lata 90-te. Wydaje się też że zamiast "wymieniać" powinno być "wymienić" (zależnie od kontekstu).

0

Dziękuję za odpowiedzi

2

A może fold expression?

template<typename... Ts>
string make_string(Ts&&... args)
{
  ostringstream oss;
  (oss << ... << args);
  return oss.str();
}
1

"fold expression" ciekawy cukier składniowy
moje oko nie dowierzało że to może działać , ale jednak działa ;)
https://godbolt.org/z/h3jcWh66b

#include <string>
#include <iostream>     // std::cout, std::ios
#include <sstream>      // std::ostringstream

template<typename... Ts>
std::string make_string(Ts&&... args)
{
  std::ostringstream oss;
  (oss << ... << args);
  return oss.str();
}

int main()
{
    int id{1};
    int gold{100};
    int silver{200};
   
    std::string s = make_string("Czy chcesz przyjąć do grupy użytkownika o id = ",id," i wymieniać z nim ", gold, " złota za ", silver, " srebra?");
    std::cout << s;
}
2
Adamek Adam napisał(a):

"fold expression" ciekawy cukier składniowy

Na marginesie -- właściwie to nie jest cukier składniowy, bo wg Wikipedii cukier składniowy to "dowolna cecha składni języka, którą można wyeliminować przez proste przekształcenia składniowe" -- a tego nie da się tak wyeliminowć po prostu. Fold expression dodaje pewną istotną nową jakość...

0

No to skoro schodzimy trochę do offtopu i akurat siedzę na nudnym, zdalnym spotkaniu...

@Adamek Adam:

przykłady mile widziane, wiedza mi wzrośnie

Moim ulubionym użyciem fold expression to przy tworzeniu prostych konceptów. Jak jeszcze dodam trochę cukru w postaci Abbreviated Function Templates and Constrained Auto to mój generyczny kod zaczyna nawet w miarę wyglądać.

template<typename T, typename ...Args>
concept OneOfTypes = (std::is_same_v<T, Args> || ...);

template<typename T>
concept StringOrVector = OneOfTypes<T, std::string, std::vector>;

//------------------------------

size_t size(const StringOrVector auto &val) { return val.size(); }

Oczywiście to tylko prezentacja, użycie powyższego szablonu size dokładnie w takiej postaci nie ma sensu, ale chyba widać sam zamysł.

Fold expression wraz z innymi ficzerami, jak generyczna lambda, może być również użyte do zbudowania alternatywnej pętli for w compile time:

[&]<std::size...p>(std::index_sequence<p...>)
{
  (do_something(p), ...);
}(std::make_index_sequence<SIZE>{});

co w efekcie zostanie rozwinięte do takiej postaci

do_something(p);
do_something(p + 1);
do_something(p + 2);
do_something(p + 3);
//...
do_something(p + SIZE - 1);

czyli de facto mamy odpowiednik

for(size_t p = 0; p < SIZE, ++p)
{
  do_something(p);
}

tylko w całości "rozwinięty" w trakcie kompilacji. Warunek taki, że SIZE musi być znane w trakcie kompilacji.

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