C++ adding n strings to a string stream [duplicate] - c++

This question already has answers here:
Variable number of arguments in C++?
(17 answers)
Closed 4 years ago.
I am kind of stuck in pre C++ 11 land. How can I write a function that takes n strings and appends them to an ostreamstream?
void Foo(std::string first_part, ...){
std::ostringstream oss;
oss << first_part << ...; // cant do it
for(int i = 0; i < ....length(); i++){ // :|
}
}
If I lived in a perfect world I could do the above. Is there any other way pre C++ 11 to loop through the ... arguments?

Sorry, but it can't be done directly (at least not in portable code).
Attempting to pass a non-trivial type (including std::string) as a variadic argument gives undefined behavior.
If you want to do something similar, you could (for one example) pass the addresses of a number of strings rather than attempting to pass the strings themselves.
If you do that, you'll still have to contend with one other detail: you'll need to tell the receiving function the number of (addresses of) strings to expect.
From there, the receiving function would use va_start, va_arg and va_end to retrieve the data and do it's thing with them.

Related

Does std::string works only with 'std::cin' in c++ [duplicate]

This question already has answers here:
How to read and write a STL C++ string?
(3 answers)
Closed 4 years ago.
I've recently learnt about std::substr() by searching on Google. I saw a code something like this:
std::string s = "This is an example string";
std::string s1 = s.substr(11, 7);
std::cout << s1 << std::endl;
Now if I try to take input using scanf() function (instead of using std::cin), the program crashes during runtime. Doesn't std::string support using scanf() function?
scanf() belongs to a family of C functions that, being part of the C language rather than C++, offers no direct support for std::string and works instead with null terminated character strings.
If you are using C++, you should generally prefer std::string over null terminated terminated character strings and the input/output library over printf()/scanf() library functions.

C++: Safe reading from file with std::string (&str[0]) as a buffer? [duplicate]

This question already has an answer here:
Is writing to &str[0] buffer (of a std:string) well-defined behaviour in C++11?
(1 answer)
Closed 7 years ago.
I have a binary file that I'm reading from. In the file at one point, there is a known number of bytes which make up a simple ASCII string (possibly with newlines). Right now I have:
void doSomething(istream &in) {
vector<char> buf(length + 1, '\0');
in.read(&buf[0], length);
string str(&buf[0]);
}
But I realized that it would probably be faster to do
void doSomething(istream &in) {
string str(length + 1, '\0'); // +1 needed?
in.read(&str[0], length);
}
I tried looking in the standard to see if string allocation is always sequential or if it's safe doing something like this. Safe meaning, no accidental reading into (writing to) memory not part of the string. Does anyone know?
std::string allocation is always sequential, at least as of C++11. I believe prior to that it wasn't clearly defined so, but no implementations used non-sequential storage.
You do not need to explicitly add space for a null terminator in std::string.

MoveFileA() doesn't like my arguments [duplicate]

This question already has answers here:
How to convert std::string to LPCSTR?
(9 answers)
Closed 8 years ago.
I have a list of file names in a .txt document, and I would like to move each of these files from one folder to another.
Using MoveFileA() I am getting the error, "no suitable conversion between std::string and LCPSTR".
Here is my code, after opening up my .txt file:
while (std::getline(myfile, line))
{
std::string oldLocation = "C:\\Users\\name\\Desktop\\docs\\folder1\\" + line;
std::string newLocation = "C:\\Users\\name\\Desktop\\docs\\folder2\\" + line;
MoveFileA(oldLocation, newLocation);
}
If I type in the full path as arguments for MoveFileA, instead of sending it a variable, it works but I am unable to iterate over .txt file this way.
Any suggestions on how I might fix this?
LCPSTR means long constant pointer to a string, which means it's a null terminated c string.
std::string is an object. It is something different. But it luckily provides a convenience method c_str the provides a pointer to a constant c style string. So as the comment says you should go by:
MoveFileA(oldLocation.c_str(), newLocation.c_str());
It is worth of explicitly noting, that you can't drop it in every place instead of char*, but only when the string won't be modified. It returns const char*. This is where the C in LCPSTR gets important.

Nicely formatting numbers in C++ [duplicate]

This question already has answers here:
Representing big numbers in source code for readability?
(5 answers)
Closed 9 years ago.
In Ada it is possible to write numbers with underscores for separating digits, which greatly improves readability. For example: 1_000_000 (which is equivalent to 1000000)
Is there some similar way for C++?
EDIT: This is question about source code, not I/O.
As of C++14, you can use ' as a digit group separator:
auto one_m = 1'000'000;
Previous versions of C++ did not support this natively. There were two major workarounds:
Using user-defined literals in C++11; this would allow you to write code as follows:
auto x = "1_000_000"_i;
(Writing this as a constexpr would be trickier – but is definitely possible.)
Using a straightforward macro, which would allow the following code:
auto x = NUM(1,000,000);
There is no way to do this currently. There is, however, a proposal to introduce digit separators (N3499). They haven't yet chosen which character they'd like to use as a separator though. The current suggestions are:
Space: 4 815 162 342
Grave accent: 4`815`162`342
Single quote: 4'815'162'342
Underscore: 4_815_162_342
Unfortunately, they all have problems as described in the proposal.
You can take the hacky approach by using a user-defined literal:
long long operator "" _s(const char* cstr, size_t)
{
std::string str(cstr);
str.erase(std::remove(str.begin(), str.end(), ','), str.end());
return std::stoll(str);
}
int main()
{
std::cout << "4,815,162,342"_s << std::endl;
}
This will print out:
4815162342
It simply removes all of the commas from the given literal and converts it to an integer.
int main()
{
int x = 1e6;
}
you can always just define a variadic macro, used like N(123,456,678). it's a bit more trouble than it's worth, though. in particular, you may have to workaround some visual c++ peculiarities for portable code for counting arguments.
What you are looking for is perfectly possible by imbue()ing the I/O stream with the appropriate locale facet (in this case, num_put).
(This is assuming you are talking about I/O. If you are talking about the source itself, that is not possible as of C++11.)

convert integer to string for function parameter [duplicate]

This question already has answers here:
Easiest way to convert int to string in C++
(30 answers)
How to convert a number to string and vice versa in C++
(5 answers)
Closed 10 years ago.
I have a function which accept a string parameter and I have an integer variable then I should convert it to string and then pass it to that function I used this code but as ostringstream is for I/O it doesn't work.
ostringstream ostr;
while (.....)
{
regnum++;
ostr<<regnum;
grph.addlastname(ostr.str());
}
for example it pass 12345 to function instead of 5,what should I do?
It's true - there are a lot of similar questions which solve "What's the best way to do this?" but I think that there's something to learn for the OP in the answer to the question of "Why does this not work?"
Therefore:
Your stringstream has an internal state, and during your loop you always append a new digit - but the previous ones are still in the stream! You can fix this by making the stringstream scope-local to the loop, i.e. declaring it inside the loop rather than outside of it.
(std::to_string is still the better solution for this particular problem, though.)
Everything is fine except one thing,
see:
ostringstream ostr;
while (.....)
{
regnum++;
ostr<<regnum;
grph.addlastname(ostr.str());
}
Your declaring your ostr outside the while, the first time that while runs, it adds '1' to the ostr, the second time, because it's the same "ostringstream" variable, it adds '2', so your string will be '12' now...
Solution: Declare ostringstream ostr, inside your while, use std::to_string, or do a ostr.clear() every time that the while ends. (The best way si declaring your ostr inside your while)