Check if multiple strings are empty and print their name - c++

Usually when i want to check if more input stored in a multiple strings are not empty i follow this simple approach:
std::string fieldA = "";
std::string fieldB = "";
std::string fieldC = "Hello";
Now, i can check for all:
if ( fieldA.empty() || fieldB.empty() || fieldC.empty() )
std::cout << "Oh oh.. one or more fields are empty << std::endl;
But it would be nice to know which fields are empty, then, i can write:
if ( fieldA.empty() )
std::cout << "fieldA is empty" << std::endl;
if ( fieldB.empty() )
std::cout << "fieldB is empty" << std::endl;
if ( fieldC.empty() )
std::cout << "fieldC is empty" << std::endl;
But in this way i can discover that fieldA is empty but not the fieldB and in this example i have only three fields, but with more fields?
What is the best practice to managing the control of many strings and locate the empty string?

PaulMcKenzies comment is the one you should follow. But assuming your example is an over simplification of your code, and you can't put all your variables in an array, I think you can be excused if you use a little macro to do stringification for you:
#define PRINT_IF_EMPTY(var) \
do { \
if (var.empty()) \
std::cout << #var " is empty" << std::endl; \
} while(0)
You can now replace your code with this:
PRINT_IF_EMPTY(fieldA);
PRINT_IF_EMPTY(fieldB);
PRINT_IF_EMPTY(fieldC);

You should use a separate FieldValidator class. With that, your code should look like this:
FieldValidator val;
val.requireNotEmpty("field1", field1);
val.requireNotEmpty("field2", field2);
The idea is that all the validation state is kept in one place. I'm sure such a class already exists somewhere since you are not the first to solve this task.

It's better to use container (std::vector, std::list, std::array e.t.c) for similar type of data.
Let's assume you have stored your std::string in std::vector.
std::vector<std::strting> data;
// Now you have to insert std::string in std::vector.
for( int i = 0; i < data.size(); i++) {
if(data[i].empty())
std::cout << "field" << (char)i+65 << " is empty \n";
}

You could use a for-range loop over an initializer list, if printing which field is empty is not mandatory and if you prefer the fields to be distinct variables :
for (const std::string str : {fieldA, fieldB, fieldC})
{
if (str.empty())
{
std::cout << "One or more fields are empty." << std::endl;
break; // Break out of the for loop
}
}

Related

How do I check whether an index of array is empty and then, if it is, skip to the next?

I'm trying to build a program that can register a user to the database (still learning cpp, I hope that in the near future I'll be able to work with database).
What I'm trying to do with this code is to check whether an index of array is empty for the user to store an ID in it. If it isn't empty, I want the program to keep looking for an empty index of array, for the new info to be stored in.
Here is the code:
void registro() {
std::string userid[3];
userid[0] = "Houkros"; // eventually I'll try to have this being read from a file or server database..
std::string userpass[3];
std::string usermail[3];
std::string userkey[3];
std::string getUid[3];
std::string getUpass[3];
std::string getUmail[3];
std::string getUkey[3];
std::cout << std::endl << " >>>> REGISTRATION <<<< " << std::endl;
std::cout << " =============================================== " << std::endl;
std::cout << std::endl;
std::cout << "Please, enter the desired user id: " << std::flush;
if (userid[0].empty())
{
std::cin >> userid[0];
}
else {
std::cin >> userid[1];
}
for (int i = 0; i < 2; i++)
{
std::cout << " Element of array: " << i << " is > " << userid[i] << std::endl;
}
Please consider the following definitions for an "empty" array element:
a) not initialised (unhelpful, cannot be checked)
b) never yet written to (same as a) )
c) contains "" (possible, but means that "" must not be accepted as an actual content)
d) is empty according to a second array in which that info is maintained (this is what I almost recommend)
e) contains a struct with a string and a maintained "empty" flag (this I recommend)
Whatever you do, make sure that you init all variables and array elements before first read-accessing them; i.e. in all cases first write something meaningful to it.

Reading Json file's root in c++ with jsoncpp

File:
{
"somestring":{
"a":1,
"b":7,
"c":17,
"d":137,
"e":"Republic"
},
}
how can I read the somestring value by jsoncpp?
Use the getMemberNames() method.
Json::Value root;
root << jsonString;
Json::Value::Members propNames = root.getMemberNames();
std::string firstProp = propNames[0];
std::cout << firstProp << '\n'; // should print somestring
If you want to see all the properties, you can loop through it using an iterator:
for (auto it: propNames) {
cout << "Property: " << *it << " Value: " << root[*it].asString() << "\n";
}
This simple loop will only work for properties whose values are strings. If you want to handle nested objects, like in your example, you'll need to make it recursive, which I'm leaving as an exercise for the reader.

Mysterious behaviors with pointers. (Internal elements of objects getting changed)

I'm trying to build a relational database for the class I'm in.
what's happening is that when I process my "Facts" and "Queries" input, I create a new relation object. And then I print them out. If I run one at a time they process just fine, but if I run them back to back, the second one modifies the contents of the vector of tokens within the other relation object.
Database.h
class Database
{
private:
datalogProgram program;
Relation theSchemes;
Relation theFacts;
std::vector<Token> FactsOrder;
public:
Database(datalogProgram input);
Database();
~Database();
Relation processSchemes(datalogProgram processme);
Relation processFacts(datalogProgram processme);
};
Database.cpp
And I apologize for all of the cout's I've been trying to debug this things for hours!
#include "Database.h"
#include <sstream>
Database :: Database(datalogProgram input)
{
// So first I will make a map with relations representing the Schemes Facts and Queries
// Thus I will have a database of schemes facts and queries, rules excluded and ignored for now.
program = input;
theSchemes = processSchemes(program);
theFacts = processFacts(program);
// just checking on progress.
std::cout << "SCHEMES" << std::endl;
theSchemes.printRelation();
std::cout << "FACTS" << std::endl;
theFacts.printRelation();
}
Database :: Database() {}
Database :: ~Database() {}
Relation Database :: processSchemes(datalogProgram input)
{
Relation temp;
// LETS START WITH SCHEMES
std::cout << "processing schemes" << std::endl;
std::vector<Scheme>* schemes = input.returnSchemeList();
// Process First Scheme
// Populate this first vector with ID's from schemes.
// std::vector<Token*> firstTuple;
std::vector<Token*> firstTuple;
std::vector<Token> idListONE;
firstTuple.push_back(input.returnFirstScheme()->returnFirstID());
// std::vector<Token> idListONE;
idListONE = input.returnFirstScheme()->returnCLEANidLIST();
for(int i = 0; i < input.returnFirstScheme()->returnCLEANidLIST().size(); i++)
firstTuple.push_back(&idListONE[i]);
temp = *new Relation(input.returnFirstScheme()->returnName(), firstTuple);
// NOW I NEED TO PROCESS THE REST OF THE SCHEMES
//Take a scheme off of the list, and work on it just like I did above.
for(int j = 0; j < schemes->size(); j++) {
// Populate this first vector with ID's from schemes.
std::vector<Token*> first;
first.clear();
first.push_back(schemes->at(j).returnFirstID());
std::vector<Token> idLista;
idLista.clear();
idLista = schemes->at(j).returnCLEANidLIST();
for(int i = 0; i < schemes->at(j).returnCLEANidLIST().size(); i++)
first.push_back(&idLista[i]);
temp.relationInsert(schemes->at(j).returnName(), first);
}
return temp;
//
// At this point I shoudl have a map with "Schemes" pointing to Relation Objects.
// I want to verify that this is working, so print out all data collected so far.
}
Relation Database :: processFacts(datalogProgram input)
{
Relation temporary;
// NOW WE PROCESS FACTS
// Order does matter, so I will create a vector to use as a key.
std::cout << "procesing facts" << std::endl;
std::vector<Fact>* facts = input.returnFactList();
std::string OUT2;
std::ostringstream convert2;
convert2 << facts->size();
OUT2 = convert2.str();
std::cout << "THE NUMBER OF FACTS IS " << OUT2 << std::endl;
// NOW I NEED TO PROCESS THE REST OF THE
//Take a scheme off of the list, and work on it just like I did above.
std::vector<Token*> firstTuple;
std::vector<Token> idListONE;
for(int j = 0; j < facts->size(); j++) {
std::cout << "NEW ITERATION:" << std::endl;
if(j==0) {
std::cout << "processing first fact" << std::endl;
// is the first Fact!
firstTuple.clear();
std::cout << "processing first fact --> tuple" << std::endl;
firstTuple.push_back(facts->at(j).returnFirstString());
idListONE.clear();
std::cout << "FIRST STRINGLIST" << std::endl;
idListONE = *facts->at(j).returnCleanStringList();
for(int i = 0; i < idListONE.size(); i++) {
std::cout << "FIRST STRING ITER" << std::endl;
firstTuple.push_back(&idListONE[i]);
}
FactsOrder.push_back(*facts->at(j).returnName());
std::cout << "creating first fact" << std::endl;
temporary = Relation(facts->at(j).returnName(), firstTuple);
} else {
std::cout << "processing A fact (ITER)" << std::endl;
// Populate this first vector with ID's from schemes.
std::vector<Token*> first;
first.clear();
std::cout << "processing fact, firststring (ITER)" << facts->at(j).returnFirstString()->getTokensValue() << std::endl;
first.push_back(facts->at(j).returnFirstString());
std::vector<Token> idLista;
idLista.clear();
std::cout << "getting stringlist (ITER)" << std::endl;
idLista = *facts->at(j).returnCleanStringList();
for(int i = 0; i < idLista.size(); i++) {
std::cout << "processing stringlist (ITER) ITER" << std::endl;
first.push_back(&idLista[i]);
}
FactsOrder.push_back(*facts->at(j).returnName());
std::cout << "adding fact" << std::endl;
temporary.relationInsert(facts->at(j).returnName(), first);
}
}
return temporary;
}
relation.cpp
Just so you can see it
Relation :: Relation(Token* key,std::vector<Token*> tuple)
{
std::pair<Token*,std::vector<Token*> > mypair (key,tuple);
contents.insert(mypair);
}
Relation :: Relation() {}
Relation :: ~Relation() {}
void Relation :: relationInsert(Token* key,std::vector<Token*> tuple)
{
std::pair<Token*,std::vector<Token*> > mypair (key,tuple);
contents.insert(mypair);
}
void Relation :: printRelation()
{
std::cout << "PRINT RELATION CALLED" << std::endl;
std::multimap<Token*,std::vector<Token*> >::iterator mapIT;
for(mapIT = contents.begin() ; mapIT != contents.end() ; mapIT ++) {
std::cout << "Key: " << mapIT->first->getTokensValue() "\nValues:" << std::endl;
for(int x = 0; x< mapIT->second.size() ; x++)
std::cout << " " << mapIT->second.at(x)->getTokensValue() << std::endl;
}
}
To solve your problem you must figure out object / pointer ownership in your code. Relation holds a relation between a pointer to Token and a list of other pointer to Tokens. It is ok to keep Token* rather then a copy of Token. (Especially if tokens can be large words you don't want to copy). But who "owns" and manages the tokens?
Lets look at an example
std::vector<Token*> firstTuple;
std::vector<Token> idListONE;
idListONE is a vector to actual Tokens. It is a function local variable so it will be discarded when we exit the function.
firstTuple is a vector to pointers of Tokens.
You push into it in the following manner:
firstTuple.push_back(&idListONE[i]);
So firstTuple tokens are pointers to the internal tokens inside idListONE. That might be valid but you must remember that as soon as idListONE is released or its memory is changed (its size increased for instance) firstTuple becomes invalid, because it will now point at memory that was released and using it may have undefined results and will likely crash the program.
Actually a few lines later you make that mistake:
temporary = Relation(facts->at(j).returnName(), firstTuple);
temporary is a Relation that holds a list to pointer of Tokens. It copies the list that means that it copies the token pointers. However the pointers it copies are to Tokens that belong to idListONE as soon as you exit the function idListONE is released and the pointers inside the Relation are no longer valid and using them is likely one source of the problems you are seeing. There might be additional problems like this in the code
In general there seems to be a lot of confusion about working with pointers vs working with objects.
Look at the following statement:
temp = *new Relation(input.returnFirstScheme()->returnName(), firstTuple);
new Relation(...) will allocate memory on the heap and initialize a Relation.
temp = *<ptr> will use operator= to copy the content on the right into temp. The Relation on the heap is forgotten and its memory is leaked.
Another example:
idListONE.clear();
std::cout << "FIRST STRINGLIST" << std::endl;
idListONE = *facts->at(j).returnCleanStringList();
first you clear idListONE then you use the operator= to overwrite it with a new list.
Why did you clear a list you are writing over?
Why do you return a pointer to a list from returnCleanStringList()? instead of a copy list or a const ref to an internal list? If you decided returnCleanStringList() should return a list by pointer rather then by value then why is the first thing you do is copying it?
Finally you really should choose one style and conform to it. In the long run it makes code clearer.
If you Camelize variable names then always do: idListONE -> idListOne
Also avoid members like 'idListONE', do you really need a different variables for the first index?

multimap iterator not working

I have a Playlist class that has a vector with Tracks and each Track has a multimap<long, Note> as datamember.
class Track {
private:
multimap<long, Note> noteList;
}
Using an iterator to acces the tracks is no problem, so this part here is working fine:
vector<Track>::iterator trackIT;
try{
for(noteIT = trackIT->getNoteList().begin(); noteIT != trackIT->getNoteList().end(); noteIT++){
cout << "---" << noteIT->second.getName() << endl;
}
}catch (int e){
cout << "exception #" << e << endl;
}
What I want to do next is iterate the Notes of each Track. But starting from this part all output is stopped. So I only get to see the first tracks name. Any cout's after that are not shown and the compiler isn't giving me any errors. Even the cout inside the try catch block isn't working..
vector<Track>::iterator trackIT;
multimap<long, Note>::iterator noteIT;
for(trackIT = this->playlist.getTracklist().begin(); trackIT < this->playlist.getTracklist().end(); trackIT++){
cout << trackIT->getTrackName() << endl;
for(noteIT = trackIT->getNoteList().begin(); noteIT != trackIT->getNoteList().end(); noteIT++){
cout << "---" << noteIT->second.getName() << endl;
}
}
cout << "random cout that is NOT shown" << endl; // this part doesn't show up in console either
Also, the method in my Track class that I'm using to add the Note objects looks like this:
void Track::addNote(Note &note) {
long key = 1000009;
this->noteList.insert(make_pair(key, note));
}
// I'm adding the notes to the track like this:
Note note1(440, 100, 8, 1, 1);
note1.setName("note1");
synthTrack.addNote(note1);
Any ideas why the iterator won't work?
Change
noteIT < trackIT->getNoteList().end()
To
noteIT != trackIT->getNoteList().end()
Not all iterators support less than / greater than comparisons.
If you have c++11 you can use a range-based for loop:
for (Note& note : trackIT->getNoteList())
Or you can use BOOST_FOREACH
BOOST_FOREACH (Note& note, trackIT->getNoteList())
You haven't shown the definitions of getTrackList or getNoteList, but there's a common mistake people make - if you return a copy of the container instead of a reference to it, the iterators will be pointing to different containers making comparisons impossible. Not only that but since the containers are temporary any use of the iterators results in undefined behavior.
If you are really hardcoding the track key, then there will only ever be one track in the map because std::map stores unique keys...
long key = 1000009; //If yo are really doing this, this key is already inserted so it will fail to insert more.
Also, if you would like a more elegant approach you could use function object.
struct print_track
{
void operator()(const Track& track)
{
cout << track.getTrackName() << endl;
std::for_each(track.getNoteList().begin(), track.getNoteList().end(), print_track_name());
}
};
struct print_note_name
{
void operator()(const std::pair<long,Note>& note_pair)
{
cout << "---" << note_pair.second.getName() << endl;
}
};
//In use...
std::for_each(playlist.getTracklist().begin(), playlist.getTracklist.end(), print_track());

Displaying custom failure message in UnitTest++?

I've got a UnitTest++ test class, which allows me to test that a class is parsing some strings correctly. Before running the test, I create a fixture that contain several strings to be tested by various functions in a loop. It seems to work fine, but the problem is that, in case of error, UnitTest++ will always give me the same error line, so I won't know which string exactly is causing the issue.
For example, it will output:
"[UnitTest++] ..\trunk\tests\Test_ChineseUtil.cpp(46): error: Failure in ParsePinyinT: ChineseUtil::parsePinyinT(pinyinT) == pinyinN"
But that doesn't tell me which string is not being parsed correctly.
So what I would like is to set some custom error message when a test fails (in that particular case, I would give it the first item in my array). Basically, I need something like:
CHECK(theTest, "my error message")
Is there such function in UnitTest++? Or maybe there is a better way to do what I'm trying to do?
For information, here is the code of my class:
#include <third_party/unittest++/UnitTest++.h>
#include <Application.h>
#include <ChineseUtil.h>
using namespace hanzi;
namespace chineseUtilTests {
class PinyinFixture {
public:
PinyinFixture() {
ChineseUtil::initialize();
testData << "third tone" << QString::fromUtf8("wo3") << QString::fromUtf8("wǒ");
testData << "no tone" << QString::fromUtf8("wo") << QString::fromUtf8("wo");
testData << "second tone" << QString::fromUtf8("guo2") << QString::fromUtf8("guó");
testData << "first tone" << QString::fromUtf8("jia1") << QString::fromUtf8("jiā");
testData << "fifth tone" << QString::fromUtf8("jia5") << QString::fromUtf8("jia");
testData << "two dots" << QString::fromUtf8("nu:") << QString::fromUtf8("nü");
testData << "two dots and tone" << QString::fromUtf8("nu:3") << QString::fromUtf8("nǚ");
}
~PinyinFixture() {
}
QStringList testData;
};
TEST_FIXTURE(PinyinFixture, ParsePinyinN) {
for (int i = 0; i < testData.size(); i++) {
QString pinyinN = testData[i][1];
QString pinyinT = testData[i][2];
CHECK(ChineseUtil::parsePinyinN(pinyinN) == pinyinT);
}
}
TEST_FIXTURE(PinyinFixture, ParsePinyinT) {
for (int i = 0; i < testData.size(); i++) {
QString pinyinN = testData[i][1];
QString pinyinT = testData[i][2];
CHECK(ChineseUtil::parsePinyinT(pinyinT) == pinyinN);
}
}
} // chineseUtilTests
If your class has an equality operator, you should be able to, instead of typing
CHECK(something == something_else);
use
CHECK_EQUAL( something, something_else);
The fact that your classes allow a == makes me thing you can do this. If the test fails, you should get something along the lines of "Expected something but got something else".
If you need more information, there are a couple other things you can do.
One is to add your own custom output in the test. If you need to know the value of i specifically, you can add a printout of i before each CHECK. However, this output may be too lengthy for large loops, so you can add your check a second time.
CHECK(ChineseUtil::parsePinyinN(pinyinN) == pinyinT);
if ( ChineseUtil::parsePinyinN(pinyinN) != pinyinT )
{
cout << "Your own custom message " << i << endl;
}
Another possibility is to modify the source code of UnitTest++ itself, then recompile the library. While I don't know the exact steps to do what you want to do, I've modified UnitTest++/src/Checks.h to improve the output of CHECK_ARRAY2D_CLOSE so it was more readable.
I have not compiled or tested the following, but the gist of it is to copy the UnitTest++ CHECK macro and expand it to take a message parameter that is std::string and combine that with the string representing the stringified version of value.
#define CHECK_MESSAGE(value, message) \
do \
{ \
try { \
if (!UnitTest::Check(value)) \
UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), (std::string(#value)+message).c_str()); \
} \
catch (...) { \
UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \
(std::string("Unhandled exception in CHECK(" #value)+message+std::string(", ")+message+std::string(")")).c_str()); \
} \
} while (0)