One if else statement will not execute - c++

Below is the section I am having trouble with
if(transition == *(vec.end()-1)) { //vec contains the ASCI code
vec.pop_back();
--vec_index;
result.append(vec[vec_index]);
} else if(colors.find(modified.substr(1)) == colors.end()) {
cout << result << endl;
cout << "\033[0;37m";
cerr << "**ERROR: INVALID CLOSING COLOR TAG ON LINE: "
//cerr << "**ERROR: OVERLAPPING CLOSING COLOR TAG ON LINE: "
<< nlines << endl;
exit(0);
} else {
cout << result << endl;
cout << "\033[0;37m";
cerr << "**ERROR: INVALID CLOSING COLOR TAG ON LINE: "
//cerr << "**ERROR: OVERLAPPING CLOSING COLOR TAG ON LINE: "
<< nlines << endl;
exit(0);
}
In the above code, my else-if statement does not seem to execute at all. What I am trying to do is when modified.substr(1) is not found in the map is print the first error otherwise (the color string is in the map but it's not the same one as the last one in the vector) print the "else" error. However, my else case is always printing. The reason why it's modified.substr(1) is because modified (in this case) starts with a /.

transition = colors[modified.substr(1)];
will create an entry in map<> color; if it's not existing and value initialize it. That's why your else if condition will never be true. Use map::find instead of operator [] to find the entry. Something like,
map<string,string>::const_iterator it = colors.find(modified.substr(1)];
And use it instead of transition. You can de-reference it (as it->first for key and it->second for string-value) when needed to get the underlying string.

In your code vec is empty, so
if(transition == *(vec.end()-1))
leads to undefined behavior.

Related

Add line in .txt update or if line does not exist does not work

I'm trying to write a program that replaces a specific line with a word in it or if the line doesn't exist in the file it should add it. Kind of like a key value store.
I played around with the following code, unfortunately nothing came of it. Either he just overwrote the file and deleted the other lines, or he just didn't write anything at all. Finally, this code remained. It's inefficient and confusing, I know that but maybe you can help me.
!!! at the moment he is not writing anything to the file!!!
Code:
void edit(char*key, char*value){
ifstream filein("test.txt");
ofstream fileout("tempTest.txt");
if(!filein || !fileout)
{
cout << "Error opening files!" << endl;
return;
}
bool found = false;
string line;
while(getline(filein, line))
{
if(line.find(key) == 0)
{
fileout << key << "=" << value << endl;
found = true;
}
else
{
fileout << line << endl;
}
if(!found)
{
fileout << key << "=" << value << endl;
}
}
filein.close();
fileout.close();
remove("test.txt");
}
In your while loop, you keep writing
fileout << key << "=" << value << endl;
in every iteration, until your key is found.
That line should be outside of the loop.

VSCode Debug opens stl_map.h when attempting to step into function to debug it

I am attempting to debug a graph function that starts at one vertex and ends at a destination vertex upon finding it via a FS (First Search) algo. Upon calling the function during debug mode, the debugger opens stl_map.h (I assume it does this because the graph (vertices and edges) have been implemented within a map.
The parameters of the function are (map, startPerson, endPerson). I pass a map, and the two people parameters as follows (name of the function is bfsFacebook):
for (;;) {
cout << endl << "Enter the name of the starting person:\n";
getline(cin, startingPerson);
if (IS_QUIT(startingPerson))
break;
if (everyone.count(startingPerson) == 0) {
cout << "Invalid starting name.";
continue;
}
cout << endl << "Enter the name of the ending person:\n";
getline(cin, endingPerson);
if (IS_QUIT(endingPerson))
break;
if (everyone.count(endingPerson) == 0) {
cout << "Invalid ending name.";
continue;
}
//Breath-First search from starting node to end node (starting vertext to end vertex)
if (bfsFacebook(everyone, everyone[startingPerson], everyone[endingPerson]) == true) {
cout << "Path found between " << startingPerson << " and " << endingPerson << endl;
} else {
cout << "Path Not Found between " << startingPerson << " and " << endingPerson << endl;
}
}
cout << "Exiting..." << endl;
Here is the actual function:
bool bfsFacebook(map<string, Person> everyone, Person &startingPerson, Person &endingPerson) {
startingPerson.visited = true;
if (startingPerson.name == endingPerson.name && startingPerson.visited == true)
return true;
for (string somePerson : startingPerson.friends) {
if (everyone[somePerson].visited == false && bfsFacebook(everyone, everyone[somePerson], endingPerson)) {
return true;
}
}
return false;
}
Is there any particular reason why stepping into the function during debugging does not send me to the actual function?
If my question is not detailed enough, please let me know.
The call line:
bfsFacebook(everyone, everyone[startingPerson], everyone[endingPerson])
Starts by resolving the arguments before calling bfsFacebook with them.
You have two calls to map<string, Person>::operator[](const string&) which shall be done to resolve everyone[startingPerson] and everyone[endingPerson], so the next executed line in your program is in std::map
The map<Key, Value>::operator[](const Key&) may be optimized depending on the build, but in debug it's more likely to be present in the code.
As the std::map has been instantiated for <string, Person> by your own code, the debugger has no reason not to step in a function which existence is your responsibility.

My application is crashing using Do/While loop to parse table

I have 2 QCheckbox tables, each contains 11 elements.
I declare them as following in my class :
QCheckBox *sectionTable[10];
QCheckBox *postTable[10];
For each QCheckBox, I do this
QCheckBox* checkboxA = new QCheckBox("A");
sectionTable[0] = checkboxA;
Through my test method, I would like to return the content of each element of my QCheckbox tables.
To do so, I've done this test :
/** TEST() **/
void VGCCC::test()
{
sectionTable[0]->setText("A");
sectionTable[1]->setText("B");
sectionTable[2]->setText("C");
sectionTable[3]->setText("D");
postTable[0]->setText("E");
postTable[1]->setText("F");
postTable[2]->setText("G");
postTable[3]->setText("H");
int i=0;
do
{
m_testTextEdit->insertPlainText(sectionTable[i]->text());
std::cout << "SECTION TABLE " << sectionTable[i]->text().toStdString() << "\n" << std::endl;
i++;
}
while(!sectionTable[i]->text().isNull());
do
{
m_testTextEdit->insertPlainText(postTable[i]->text());
std::cout << "POST TABLE " << postTable[i]->text().toStdString() << "\n" << std::endl;
i++;
}
while(!postTable[i]->text().isEmpty());
}
My application is compiling, and also running. But when I call the test function, my application crash.
How can we explain this problem ?
I would like to notify that I get a result in my console. It seems my test is half working, but is crashing at the end of the 1st do/while loop, when I get out of my condition.
With regard to the 11 elements: QCheckBox *sectionTable[10]; defines only 10 slots (0 through 9) for elements.
int i=0;
do
{
m_testTextEdit->insertPlainText(sectionTable[i]->text());
std::cout << "SECTION TABLE " << sectionTable[i]->text().toStdString() << "\n" << std::endl;
i++;
}
while(!sectionTable[i]->text().isNull());
Has the potential to reach past ten or eleven elements. Unless the terminating condition is found earlier, there is nothing to stop sectionTable[i] from trying to read sectionTable[11] to call its text method. If it manages to survive the call to the out-of-range sectionTable[11]->text(), it will then try calling sectionTable[11]->text().isNull(). Possibly this will be survivable as well and not be NULL. In this case sectionTable[12] will be tested. This will continue until the program hits really bad memory and crashes, a null is found, or pigs become the terror of the airways we all know they truly wish to be.
Note that i is not set back to 0 after this loop, so the first postTable to be inspected in the next loop will be at the same index as the last sectionTable.
So if sectionTable[5]->text().isNull() was NULL, postTable[5] will be the first postTable indexed and inspected.
do
{
m_testTextEdit->insertPlainText(postTable[i]->text());
std::cout << "POST TABLE " << postTable[i]->text().toStdString() << "\n" << std::endl;
i++;
}
while(!postTable[i]->text().isEmpty());
This loop has the same error in the exit condition as the sectionTable loop.
I find out how to solve the problem. As said in the answer before (#user4581301), I didn't set back my iterator i to 0.
Also, to avoid the "out of range" crash, I put a second condition which is i<sizeof(sectionTable[i]);
This is my fonctional test function :
/** TEST() **/
void VGCCC::test()
{
int i = 0;
do
{
m_testTextEdit->insertPlainText(sectionTable[i]->text());
std::cout << "SECTION TABLE " << m_materialMap[sectionTable[i]].c_str() << "\n" << std::endl;
i++;
}
while(!sectionTable[i]->text().isNull() && i<sizeof(sectionTable[i]));
i = 0;
do
{
m_testTextEdit->insertPlainText(postTable[i]->text());
std::cout << "POST TABLE " << postTable[i]->text().toStdString() << "\n" << std::endl;
std::cout << "POST TABLE " << m_materialMap[postTable[i]].c_str() << "\n" << std::endl;
i++;
}
while(!postTable[i]->text().isEmpty() && i<sizeof(postTable[i]));
}

Why is my first ofstream output in my else block missing the fill character?

I'm using this code to output nodes of a huffman tree to a text file with a certain formatting. All the node outputs within the if block run as expected, but the first output in the else block is missing the '0' fill character after the "L:". It should output "L:076" but instead is outputting "L: 76". The cout looks correct but the text file isn't. All future loops through the else block output like they should, it's only the first loop that is missing the fill character. Here's a picture of my output
void preOrder(node* tree, std::ofstream& of) {
if (tree->label > 0) {
of << "I:" << tree->label << " ";
}
else {
std::cout.width(3);
std::cout << std::right;
std::cout.fill('0');
std::cout << int(tree->ch) << std::endl;
of << "L:";
of << of.fill('0');
of << std::right;
of << int(tree->ch);
of << " ";
return;
}
preOrder(tree->left, of);
preOrder(tree->right, of);
}
From cppreference.com:
The second form (2) sets fillch as the new fill character and returns the fill character used before the call.
"The second form" is the non-const version, that applies here. So my guess (I never used fill myself and I cannot compile your code as it is) would be that the call is correctly applied and then you put the old fill character (blank space presumably) to the stream, because you do:
of << of.fill('0');
Also, I noticed that you dont set the width of of.
Because you're hiding something naughty from us.
#include <iostream>
int main()
{
std::cout.width(3);
std::cout << std::right;
std::cout.fill('0');
std::cout << 3 << std::endl;
return 0;
}
Outputs 003 (live example).
Please provide an MCVE and I'll edit my answer to help you.

TinyXML2 EXC_BAD_ACCESS Im sure its a null ptr but no idea why

So I have been at this for days, and I have no idea why a BAD_ACCESS error is thrown. Sometimes it works, sometimes it doesn't.
void xmlParser::parseXML(string file){
tinyxml2::XMLDocument doc;
if(!doc.LoadFile(file.c_str()))
{
cout << "ERROR: TINYXML2 FAILED TO LOAD" << endl;
}
//XML FILE LAYOUT:
//<item>
// <type id="laserWeapon" name="Laser Rifle">
// <tooltip>
// <stats>
//</item>
//error seems to occur on this line
tinyxml2::XMLElement* elementType = doc.FirstChildElement("item")->FirstChildElement("type");
string id = elementType->Attribute("id");
string name = elementType->Attribute("name");
cout << "id: " << id << endl;
cout << "name: " << name << endl;
}
I use
xmlparser.parseXML(xmlparser.path+"laserRifle.xml");
to load the file. Should I be parsing this as a string, or is there some null ptr I'm neglecting? I've tried to do an 'if nullptr' clause, but it still turns out an error instead of skipping over it.
Any advice on what to do? I'm completely lost with this.
// item element can be missed and you'll get bad access. Do not chain your calls that way
tinyxml2::XMLElement* elementType = doc.FirstChildElement("item")->FirstChildElement("type");
// element type can be missed, as well as attributes id and name
string id = elementType->Attribute("id");
string name = elementType->Attribute("name");
cout << "id: " << id << endl;
cout << "name: " << name << endl;
}
Carefully check every element and attribute. Do not chain calls because every call can return null. If you check all nullptr cases you'll find your error