How can you concisely combine a container of std::string_views?
For instance, boost::algorithm::join is great, but it only works for std::string.
An ideal implementation would be
static std::string_view unwords(const std::vector<std::string_view>& svVec) {
std::string_view joined;
boost::algorithm::join(svVec," ");
return joined;
}
ITNOA
short C++20 answer version:
using namespace std::literals;
const auto bits = { "https:"sv, "//"sv, "cppreference"sv, "."sv, "com"sv };
for (char const c : bits | std::views::join) std::cout << c;
std::cout << '\n';
since C++23 if you want to add special string or character between parts you can just use simple join_with and your code is just below (from official cppreference example)
#include <iostream>
#include <ranges>
#include <vector>
#include <string_view>
int main() {
using namespace std::literals;
std::vector v{"This"sv, "is"sv, "a"sv, "test."sv};
auto joined = v | std::views::join_with(' ');
for (auto c : joined) std::cout << c;
std::cout << '\n';
}
Note1: if you do not like use not stable release of language, you can simple use range-v3 library for join_with views
Note2: As Nicol Bolas you cannot join literally to exact one string_view without any copy (you can copy to string and ... :D), if you want to know more detailed about that you can see Why can't I construct a string_view from range iterators? SO question and answer.
Related
Browsing twitter I found this example of C++23 code.
This is my adaptation of it, to make more obvious what I am interested about(I do not care about dangling problems mentioned in replies).
#include <vector>
#include <string_view>
#include <iostream>
#include <type_traits>
int main() {
std::vector v{84.72};
std::basic_string_view sv = v;
static_assert(std::is_same_v<decltype(sv), std::basic_string_view<double>>);
const auto val = *std::begin(sv);
std::cout << val;
}
My question is why isn't there some requires/concept constraint on the basic_string_view to make it work only with charish types, so basic_string_view<double> in this example would not compile?
I suspect that this is a char-like type:
struct Char {
char c;
Char() : c{} {}
Char(char c) : c{c} {}
};
Why shouldn't it work? Indeed it does
std::basic_string<Char> str{'a', 'b'}; // OK
std::cout << str[0].c << std::endl; // prints a
std::cout << str.length() << std::endl; // prints 2
And what makes that class special with respect to, say, this?
struct Char {
int c;
Char() : c{} {}
Char(int c) : c{c} {}
};
Nothing, except our decision that char is a character and int is not. (And that's exactly the reason why I had to write std::cout << str[0].c and couldn't write std::cout << str or std::cout << str[0], because << is overloaded for chars and maybe something else, but certainly not for my own types.)
So the bottom line, as implied by some comments, is a counter-question:
How would you define a "charish" type?
which I would rephrase as
Can we encode the definiton of "sequence of char-like objects" in a concept?
which leads in turn to another question:
What operations can you do only on a "sequence of char-like objects" that you can't do on all "sequences of non-char-like objects"?
I can't think of one.
So if you wanted to enforce the constraint you mention, you would end up explicitly listing char, wchar, and all the others in some SFINAE thing.
And then you couldn't use it with any other type.
There are the atox, strtox and stox families that I know of, but I can't seem to find any iterator based string to int conversions in the Standard Library or Boost.
The reason I need them is because I am having a parser whose match result is a range referencing the input string. I might very well have an input string like
...8973893488349798923475...
^begin ^end
so I need 738934883 as an integer.
Of couse, I could first take begin and end to construct an std::string to use with any of above families, but I would very much like to avoid that overhead.
So my question: Is there anything in the Standard Library or Boost accepting iterators as input, or do I have to write my own.
Boost does actually support this, using the Lexical Cast library. The following code uses a substring range to parse the number without performing any dynamic allocation:
#include <boost/lexical_cast.hpp>
#include <string>
#include <iostream>
int convert_strings_part(const std::string& s, std::size_t pos, std::size_t n)
{
return boost::lexical_cast<int>(s.data() + pos, n);
}
int main(int argc, char* argv[])
{
std::string s = "8973893488349798923475";
// Expect: 738934883
std::cout << convert_strings_part(s, 2, 9) << std::endl;
return 0;
}
The output (tested on OS X with Boost 1.60):
738934883
The lexical cast library has some great features for conversion to and from strings, though it isn't as well known as some of the others for some reason.
Until gavinb's answer, I was not aware of any such library function. My try would have been this, using any of atox and strtox as follows (you could avoid a dependency on boost library then, if wanted):
::std::string::iterator b; // begin of section
::std::string::iterator e; // end of section, pointing at first char NOT to be evaluated
char tmp = *e;
*e = 0;
int n = atoi(&*b);
*e = tmp;
If you only had const_iterators available, you would have to apply a const_cast to *e before modifying.
Be aware that this solution is not thread safe, though.
You could do it with strstream but it was depracated. Below two examples, with strstream and boost arrays:
http://coliru.stacked-crooked.com/a/04d4bde6973a1972
#include <iostream>
#include <strstream>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/copy.hpp>
int main()
{
std::string in = "8973893488349798923475";
// ^^^^^
auto beg = in.begin()+2;
auto end = in.begin()+6;
// strstream example - DEPRECATED
std::istrstream os(&*beg, end-beg);
int n;
std::string ss;
os >> n;
std::cout << n << "\n";
// Boost example
namespace io = boost::iostreams;
int n2;
io::array_source src(&*beg, end-beg);
io::stream<io::array_source> os2(src);
os2 >> n2;
std::cout << n2 << "\n";
return 0;
}
With modern STL implementations std::string(begin,end) is not that bad - SSO eliminates any allocations for strings, smaller than ~15 chars (22 for 64bit).
Getting input from another source; which populates a string of up to 2048 characters.
What is the most efficient way of populating and comparing this string? - I want to be able to easily append to the string also.
Here are three attempts of mine:
C-style version
#include <cstdio>
#include <cstring>
int main(void) {
char foo[2048];
foo[0]='a', foo[1]='b', foo[2]='c', foo[3]='\0'; // E.g.: taken from u-input
puts(strcmp(foo, "bar")? "false": "true");
}
C++-style version 0
#include <iostream>
int main() {
std::string foo;
foo.reserve(2048);
foo += "abc"; // E.g.: taken from user-input
std::cout << std::boolalpha << (foo=="bar");
}
C++-style version 1
#include <iostream>
int main() {
std::string foo;
foo += "abc"; // E.g.: taken from user-input
std::cout << std::boolalpha << (foo=="bar");
}
What is most efficient depends on what you optimize for.
Some common criteria:
Program Speed
Program Size
Working Set Size
Code Size
Programmer Time
Safety
Undoubted King for 1 and 2, in your example probably also 3, is C style.
For 4 and 5, C++ style 1.
Point 6 is probably with C++-style.
Still, the proper mix of emphasizing these goal is called for, which imho favors C++ option 0.
#include<iostream>
#include<string>
#include<iterator>
using namespace std;
int main()
{
string a("hello world");
for(auto it = a.begin(); it != a.end() && !isspace(*it); it++ )
{
*it = toupper(*it);
}
cout<<a;
}
There are two errors I get. One is as mentioned, "auto changes meaning in c++11" and the other is "!= operator not defined." Never had this problem before.
I only used the auto operator because the book suggested.
I'm a beginner, and getting back to learning after about 2 months.
Having trouble catching up.
Your code runs ok when compiled with -std=c++11, You may check it here.
You can add the option in Setting->Compiler->Have g++ follow the C++11 ISO C++ language standard [-std=C++11] in CodeBlocks.
As chris mentioned, using Range-based for loop is much better. It's closer to spirit of C++11
and it's easier to learn for beginners. Consider:
#include <string>
#include <iostream>
int main()
{
std::string s{"hello, world"}; // uniform initialization syntax is better
for (auto& c : s) // remember to use auto&
if (!isspace(c)) c = toupper(c);
cout << s << '\n'; // remember the last newline character
return 0;
}
-- Saeed Amrollahi Boyouki
What is the Difference between using BOOST's ForEach and my own custom #define macro to iterate through a container??
mine:
#define iterate(i,x) for(typeof(x.begin()) i=x.begin();i!=x.end();++i)
boost:
#include <string>
#include <iostream>
#include <boost/foreach.hpp>
int main()
{
std::string hello( "Hello, world!" );
BOOST_FOREACH( char ch, hello )
{
std::cout << ch;
}
return 0;
}
Please explain which method is better and why?
First big difference, is when you using rvalues, like this:
vector<int> foo();
// foo() is evaluated once
BOOST_FOREACH(int i, foo())
{
}
// this is evaluated twice(once for foo().begin() and another foo().end())
iterate(i, foo())
{
}
This is because BOOST_FOREACH detects if it is an rvalue and makes a copy(which can be elided by the compiler).
The second difference is BOOST_FOREACH uses Boost.Range to retrieve the iterators. This allows it to be extended easily. So it will work on arrays and std::pair.
The third difference, is your iterate macro automatically deduces the type of the range, which can be very convenient on older compilers that support typeof but not auto. However, BOOST_FOREACH will work on all C++03 compilers.