1

I've been trying to put every single element of a vector of integers into a string. I want to achieve this by type casting the integers into strings, after that I cocatenate those "small strings" into a single big string, which is going to represent all the elements of that specific vector.

This may look silly, but is really useful if you want to make a function that returns a vector like-a-thing, or etc.

The only problem is that I'm getting an error on line 13, which says :

error: no matching function for call to ‘std::__cxx11::basic_string<char>::basic_string(int&)’
   13 |     myString += (string) myVector[i];
      |                                    ^

and I don't have the slightest idea on why this is happening. My code follows below :

#include <iostream>
#include <vector>
using namespace std;

int main()
{
  int myVector[5] = {1,2,3,4,5};

  string myString = "";

  for (int i =0; i < 5; i++)
  {
    myString += (string) myVector[i];
    myString += "\n";
  }

  cout << myString << endl;

any help will be much appreciated.

rturrado
  • 7,699
  • 6
  • 42
  • 62
HaveMercy
  • 65
  • 4
  • [`std::ostringstream`](https://en.cppreference.com/w/cpp/io/basic_ostringstream), [`std::ostream_iterator`](https://en.cppreference.com/w/cpp/iterator/ostream_iterator), and [`std::copy`](https://en.cppreference.com/w/cpp/algorithm/copy). And if you just going to print the values, then skip the string stream and use `std::cout` directly. – Some programmer dude Jan 30 '23 at 14:00
  • And as a general hint: Whenever you feel the need to do a C-style cast (like you do in attempting to convert the integer to a string) you should see that as a sign that you're doing something wrong. – Some programmer dude Jan 30 '23 at 14:03
  • *and I don't have the slightest idea on why this is happening* -- Is it that you are used to other languages that do this type of conversion of integer to string, where all you need to do is have a `+`, and magically the integer will turn into a string? If so, you see that C++ doesn't work that way. – PaulMcKenzie Jan 30 '23 at 14:07
  • in general finding all possible conversions is not easy, finding that there is no conversion is even harder, but a good place to start is looking at constructors of `std::string` https://en.cppreference.com/w/cpp/string/basic_string/basic_string – 463035818_is_not_an_ai Jan 30 '23 at 14:10

6 Answers6

4

You can use std::to_string to convert an int to a std::string.

Change this line:

myString += (string) myVector[i];

To:

myString += std::to_string(myVector[i]);

Note: concatenating strings like that might not be so efficient due to temporary strings being created and destroyed (although it is likely that small strings optimization will kick in, so no additional heap allocations will take place).
As @Someprogrammerdude commented, you can consider to use std::ostringstream.

Side notes:

  1. You are missing #include <string>.
  2. Why is "using namespace std;" considered bad practice?.
wohlstad
  • 12,661
  • 10
  • 26
  • 39
  • *many temporary strings being created and destroyed* - Due to [SSO](https://stackoverflow.com/questions/10315041/meaning-of-acronym-sso-in-the-context-of-stdstring) no heap allocations are likely to occur. – Evg Jan 30 '23 at 14:28
  • 1
    @Evg clarified that point. – wohlstad Jan 30 '23 at 14:34
3

You can use std::stringstream

#include <iostream>
#include <string>
#include <sstream>
int main()
{
    int myVector[5] = {1,2,3,4,5};
    std::string myString;

    std::stringstream sstream;
    for (auto i : myVector)
        sstream << i;

    sstream >> myString;
    std::cout << myString;
}

Link.

2

You can use the fmt library:

  1. fmt::join will accept a range, in your case a vector of ints, and join its contents with a given separator (e.g. an empty string if you just want all of the elements together).
  2. fmt::format will create a string with a given format, in this case just the contents of the joined vector.

Demo

#include <fmt/ranges.h>

int main() {
  int myVector[5] = {1,2,3,4,5};
  auto myString = fmt::format("{}", fmt::join(myVector, ""));
  fmt::print("{}\n", myString);
}

// Outputs: 12345

Or, simpler, if you don't need the string:

int main() {
  int myVector[5] = {1,2,3,4,5};
  fmt::print("{}\n", fmt::join(myVector, ""));
}

The error you are getting is saying that the compiler cannot find a std::__cxx11::basic_string<char>::basic_string(int&) function, i.e., a std::string constructor accepting an int&.

rturrado
  • 7,699
  • 6
  • 42
  • 62
2

I'll add my own solution, as laid out in my comment:

#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>

int main()
{
    std::vector myvector = { 1, 2, 3, 4, 5 };

    std::copy(std::begin(myvector), std::end(myvector),
              std::ostream_iterator<int>(std::cout, "\n"));
}
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1

Overload the output stream operator, and then you have something reusable for a lot of scenarios.

Based on the feedback below overloading is not the best answer, another approach here : https://www.onlinegdb.com/zDUjVbSTp

#include <vector>
#include <iostream>
#include <string>
#include <sstream>

// Overloading operator<< will have many benefits.
// you can use it to output an array to std::cout directly
// or you can write it to a file or stringstream
std::ostream& operator<<(std::ostream& os, const std::vector<int>& values)
{
    os << "[";
    bool comma = false;
    for (const auto& value : values)
    {
        if (comma) os << ", ";
        os << value;
        comma = true;
    }
    os << "]";

    return os;
}

int main()
{
    std::vector<int> values{ 1,2,3,4,5 }; 

    // write directly to std::cout
    std::cout << "direct : " << values << "\n";

    // adding array to a string
    std::ostringstream os;
    std::string string{ "output = " };
    os << values;
    string += os.str();
    std::cout << string << "\n";
    

    return 0;
}
Pepijn Kramer
  • 9,356
  • 2
  • 8
  • 19
  • 2
    I would not overload operators for standard types. Suppose you use a library that also provides such overload, and another one that does the same... – 463035818_is_not_an_ai Jan 30 '23 at 14:12
  • That's a fair comment – Pepijn Kramer Jan 30 '23 at 14:16
  • Overloading `operator<<` makes sense for types for which you have more or less canonical output format, like integers or strings. For types like `std::vector` it's questionable because no canonical output exists - one might want to use spaces or commas as separators, to put or not to put the whole sequence into brackets, etc. – Evg Jan 30 '23 at 14:16
  • fwiw, a named function `void print(std::ostream& out,const std::vector&)` has the same advantages you list. – 463035818_is_not_an_ai Jan 30 '23 at 14:18
  • @463035818_is_not_a_number Yes I realize that now too :) https://onlinegdb.com/zDUjVbSTp – Pepijn Kramer Jan 30 '23 at 14:25
  • I will leave this answer as it is, since I think it contains good info for others as well :) – Pepijn Kramer Jan 30 '23 at 14:26
1

You can use for_each algorithm as well to do the concatenation.

#include <iostream>
#include <algorithm>

int main()
{
    std::vector<int> v{1, 2, 3, 4, 5, 6};  

    std::string all;
    std::for_each(v.begin(), v.end(), [&, del=""](const int &e) { 
        all += std::to_string(e) + (&e == &v.back() ? "" : del); 
    });
    std::cout << all << std::endl;
}

output:

123456

If you want to add a delimiter in between, just change the del value in lambda capture.

std::for_each(v.begin(), v.end(), [&, del="-"](const int &e) { 
        all += std::to_string(e) + (&e == &v.back() ? "" : del); 
    });

Output:

1-2-3-4-5-6
Aamir
  • 1,974
  • 1
  • 14
  • 18