How would you unit test do_int_to_string_conversion?
#include <string>
#include <iostream>
void do_int_to_string_conversion(int i, std::string& s) {
switch(i) {
case 1:
s="1";
break;
case 2:
s="2";
break;
default:
s ="Nix";
}
}
int main(int argc, char** argv){
std::string little_s;
do_int_to_string_conversion(1, little_s);
do_int_to_string_conversion(2, little_s);
do_int_to_string_conversion(3, little_s);
}
Instead of worrying about how to test the function as it stands, I'd redesign the function to work a bit more sensibly, and test the re-designed version instead.
Right now, the function seems to have three separate (and only slightly related) responsibilities: do a conversion, modify an externally supplied string, and write some data to a stream. The stream to which it writes (std::cout) is also hard-coded -- a problem waiting to happen (e.g., conversion to a GUI environment is likely to be non-trivial).
I'd start by 1) splitting it up into logical functions, and 2) supplying the stream as a parameter.
std::string convert_int(int val) {
switch (val) {
case 1: return "1";
case 2: return "2";
default: return "Nix";
}
}
std::ostream &write_string(std::ostream &os, std::string const &s) {
return os << s;
}
I haven't included anything to (specifically) modify an externally supplied string -- obviously you can assign the return value from convert_int as you see fit, and the value of the string that was passed in wasn't being used anyway.
Truthfully, write_string is a good candidate to be eliminated entirely, but since you had that basic kind of capability, we'll retain it for the moment. Testing these is relatively simple -- for convert_int, we look at the string it returns, and compare to what we expect. For write_string, we can pass a stringstream instead of a normal ostream -- then we can use .str() to get that result as a string, and (again) compare to what we expect.
I assume this is just an example. Why can't you assert on the value of little_s after each call?
do_int_to_string_conversion(1, little_s);
assert_are_equal("1", little_s);
If you really need to ensure that the output has been written, you need to break your dependency on std::cout and use another std::ostream during tests.
This might be as simple as a global variable:
#if PRODUCTION
std::ostream my_output = std::cout;
#else
std::ostream my_output = std::ostringstream;
#endif
void setup()
{
my_output = std::ostringstream;
}
void print_hello()
{
my_output << "hello";
}
void test_hello_was_printed()
{
print_hello();
ASSERT("hello" == my_output.str());
}
Or something similar to that effect.
I'd change do_int_to_string_conversion so that it does just one thing (convert the in to a string).
void do_int_to_string_conversion(int i, std::string& s) {
switch(i) { ... }
}
This has no side effects, so you can write a simple unit test that verifies the output (s).
If I needed a function that printed the result of the conversion, I'd put that in a separate function, and I'd parameterize the output stream.
void output_int(int i, ostream &stream) {
std::string s;
do_int_to_string_conversion(i, s);
stream << s;
}
To unit test that, I'd pass in a std::stringstream object and check the result.
You can use something like Expect to pass it some input and verify that its output is what it should be.
Related
The one annoyance I have with the std::string class is that the only ways (that I could figure out after reading cplusplus.com's info about it) to get the location of the last character in the string is (stringVariable.length() - 1) or stringVariable.rfind(stringVariable.back()). It'd be nice if I could just do stringVariable.last(). This is for a function I wrote in a personal project that needs to reference this number of a user's input string.
Some ideas I had were creating a struct that is just a string and has the last() function as a member function, or a class that copies the string class and adds that member. With a struct, I'm not sure how (or if it's possible) to make it so I can make the variable assigned to the type automatically reference the string in it so that I don't need to make a constant member call. I'm taking the second C++ class in school right now, but we haven't touched on C++ classes yet.
I tried reading some guides and answers here about classes, and they don't look all that different from structs, but the more complex stuff in either case was Greek to me. I only learned how to use a struct as a holder for multiple variable types; like the name string and id int for a person, or something like that. I learned from the guides I can put functions in them, and define operator behavior too, but when I tried to define operator behavior for the string struct I made, I couldn't get it to work.
Based on the example I read, I tried:
str &operator=(const str &ing)
{
s = ing.s;
return s;
}
But when I tried to test it by using = to copy a str variable to a string variable I could cout, it errors that str can't be converted to string, so I tried a few adjustments, and after getting errors about the & and such, I ended up with:
string operator=(str ing)
{
return ing.s;
}
Which gets the same error. Here's the full struct test program I'm using:
#include <iostream>
#include <string>
using namespace std;
struct str
{
string s;
string operator=(str ing)
{
return ing.s;
}
int last()
{
return s.length() - 1;
}
};
int main()
{
str ing {"Hello World!"};
string i = ing;
cout << i;
return 0;
}
If I could get the = assignment to work, I'd try to get << and such to work with str, too.
If that doesn't turn out to be possible, my fallback is just using a function like:
int last(string str)
{
return str.length() - 1;
}
Edit: For More Info
I was asked many times in the comments what my actual need is for this. In truth it’s just that it annoys me that it doesn’t have that member function. I’m surprised it wasn’t implemented long ago.
Thanks to the commenters I was able to come up with the diabolical workaround of overloading an operator to make a string able to subtract a function to output the result of a string being input to the function. I used - because I was thinking script notation: stringVariable -l or stringVariable -last. Then I can also just use #define to remove the need for the operator, making it stringVariable last() (“last()” instead of “last” because aesthetic).
Another option I figured out was reversing positions and using #define to make it last stringVariable, or #define in - to make it last in stringVariable. Although the simplest version of the operator function for this by far is just defining a negative string as the int output directly. Not that any of that is really better than just using the function normally, but I enjoyed learning about those features of C++.
The single answerer also consolidated much of the commenters advice and brought it to the next level to give me a more elegant version of the idea I had to create my own class with a string that could do all the string stuff and the extra member. However taking the advice of reexamining my needs I think perhaps ‘string’ isn’t the only option I have for a user input container. I definitely need the int output made by stringVariable.size() - 1 with whatever char array I use (since it’s used in mathematical equations), but maybe a vector or something else could do that already?
I was briefly told about vectors in my previous class, but we weren’t allowed to use them. Since this is for a simulated environment I’m doing on my own (that I might use for the basis of a game some day) I can use anything I want though. I also decided to pull an allnighter last night and just started reading about containers at random on cplusplus.com.
So I’m wondering if perhaps a list or deque could work too. I wasn’t really taught about anything other than string and hardcoded arrays (yet) though. I use the string to store the user’s input to simplify the process of avoiding unforeseeable crashing/errors that come from bad user inputs, then just translate the strings to whatever I need with various functions I've written.
creating a struct that is just a string and has the last() function as a member function
That will work just fine, if you don't mind implementing the interfaces needed to convert between std::string <-> str.
Also, be aware that std::string indexes use std::string::size_type, which is not int. size_type is an unsigned type, typically std::size_t. std::string defines an npos constant to indicate "no index", that is what your last() function should return if the std::string is empty, eg:
std::string::size_type last_index() const
{
return !s.empty() ? s.size() - 1 : std::string::npos;
}
But, if you really want to have last() return an int (ie, your std::string will never exceed 2147483647 characters):
int last_index() const
{
return static_cast<int>(s.size()) - 1;
}
With a struct, I'm not sure how (or if it's possible) to make it so I can make the variable assigned to the type automatically reference the string in it so that I don’t need to make a constant member call.
In short, no.
Based on the example I read, I tried:
str &operator=(const str &ing)
{
s = ing.s;
return s;
}
It needs to return a reference to the str object that is being assigned to, not the std::string member that was actually modified, eg:
str& operator=(const str &rhs)
{
s = rhs.s;
return *this;
}
But when I tried to test it by using = to copy a str variable to a string variable I could cout, it errors that str can't be converted to string
Correct, it can't by default. You need to define a conversion operator for that purpose, eg:
operator std::string() const
{
return s;
}
If I could get the = assignment to work, I'd try to get << and such to work with str, too.
Yes, you should, eg:
std::ostream& operator<<(std::ostream &out, const str &rhs)
{
return out << rhs.s;
}
If that doesn't turn out to be possible, my fallback is just using a function
That is a good idea, eg:
std::string::size_type last_index(const std::string &s)
{
return !s.empty() ? s.size() - 1 : std::string::npos;
}
Or:
int last_index(const str::string &s)
{
return static_cast<int>(s.size()) - 1;
}
Here's the full struct test program I'm using
Try this:
#include <iostream>
#include <string>
using namespace std;
class str
{
private:
string s;
public:
str() = default;
str(const string &s) : s(s) {}
str& operator=(const str &rhs)
{
s = rhs.s;
return *this;
}
operator string() const
{
return s;
}
string::size_type last_index() const
{
return !s.empty() ? s.size() - 1 : string::npos;
}
friend ostream& operator<<(ostream &out, const str &rhs)
{
return out << rhs.s;
}
};
string::size_type last_index(const string &s)
{
return !s.empty() ? s.size() - 1 : string::npos;
}
int main()
{
str ing {"Hello World!"};
cout << ing << endl;
cout << ing.last_index() << endl;
string i = ing;
cout << i << endl;
cout << last_index(i) << endl;
return 0;
}
vector<string> cmdV = split(_cmd, " ");
switch (cmdV[0])
{
}
For some reason it gives me the error: "The value must have an integral or enum type" in cmdV[0]
If you really want to make a switch statement with values from a vector<string> you can use either atoi() or std::stoi(). More described in this answer: How can I convert a std::string to int?.
The following code should work:
#include <iostream>
#include <vector>
#include <string>
int main() {
std::vector<std::string> test;
test.push_back("2");
switch(std::stoi(test[0])) {
case 1:
std::cout << "IT WORKS!";
break;
case 2:
std::cout << "IT WORKS 2!";
break;
}
}
It should print "IT WORKS 2!" without errors.
Or if you would want a string such as std::string str = "Test" to be one of the cases you could use the answer in this previous question:
enum string_code {
eFred,
eBarney,
eWilma,
eBetty,
...
};
string_code hashit (std::string const& inString) {
if (inString == "Fred") return eFred;
if (inString == "Barney") return eBarney;
...
}
void foo() {
switch (hashit(stringValue)) {
case eFred:
...
case eBarney:
...
}
}
NOTE: You should read a bit and make sure you understand the errors that might occur if you do this. And also read about different data types or else errors like this might occur: wrong result of casting string to int C++
EDIT: As mentioned in the comment below by #theOtherMichael the code above is not a "real" hashing method. But as found in this post there is a way to use the same idea but actually hash the values.
constexpr unsigned int hash(const char *s, int off = 0) {
return !s[off] ? 5381 : (hash(s, off+1)*33) ^ s[off];
}
switch( hash(str) ){
case hash("one") : // do something
case hash("two") : // do something
}
What can happen here though is that different strings might return the same value but it should work.
switch statements require integral types on both the condition and the case statements (the latter of which must be known at compile-time). If you're making conditions based on the contents of a string, you must use something else, such as an if statement.
If you have to do a lot of conditional programming based on your strings, you might consider hashing your strings into integers. If done right, this can allow you to use switch statements in a switch faster than full string compares can be done. I made a compile-time version of the SpookyHash algorithm for this exact purpose.
I would like to be able to do the following:
std::cout << str_manip("string to manipulate");
as well as
std::string str;
str_manip(str);
std::cout << str;
For this, I have two functions
#include <string>
// copying
std::string str_manip(std::string str)
{
// manipulate str
return str;
}
// in-place
void str_manip(std::string& str)
{
// manipulate str
}
but they produce the following error:
error: call of overloaded 'str_manip(std::__cxx11::string&)' is ambiguous
How can I overcome this?
The problem is with this call:
std::string str;
str_manip(str);
std::cout << str;
The compiler doesn't know which version of str_manip to call.
You can change your functions to look like this:
#include <string>
// copying
std::string str_manip(const std::string& str)
{
std::string dup = str;
// manipulate dup
return dup;
}
// in-place
void str_manip(std::string& str)
{
// manipulate str
}
Now, the compiler knows that the ambiguous call has to be the function that takes the non-const parameter. You can also be sure that your call that returns a std::string to the << operator isn't modifying your string.
This might be not the thing you are looking for, but for your code
std::cout << str_manip("string to manipulate");
the parameter to str_manip is not a string but const char* (actually an array, but convertible to a char pointer). You can overload based on that.
std::string str_manip(const char* s)
{
std::string str(s); // create str
// manipulate str
return str;
}
However, let's look at the big picture. When you see str_manip in your code, does this mean "change the string" or "make a new string based on the given string"? Do you want to be intentionally ambivalent on the real meaning?
Consider yourself reading your code in 1 year in future. What will you think when you see a call to str_manip - does this mutate its parameter? Does the answer to the previous question depend on context?
The goal in writing code is to make it clear, especially in a multi-paradigm language like C++. So, in my opinion, just don't do overloading that you are thinking about. Instead, make 2 distinct names, like
void frobnicate_str(std::string&) {...}
std::string get_frobnicated_str(std::string) {...}
I want to extend the usage of std::cout to use my own console/cout wrapper class.
Ideally I would have 2 ostreams, one for regular printing and one that appends a new line.
std::ostream Write;
Write << "Hello, I am " << 99 << " years old.";
prints Hello, I am 99 years old.
std::ostream WriteLine;
WriteLine << "Hello, I am " << 99 << " years old.";
prints Hello, I am 99 years old.\n (an actual new line, not just it escaped)
I would then like to extend this to have error streams (Error and ErrorLine, for example) which prefix "ERROR: " before the message and prints in a different color.
I know I have to create my own streams to add in this functionality, and I followed C++ cout with prefix for prefixing std::cout which was almost what I wanted but not quite. I couldn't figure out how to add a new line to the end of the stream, and the prefix was unreliable, especially when I would do more than a single print statement.
I should also mention I don't want to use overloaded operators to achieve this effect, because I want to be able to daisy-chain things on.
What didn't work
If I did WriteLine >> "First"; then WriteLine << "Second"; I would get weird results like SecondFirst\n or Second\nFirst. My ideal output would be First\nSecond\n. I think it is due to not closing/flushing/resetting the stream properly, but nothing I tried got it to work reliably.
I could get it to work for a single statement, but as soon as I added another print statement, the things I tried to print would switch order, the post/pre fix wouldn't get added in the correct spot, or I would end up with garbage.
I don't care about wchars, because we will always only need a single byte for a single char. Also we will only be working on Windows 10.
This is what I have so far:
Console.h
#include <windows.h>
#include <iostream>
#include <sstream>
#include <string>
class Console {
using Writer = std::ostream;
Console() {}
static const char newline = '\n';
class error_stream: public std::streambuf {
public:
error_stream(std::streambuf* s) : sbuf(s) {}
~error_stream() { overflow('\0'); }
private:
typedef std::basic_string<char_type> string;
int_type overflow(int_type c) {
if(traits_type::eq_int_type(traits_type::eof(), c))
return traits_type::not_eof(c);
switch(c) {
case '\n':
case '\r':
{
SetColor(ConsoleColor::Red);
prefix = "ERROR: ";
buffer += c;
if(buffer.size() > 1)
sbuf->sputn(prefix.c_str(), prefix.size());
int_type rc = sbuf->sputn(buffer.c_str(), buffer.size());
buffer.clear();
SetColor(ConsoleColor::White);
return rc;
}
default:
buffer += c;
return c;
}
}
std::string prefix;
std::streambuf* sbuf;
string buffer;
};
class write_line_stream: public std::streambuf {
public:
write_line_stream(std::streambuf* s) : sbuf(s) {}
~write_line_stream() { overflow('\0'); }
private:
typedef std::basic_string<char_type> string;
int_type overflow(int_type c) {
if(traits_type::eq_int_type(traits_type::eof(), c))
return traits_type::not_eof(c);
switch(c) {
case '\n':
case '\r':
{
buffer += c;
int_type rc = sbuf->sputn(buffer.c_str(), buffer.size());
sbuf->sputn(&newline, 1);
buffer.clear();
return rc;
}
default:
buffer += c;
return c;
}
}
std::streambuf* sbuf;
string buffer;
};
static output_stream outputStream;
static error_stream errorStream;
static write_line_stream writeLineStream;
public:
static void Setup();
static Writer Write;
static Writer WriteLine;
static Writer Err;
};
Console.cpp
#include "Console.h"
Console::Writer Console::Write(nullptr);
Console::Writer Console::WriteLine(nullptr);
Console::Writer Console::Err(nullptr);
Console::error_stream Console::errorStream(std::cout.rdbuf());
Console::write_line_stream Console::writeLineStream(std::cout.rdbuf());
void Console::Setup() {
Write.rdbuf(std::cout.rdbuf());
Err.rdbuf(&errorStream);
WriteLine.rdbuf(&writeLineStream);
}
Main.cpp
int main() {
Console::Setup();
Console::Write << "First" << "Second";
Console::WriteLine << "Third";
Console::WriteLine << "Fourth";
Console::Write << "Fifth";
Console::Error << "Sixth";
Console::ErrorLine << "Seventh";
Console::WriteLine << "Eighth";
}
Which should give an output of
FirstSecondThird
Fourth
FifthERROR: SixthERROR: Seventh
Eighth
Press any key to continue...
Any help and/or suggestions are appreciated.
There are multiple concerns here which do require different approaches. Some of the description also seems that the actual desire isn't quite clear. The most problematic requirement is that a newline needs to be inserted apparently at the end of a statement. That's certainly doable but effectively does require a temporary being around.
Before going there I want to point out that most other languages offering a print-line(....) construct delineate what is going onto a line using a function call. There is no doubt where the newline goes. If C++ I/O would be created now I'd be quite certain that it would be based on a variadic (not vararg) function template. This way print something at the end of the expression is trivial. Using a suitable manipulator at the end of the line (although probably not std::endl but maybe a custom nl) would be an easy approach.
The basics of adding a newline at the end of expression would be using a destructor of a suitable temporary object to add it. The straight forward way would be something like this:
#include <iostream>
class newline_writer
: public std::ostream {
bool need_newline = true;
public:
newline_writer(std::streambuf* sbuf)
: std::ios(sbuf), std::ostream(sbuf) {
}
newline_writer(newline_writer&& other)
: newline_writer(other.rdbuf()) {
other.need_newline = false;
}
~newline_writer() { this->need_newline && *this << '\n'; }
};
newline_writer writeline() {
return newline_writer(std::cout.rdbuf());
}
int main() {
writeline() << "hello, " << "world";
}
This works reasonable nice. The notation in the question doesn't use a function call, though. So, instead of writing
writeline() << "hello";
it seems necessary to write
writeline << "hello";
instead and still add a newline. This complicates matters a bit: essentially, writeline now needs to be an object which somehow causes another object to jump into existence upon use so the latter can do its work in the destructor. Using a conversion won't work. However, overloading an output operator to return a suitable object does work, e.g.:
class writeliner {
std::streambuf* sbuf;
public:
writeliner(std::streambuf* sbuf): sbuf(sbuf) {}
template <typename T>
newline_writer operator<< (T&& value) {
newline_writer rc(sbuf);
rc << std::forward<T>(value);
return rc;
}
newline_writer operator<< (std::ostream& (*manip)(std::ostream&)) {
newline_writer rc(sbuf);
rc << manip;
return rc;
}
} writeline(std::cout.rdbuf());
int main() {
writeline << "hello" << "world";
writeline << std::endl;
}
The primary purpose of the overloaded shift operators is to create a suitable temporary object. They don't try to mess with the content of the character stream. Personally, I'd rather have the extra parenthesis than using this somewhat messy approach but it does work. What is kind of important is that the operator is also overloaded for manipulators, e.g., to allow the second statement with std::endl. Without the overload the type of endl can't be deduce.
The next bit is writing the prefix and mixing multiple streams. The important bit here is to realize that you'd want to one of two things:
Immediately write the characters to a common buffer. The buffer is most like just another stream buffer, e.g., the destination std::streambuf.
If the character should be buffered locally in separate stream buffers, the corresponding streams need be flushed in a timely manner, e.g., after each insertion (by setting the std::ios_base::unitbuf bit) or, latest, at the end of the expression, e.g., using an auxiliary class similar to the newline_writer.
Passing through the characters immediately is fairly straight forward. The only slight complication is to know when to write a prefix: upon the first non-newline, non-carriage-return return after a newline or a carriage return (other definitions are possibly and should be easily adaptable). The important aspect is that stream buffer doesn't really buffer but actually passes through the character to the underlying [shared] stream buffer:
class prefixbuf
: public std::streambuf {
std::string prefix;
bool need_prefix = true;
std::streambuf* sbuf;
int overflow(int c) {
if (c == std::char_traits<char>::eof()) {
return std::char_traits<char>::not_eof(c);
}
switch (c) {
case '\n':
case '\r':
need_prefix = true;
break;
default:
if (need_prefix) {
this->sbuf->sputn(this->prefix.c_str(), this->prefix.size());
need_prefix = false;
}
}
return this->sbuf->sputc(c);
}
int sync() {
return this->sbuf->pubsync();
}
public:
prefixbuf(std::string prefix, std::streambuf* sbuf)
: prefix(std::move(prefix)), sbuf(sbuf) {
}
};
The remaining business is to set up the relevant objects in the Console namespace. However, doing so is rather straight forward:
namespace Console {
prefixbuf errorPrefix("ERROR", std::cout.rdbuf());
std::ostream Write(std::cout.rdbuf());
writeliner WriteLine(std::cout.rdbuf());
std::ostream Error(&errorPrefix);
writeliner ErrorLine(&errorPrefix);
}
I except that the approach adding the newline creates a custom type I think that matches the original goes. I don't think the temporary object can be avoided to automatically create a newline at the end of a statement.
All that said, I think you should use C++ idioms and not try to replicate some other language in C++. The way to choose whether a line end in newline or not in C++ is to write, well, a newline where one should appear potentially by way of a suitable manipulator.
Suppose that I have to call same method for each member of a vector contained in a class.
If element-i of the vector has a certain value, I have to modify it.
I've max 10 element in this vector.
What is the best way to do?
- Call a method with an optional parameter?
- Or call a method with an if-else statment inside?
class A {
public:
A();
void doSomething(const string& s) {
if(s=="foo") {
std::cout << s;
} else {
std::cout << s << ".dat"
}
}
void doSomethingDef(const string& s, const string& v = "") {
std::cout << s << v;
}
private:
std::vector<std::string> list_;
}
int main() {
A a;
}
/* Constructor with method 1 */
A::A() {
std::vector<std::string>::iterator i = list_.begin();
for(; i != list_.end(); ++i) {
this->doSomething(*i);
}
}
/* Constructor with method 2 */
A::A() {
this->doSomethingDef(list[0]);
this->doSomethingDef(list[1]);
this->doSomethingDef(list[2]);
this->doSomethingDef(list[3]);
this->doSomethingDef(list[4], ".dat");
this->doSomethingDef(list[5], ".dat");
this->doSomethingDef(list[6]);
this->doSomethingDef(list[7]);
this->doSomethingDef(list[8]);
this->doSomethingDef(list[9]);
}
If you have a max of 10 elements, I'm going to claim that performance is completely irrelevant anyway.
Furthermore, until you have proven that performance really matters, method 1 is so much more readable that you should prefer it anyway.
Finally, because of the way cout operations work, I would guess that in this little example, method 2 is actually slower, because it's faster to do a branch and a comparison with a fixed string than doing an additional call to a formatted output function.
In C++11 your constructor with method 1 could be written as:
A::A()
{
for(const auto & listElement : list_)
{
this->doSomething(listElement);
}
}
Performance and readability and a bit more generic to boot. Or you could do it with a std::for_each and a lambda function which may trigger a compiler with optimizations turned on to unroll that loop for you.
A::A()
{
for_each(begin(list_), end(list_),[this](const std::string & listElement)
{
doSomething(listElement);
});
}
If you decided to use something similar to your second method (not that I'm advising it, just considering how to do it if you were to), I'd strongly consider using overloading instead of a default parameter:
void doSomethingDef(const string& s) {
std::cout << s;
}
void doSomethingDef(const string &s, const string &v) {
std::cout << s << v;
}
With a default parameter, you're still creating a temporary string and passing it as the second parameter, then making all the iostreams calls to insert that string into the stream even though it has no effect. By using overloading instead, you avoid all the processing necessary to create, pass, and insert the second string (except when you really have a second string to display, of course).
Mixing that with I/O (and only writing 10 strings anyway) probably covers up most of the benefit from this, so it'll probably be hard to even measure, not to mention notice in real life. On the other hand, if you were generating a lot of strings and (for example) depositing the output in memory instead of writing it to output, the difference could start to become substantial.