Correct way to printf() a std::string_view? - c++

I am new to C++17 and to std::string_view.
I learned that they are not null terminated and must be handled with care.
Is this the right way to printf() one?
#include<string_view>
#include<cstdio>
int main()
{
std::string_view sv{"Hallo!"};
printf("=%*s=\n", static_cast<int>(sv.length()), sv.data());
return 0;
}
(or use it with any other printf-style function?)

This is strange requirement, but it is possible:
std::string_view s{"Hallo this is longer then needed!"};
auto sub = s.substr(0, 5);
printf("=%.*s=\n", static_cast<int>(sub.length()), sub.data());
https://godbolt.org/z/nbeMWo1G1
As you can see you were close to solution.

You can use:
assert(sv.length() <= INT_MAX);
std::printf(
"%.*s",
static_cast<int>(sv.length()),
sv.data());

The thing to remember about string_view is that it will never modify the underlying character array. So, if you pass a C-string to the string_view constructor, the sv.data() method will always return the same C-string.
So, this specific case will always work:
#include <string_view>
#include <cstdio>
int main() {
std::string_view sv {"Hallo!"};
printf("%s\n", sv.data());
}

Related

Using C++'s reverse(string.begin(), string.end()) Why won't it let me hold it in a new variable?

Hello I am very new to programming and C++. I'm trying to make a program that checks if a string is a palindrome (a word that is the same backwards as it is forwards).
In order to do that I searched online about how to reverse a string and came across the reverse(string.begin(), string.end()) function from <bits/stdc++.h>.
I've made a function that can reverse the string written in the parameters and it works fine:
#include <iostream>
#include <vector>
#include <string>
#include <bits/stdc++.h>
std::string reverseStr(std::string str) {
reverse(str.begin(), str.end());
return str;
}
int main() {
std::cout << reverseStr("word");
}
But when I want to assign the reversed string into a new variable "reversedStr":
#include <iostream>
#include <vector>
#include <string>
#include <bits/stdc++.h>
std::string reverseStr(std::string str) {
std::string reversedStr;
reversedStr = reverse(str.begin(), str.end());
return reversedStr;
}
int main() {
std::cout << reverseStr("word");
}
Then when I try and compile it, it gives me this error.
C:/Program Files/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/basic_string.h:776:7: note: no known conversion for argument 1 from 'void' to 'std::initializer_list<char>'
The terminal process "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command g++ -g main.cpp" terminated with exit code: 1.
If you wouldn't mind explaining what is happening that would be great! Thank you!
reverse reverses a collection in place and doesn't return it. If you want to do it to a new variable, then first copy the string to the variable then reverse that:
// pass the str argument by reference to avoid unnecessary copies
std::string reverseStr(const std::string& str) {
std::string reversedStr = str;
std::reverse(reversedStr.begin(), reversedStr.end());
return reversedStr;
}
As stated in documentation std::reverse() does not return anything so you cannot assign it's return value to a variable. Simplest solution would be:
std::string reverseStr(const std::string &str)
{
return std::string( str.rbegin(), str.rend() );
}
using reverse iterators to initialize and return temporary std::string
std::reverse() is used to reverse the elements within the range given by the two parameters, str.begin() and str.end() in your case. This does not return a new reversed string, instead it reverses the collection itself.
If you want the reversed content in a new variable, you must first copy the original string into a new string and then reverse the new string. Alternatively you could use std::reverse_copy() which copies the reverse contents to a new string without affecting the original. It takes in a third parameter that tells where the reversed content must be copied. Do note the reversed string variable must first be resized to the original string's size.
std::string reverseStr(std::string& str) {
std::string reversedStr;
reversedStr.resize(str.size());
std::reverse_copy(str.begin(), str.end(), reversedStr.begin());
return reversedStr;
}
Some additional info: std::reverse() and std::reverse_copy() are present in the <algorithm> header file. <bits/stdc++.h> is non-standard and compiler specific and hence should be avoided. Check this answer for more details: Why should I not #include <bits/stdc++.h>?

Extracting and Creating separate txt files for each line of the source file [duplicate]

This question already has answers here:
Easiest way to convert int to string in C++
(30 answers)
Closed 7 years ago.
I was wondering if there was an alternative to itoa() for converting an integer to a string because when I run it in visual Studio I get warnings, and when I try to build my program under Linux, I get a compilation error.
In C++11 you can use std::to_string:
#include <string>
std::string s = std::to_string(5);
If you're working with prior to C++11, you could use C++ streams:
#include <sstream>
int i = 5;
std::string s;
std::stringstream out;
out << i;
s = out.str();
Taken from http://notfaq.wordpress.com/2006/08/30/c-convert-int-to-string/
boost::lexical_cast works pretty well.
#include <boost/lexical_cast.hpp>
int main(int argc, char** argv) {
std::string foo = boost::lexical_cast<std::string>(argc);
}
Archeology
itoa was a non-standard helper function designed to complement the atoi standard function, and probably hiding a sprintf (Most its features can be implemented in terms of sprintf): http://www.cplusplus.com/reference/clibrary/cstdlib/itoa.html
The C Way
Use sprintf. Or snprintf. Or whatever tool you find.
Despite the fact some functions are not in the standard, as rightly mentioned by "onebyone" in one of his comments, most compiler will offer you an alternative (e.g. Visual C++ has its own _snprintf you can typedef to snprintf if you need it).
The C++ way.
Use the C++ streams (in the current case std::stringstream (or even the deprecated std::strstream, as proposed by Herb Sutter in one of his books, because it's somewhat faster).
Conclusion
You're in C++, which means that you can choose the way you want it:
The faster way (i.e. the C way), but you should be sure the code is a bottleneck in your application (premature optimizations are evil, etc.) and that your code is safely encapsulated to avoid risking buffer overruns.
The safer way (i.e., the C++ way), if you know this part of the code is not critical, so better be sure this part of the code won't break at random moments because someone mistook a size or a pointer (which happens in real life, like... yesterday, on my computer, because someone thought it "cool" to use the faster way without really needing it).
Try sprintf():
char str[12];
int num = 3;
sprintf(str, "%d", num); // str now contains "3"
sprintf() is like printf() but outputs to a string.
Also, as Parappa mentioned in the comments, you might want to use snprintf() to stop a buffer overflow from occuring (where the number you're converting doesn't fit the size of your string.) It works like this:
snprintf(str, sizeof(str), "%d", num);
Behind the scenes, lexical_cast does this:
std::stringstream str;
str << myint;
std::string result;
str >> result;
If you don't want to "drag in" boost for this, then using the above is a good solution.
We can define our own iota function in c++ as:
string itoa(int a)
{
string ss=""; //create empty string
while(a)
{
int x=a%10;
a/=10;
char i='0';
i=i+x;
ss=i+ss; //append new character at the front of the string!
}
return ss;
}
Don't forget to #include <string>.
С++11 finally resolves this providing std::to_string.
Also boost::lexical_cast is handy tool for older compilers.
I use these templates
template <typename T> string toStr(T tmp)
{
ostringstream out;
out << tmp;
return out.str();
}
template <typename T> T strTo(string tmp)
{
T output;
istringstream in(tmp);
in >> output;
return output;
}
Try Boost.Format or FastFormat, both high-quality C++ libraries:
int i = 10;
std::string result;
WIth Boost.Format
result = str(boost::format("%1%", i));
or FastFormat
fastformat::fmt(result, "{0}", i);
fastformat::write(result, i);
Obviously they both do a lot more than a simple conversion of a single integer
You can actually convert anything to a string with one cleverly written template function. This code example uses a loop to create subdirectories in a Win-32 system. The string concatenation operator, operator+, is used to concatenate a root with a suffix to generate directory names. The suffix is created by converting the loop control variable, i, to a C++ string, using the template function, and concatenating that with another string.
//Mark Renslow, Globe University, Minnesota School of Business, Utah Career College
//C++ instructor and Network Dean of Information Technology
#include <cstdlib>
#include <iostream>
#include <string>
#include <sstream> // string stream
#include <direct.h>
using namespace std;
string intToString(int x)
{
/**************************************/
/* This function is similar to itoa() */
/* "integer to alpha", a non-standard */
/* C language function. It takes an */
/* integer as input and as output, */
/* returns a C++ string. */
/* itoa() returned a C-string (null- */
/* terminated) */
/* This function is not needed because*/
/* the following template function */
/* does it all */
/**************************************/
string r;
stringstream s;
s << x;
r = s.str();
return r;
}
template <class T>
string toString( T argument)
{
/**************************************/
/* This template shows the power of */
/* C++ templates. This function will */
/* convert anything to a string! */
/* Precondition: */
/* operator<< is defined for type T */
/**************************************/
string r;
stringstream s;
s << argument;
r = s.str();
return r;
}
int main( )
{
string s;
cout << "What directory would you like me to make?";
cin >> s;
try
{
mkdir(s.c_str());
}
catch (exception& e)
{
cerr << e.what( ) << endl;
}
chdir(s.c_str());
//Using a loop and string concatenation to make several sub-directories
for(int i = 0; i < 10; i++)
{
s = "Dir_";
s = s + toString(i);
mkdir(s.c_str());
}
system("PAUSE");
return EXIT_SUCCESS;
}
Allocate a string of sufficient length, then use snprintf.
int number = 123;
stringstream = s;
s << number;
cout << ss.str() << endl;
I wrote this thread-safe function some time ago, and am very happy with the results and feel the algorithm is lightweight and lean, with performance that is about 3X the standard MSVC _itoa() function.
Here's the link. Optimal Base-10 only itoa() function? Performance is at least 10X that of sprintf(). The benchmark is also the function's QA test, as follows.
start = clock();
for (int i = LONG_MIN; i < LONG_MAX; i++) {
if (i != atoi(_i32toa(buff, (int32_t)i))) {
printf("\nError for %i", i);
}
if (!i) printf("\nAt zero");
}
printf("\nElapsed time was %f milliseconds", (double)clock() - (double)(start));
There are some silly suggestions made about using the caller's storage that would leave the result floating somewhere in a buffer in the caller's address space. Ignore them. The code I listed works perfectly, as the benchmark/QA code demonstrates.
I believe this code is lean enough to use in an embedded environment. YMMV, of course.
The best answer, IMO, is the function provided here:
http://www.jb.man.ac.uk/~slowe/cpp/itoa.html
It mimics the non-ANSI function provided by many libs.
char* itoa(int value, char* result, int base);
It's also lightning fast and optimizes well under -O3, and the reason you're not using c++ string_format() ... or sprintf is that they are too slow, right?
If you are interested in fast as well as safe integer to string conversion method and not limited to the standard library, I can recommend the format_int method from the {fmt} library:
fmt::format_int(42).str(); // convert to std::string
fmt::format_int(42).c_str(); // convert and get as a C string
// (mind the lifetime, same as std::string::c_str())
According to the integer to string conversion benchmarks from Boost Karma, this method several times faster than glibc's sprintf or std::stringstream. It is even faster than Boost Karma's own int_generator as was confirm by an independent benchmark.
Disclaimer: I'm the author of this library.
Note that all of the stringstream methods may involve locking around the use of the locale object for formatting. This may be something to be wary of if you're using this conversion from multiple threads...
See here for more. Convert a number to a string with specified length in C++
On Windows CE derived platforms, there are no iostreams by default. The way to go there is preferaby with the _itoa<> family, usually _itow<> (since most string stuff are Unicode there anyway).
Most of the above suggestions technically aren't C++, they're C solutions.
Look into the use of std::stringstream.

C++ Code optimization

I have created my custom function to turn a wstring into lower case. However, it is pretty slow in DebugMode. Yes, I know ReleaseMode is what counts, but anyway it is pretty unnerving.
wstring wstringToLower(wstring u)
{
wstring s;
for (int i=0;i<u.size();i++)
{
wstring sChar;
sChar=u.substr(i,1);
int iChar=static_cast<int>(sChar[0]);
int iNewChar=charCodeToLower(iChar);
wstring sNewChar=wstring(1,iNewChar);
s.append(sNewChar);
}
return s;
}
Does anybody see anything obvious that I could improve to speed up the code, even in DebugMode?
Thank you!
There's no need to make temporary strings.
So, for start, instead of:
wstring sNewChar=wstring(1,iNewChar);
s.append(sNewChar);
This should do the trick:
s.push_back(iNewChar);
Then, instead of:
wstring sChar;
sChar=u.substr(i,1);
int iChar=static_cast<int>(sChar[0]);
This should work:
int iChar=static_cast<int>(u[i]);
And, of course, as noted by Marcel, you can do everything on the passed copy, avoiding the extra string allocation.
Also, as noted in the comments: How to convert std::string to lower case? . Also, read all answers (and comments) here: how to Make lower case letters for unicode characters :
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
int main()
{
::setlocale(LC_ALL,"");
std::wstring data = L"НЕМАЊА БОРИЋ"; // Wide chars
std::transform(data.begin(), data.end(), data.begin(), ::towlower);
// prints немања борић
std::wcout << data << std::endl;
return 0;
}
http://en.cppreference.com/w/cpp/string/wide/towlower
First of all I would avoid to allocate memory for variables each run, since allocating is a heavy operation.
Then do not call u.size() in the for-loop declaration. It will be called every loop otherwise. Every function call less that you call in a loop is a good win for performance.
Next everything Nemanja Boric said in the other answer.
And since the variable u is passed as copy, you can use it as return value and operate directly on it.
wstring wstringToLower(wstring u)
{
int size = u.size();
for (int i = 0; i < size; ++i)
{
u[i] = charCodeToLower(static_cast<int>(u[i]));
}
return u;
}
Conclusion: Basically avoid to allocate memory or calling functions in loops. Do just as much as you really have to.
There is actually no need for the wstringToLower function at all. You can use <algorithm> to do most of the work:
std::wstring str = "Some String";
std::transform(str.begin(), str.end(), str.begin(), ::towlower);
If you are trying to localize it, you may want to modify it slightly:
std::wstring str = "Some String";
std::locale loc; // set your locale
std::transform(str.begin(), str.end(), str.begin(), [](wchar_t c)
{
return use_facet<ctype<wchar_t>>(loc).tolower(c);
});

Mixing c++ standard strings and windows API

Many windows APIs take a pointer to a buffer and a size element but the result needs to go into a c++ string. (I'm using windows unicode here so they are wstrings)
Here is an example :-
#include <iostream>
#include <string>
#include <vector>
#include <windows.h>
using namespace std;
// This is the method I'm interested in improving ...
wstring getComputerName()
{
vector<wchar_t> buffer;
buffer.resize(MAX_COMPUTERNAME_LENGTH+1);
DWORD size = MAX_COMPUTERNAME_LENGTH;
GetComputerNameW(&buffer[0], &size);
return wstring(&buffer[0], size);
}
int main()
{
wcout << getComputerName() << "\n";
}
My question really is, is this the best way to write the getComputerName function so that it fits into C++ better, or is there a better way? I don't see any way to use a string directly without going via a vector unless I missed something? It works fine, but somehow seems a little ugly. The question isn't about that particular API, it's just a convenient example.
In this case, I don't see what std::vector brings to the party. MAX_COMPUTERNAME_LENGTH is not likely to be very large, so I would simply use a C-style array as the temporary buffer.
See this answer to another question. It provides the source to a StringBuffer class which handles this situation very cleanly.
I would say, since you are already at task of abstracting Windows API behind a more generic C++ interface, do away with vector altogether, and don't bother about wstring constructor:
wstring getComputerName()
{
wchar_t name[MAX_COMPUTERNAME_LENGTH + 1];
DWORD size = MAX_COMPUTERNAME_LENGTH;
GetComputerNameW(name, &size);
return name;
}
This function will return a valid wstring object.
I'd use the vector. In response to you saying you picked a bad example, pretend for a moment that we don't have a reasonable constant upper bound on the string length. Then it's not quite as easy:
#include <string>
#include <vector>
#include <windows.h>
using std::wstring;
using std::vector;
wstring getComputerName()
{
DWORD size = 1; // or a bigger number if you like
vector<wchar_t> buffer(size);
while ((GetComputerNameW(&buffer[0], &size) == 0))
{
if (GetLastError() != ERROR_BUFFER_OVERFLOW) aargh(); // handle error
buffer.resize(++size);
};
return wstring(&buffer[0], size);
}
In practice, you can probably get away with writing into a string, but I'm not entirely sure. You certainly need additional guarantees made by your implementation of std::wstring, beyond what's in the standard, but I expect MSVC's strings are probably OK.
I think that if wstring::reference is wchar_t& then you're sorted. 21.3.4 defines that non-const operator[] returns a reference, and that it returns data()[pos]. So if reference is just a plain wchar_t& then there's no scope for exciting copy-on-write behaviour through the reference, and the string must in fact be modifiable through the pointer &buffer[0]. I think. The basic problem here is that the standard allowed implementations more flexibility than turned out to be needed.
That's a lot of effort and commenting though, just to avoid copying a string, so I've never felt the need to avoid an intermediate array/vector.

Alternative to itoa() for converting integer to string C++? [duplicate]

This question already has answers here:
Easiest way to convert int to string in C++
(30 answers)
Closed 7 years ago.
I was wondering if there was an alternative to itoa() for converting an integer to a string because when I run it in visual Studio I get warnings, and when I try to build my program under Linux, I get a compilation error.
In C++11 you can use std::to_string:
#include <string>
std::string s = std::to_string(5);
If you're working with prior to C++11, you could use C++ streams:
#include <sstream>
int i = 5;
std::string s;
std::stringstream out;
out << i;
s = out.str();
Taken from http://notfaq.wordpress.com/2006/08/30/c-convert-int-to-string/
boost::lexical_cast works pretty well.
#include <boost/lexical_cast.hpp>
int main(int argc, char** argv) {
std::string foo = boost::lexical_cast<std::string>(argc);
}
Archeology
itoa was a non-standard helper function designed to complement the atoi standard function, and probably hiding a sprintf (Most its features can be implemented in terms of sprintf): http://www.cplusplus.com/reference/clibrary/cstdlib/itoa.html
The C Way
Use sprintf. Or snprintf. Or whatever tool you find.
Despite the fact some functions are not in the standard, as rightly mentioned by "onebyone" in one of his comments, most compiler will offer you an alternative (e.g. Visual C++ has its own _snprintf you can typedef to snprintf if you need it).
The C++ way.
Use the C++ streams (in the current case std::stringstream (or even the deprecated std::strstream, as proposed by Herb Sutter in one of his books, because it's somewhat faster).
Conclusion
You're in C++, which means that you can choose the way you want it:
The faster way (i.e. the C way), but you should be sure the code is a bottleneck in your application (premature optimizations are evil, etc.) and that your code is safely encapsulated to avoid risking buffer overruns.
The safer way (i.e., the C++ way), if you know this part of the code is not critical, so better be sure this part of the code won't break at random moments because someone mistook a size or a pointer (which happens in real life, like... yesterday, on my computer, because someone thought it "cool" to use the faster way without really needing it).
Try sprintf():
char str[12];
int num = 3;
sprintf(str, "%d", num); // str now contains "3"
sprintf() is like printf() but outputs to a string.
Also, as Parappa mentioned in the comments, you might want to use snprintf() to stop a buffer overflow from occuring (where the number you're converting doesn't fit the size of your string.) It works like this:
snprintf(str, sizeof(str), "%d", num);
Behind the scenes, lexical_cast does this:
std::stringstream str;
str << myint;
std::string result;
str >> result;
If you don't want to "drag in" boost for this, then using the above is a good solution.
We can define our own iota function in c++ as:
string itoa(int a)
{
string ss=""; //create empty string
while(a)
{
int x=a%10;
a/=10;
char i='0';
i=i+x;
ss=i+ss; //append new character at the front of the string!
}
return ss;
}
Don't forget to #include <string>.
С++11 finally resolves this providing std::to_string.
Also boost::lexical_cast is handy tool for older compilers.
I use these templates
template <typename T> string toStr(T tmp)
{
ostringstream out;
out << tmp;
return out.str();
}
template <typename T> T strTo(string tmp)
{
T output;
istringstream in(tmp);
in >> output;
return output;
}
Try Boost.Format or FastFormat, both high-quality C++ libraries:
int i = 10;
std::string result;
WIth Boost.Format
result = str(boost::format("%1%", i));
or FastFormat
fastformat::fmt(result, "{0}", i);
fastformat::write(result, i);
Obviously they both do a lot more than a simple conversion of a single integer
You can actually convert anything to a string with one cleverly written template function. This code example uses a loop to create subdirectories in a Win-32 system. The string concatenation operator, operator+, is used to concatenate a root with a suffix to generate directory names. The suffix is created by converting the loop control variable, i, to a C++ string, using the template function, and concatenating that with another string.
//Mark Renslow, Globe University, Minnesota School of Business, Utah Career College
//C++ instructor and Network Dean of Information Technology
#include <cstdlib>
#include <iostream>
#include <string>
#include <sstream> // string stream
#include <direct.h>
using namespace std;
string intToString(int x)
{
/**************************************/
/* This function is similar to itoa() */
/* "integer to alpha", a non-standard */
/* C language function. It takes an */
/* integer as input and as output, */
/* returns a C++ string. */
/* itoa() returned a C-string (null- */
/* terminated) */
/* This function is not needed because*/
/* the following template function */
/* does it all */
/**************************************/
string r;
stringstream s;
s << x;
r = s.str();
return r;
}
template <class T>
string toString( T argument)
{
/**************************************/
/* This template shows the power of */
/* C++ templates. This function will */
/* convert anything to a string! */
/* Precondition: */
/* operator<< is defined for type T */
/**************************************/
string r;
stringstream s;
s << argument;
r = s.str();
return r;
}
int main( )
{
string s;
cout << "What directory would you like me to make?";
cin >> s;
try
{
mkdir(s.c_str());
}
catch (exception& e)
{
cerr << e.what( ) << endl;
}
chdir(s.c_str());
//Using a loop and string concatenation to make several sub-directories
for(int i = 0; i < 10; i++)
{
s = "Dir_";
s = s + toString(i);
mkdir(s.c_str());
}
system("PAUSE");
return EXIT_SUCCESS;
}
Allocate a string of sufficient length, then use snprintf.
int number = 123;
stringstream = s;
s << number;
cout << ss.str() << endl;
I wrote this thread-safe function some time ago, and am very happy with the results and feel the algorithm is lightweight and lean, with performance that is about 3X the standard MSVC _itoa() function.
Here's the link. Optimal Base-10 only itoa() function? Performance is at least 10X that of sprintf(). The benchmark is also the function's QA test, as follows.
start = clock();
for (int i = LONG_MIN; i < LONG_MAX; i++) {
if (i != atoi(_i32toa(buff, (int32_t)i))) {
printf("\nError for %i", i);
}
if (!i) printf("\nAt zero");
}
printf("\nElapsed time was %f milliseconds", (double)clock() - (double)(start));
There are some silly suggestions made about using the caller's storage that would leave the result floating somewhere in a buffer in the caller's address space. Ignore them. The code I listed works perfectly, as the benchmark/QA code demonstrates.
I believe this code is lean enough to use in an embedded environment. YMMV, of course.
The best answer, IMO, is the function provided here:
http://www.jb.man.ac.uk/~slowe/cpp/itoa.html
It mimics the non-ANSI function provided by many libs.
char* itoa(int value, char* result, int base);
It's also lightning fast and optimizes well under -O3, and the reason you're not using c++ string_format() ... or sprintf is that they are too slow, right?
If you are interested in fast as well as safe integer to string conversion method and not limited to the standard library, I can recommend the format_int method from the {fmt} library:
fmt::format_int(42).str(); // convert to std::string
fmt::format_int(42).c_str(); // convert and get as a C string
// (mind the lifetime, same as std::string::c_str())
According to the integer to string conversion benchmarks from Boost Karma, this method several times faster than glibc's sprintf or std::stringstream. It is even faster than Boost Karma's own int_generator as was confirm by an independent benchmark.
Disclaimer: I'm the author of this library.
Note that all of the stringstream methods may involve locking around the use of the locale object for formatting. This may be something to be wary of if you're using this conversion from multiple threads...
See here for more. Convert a number to a string with specified length in C++
On Windows CE derived platforms, there are no iostreams by default. The way to go there is preferaby with the _itoa<> family, usually _itow<> (since most string stuff are Unicode there anyway).
Most of the above suggestions technically aren't C++, they're C solutions.
Look into the use of std::stringstream.