Confused about behavior when reading stdin c++ - c++

I am attempting to solve a problem to improve my C++ skills. I have come across some unusual behavior and I am not sure why it is happening.
I initially parsed the stdin and sorted it into a map with a key and a matching element (value). I then want to read a list of keys and output the element (value). However, for some of the key names it returns the correct value but for others it does not, but, if I hard code the intended key it works.
I know I am parsing correctly since the correct key and value are in the map as shown at the end of my output.
I assume it is an issue with reading stdin since the boolean str.compare("tag1.tag2~name") == 0 never evaluates to 0.
The code is as follows:
//'it' is the name of my map
//q = 3
for (int i = 0; i < q; i++)
{
getline(cin, str);
if (str.compare("tag1.tag2~name") == 0)
{
cout << "key is found" << endl;
}
else
{
cout << "'" << str << "'" << endl;
}
if (it.count(str) == 0)
{
cout << "Not Found!" << endl;
}
else
{
cout << it[str] << endl;
}
}
map<string, string>::iterator ptr;
cout << "\nThe map it is : \n";
cout << "\tKEY\tELEMENT\n";
for (ptr = it.begin(); ptr != it.end(); ++ptr) {
cout << '\t' << ptr->first
<<"\t" + ptr->second << "\n";
}
return 0;
The output is:
'tag1.tag2~name
Not Found!
'tag1~name
Not Found!
'tag1~value'
HelloWorld
The map it is :
KEY ELEMENT
tag1.tag2~name Name1
tag1~value HelloWorld
The input is :
tag1.tag2~name
tag1~name
tag1~value
Thank you! I have been struggling with this for a while.

Related

Visual Studio C++ 2k15 - Getting error on pointer address

this is my first post on Stack Overflow :)
Sorry if I seems egoistic, but I have an exam tomorrow and I'm facing a problem that I cannot solve. Hope to find here an answer, I tried to find out if there was already an opened 3d, but I cannot find it.
Here's my problem:
I'm writing a code in C++, using the pointer. Because of I retrieve always the same error on a larger code, I tried with an easier one, but the error persists.
The code is the following:
#include <iostream>
using namespace std;
struct EXAMPLE {
int value;
EXAMPLE *next;
};
int insertnew(EXAMPLE *&sorting, EXAMPLE val);
int printlist(EXAMPLE *&sorting);
int main() {
int i;
EXAMPLE new;
EXAMPLE *list = NULL;
for (i = 0; i < 3; i++)
{
cout << "value: " << endl;
cin >> new.value;
insertnew(list, new);
}
printlist(list);
system("Pause");
return 0;
}
int insertnew(EXAMPLE *&sorting, EXAMPLE val){
EXAMPLE *temp;
temp = new EXAMPLE;
temp->value = val.value;
temp->next = sorting;
sorting = temp;
return 0;
}
int printlist(EXAMPLE *&sorting) {
while (sorting != 0)
{
sorting = sorting->next;
cout << sorting->next << " " << sorting->value << endl;
}
return 0;
}
It's an easy LIFO structure.
I get a bad reading access error on this line:
cout << elenco->next << " " << elenco->valore << endl;
But here's the curios thing.
If I revert the lines in this way:
int printlist(EXAMPLE *&sorting) {
while (sorting != 0)
{
cout << sorting->next << " " << sorting->value << endl;
sorting = sorting->next;
}
return 0;
}
as a FIFO structure, I got no error at all!
Can you help me understanding where the problem is?
Thanks in advance
//edit
Uops, find out my error.
The while was supposed to be a recursive function, dunno why I inserted a while, assuming it will function as a recursive function.
just solved
cout << lista->value << endl;
while (list != NULL)
{
list = list->next;
if (list != 0) {
cout << list->value << endl;
}
}
Sorry
Let's take a look at your example code:
int printlist(EXAMPLE *&sorting) {
while (sorting != 0) //As long as "sorting" is not null
{
sorting = sorting->next; //Set "sorting" to the next value
cout << sorting->next << " " << sorting->value << endl; //print the value
}
return 0;
}
Just play this code through if you have only one element in your LIFO list.
int printlist(EXAMPLE *&sorting) {
while (sorting != 0) //"sorting" is not null
{
sorting = sorting->next; //Set "sorting" to the next value, which is null
cout << sorting->next << " " << sorting->value << endl; //crash because "sorting" is null
}
return 0;
}
This will happen every time you hit the last element.
You can change your code to a do-while-loop with an additional if, or add an if with a break within your current loop. But I would recommend to go with a for-loop on this one.
Also you don't need to pass the pointer by reference. You even shouldn't do it, as you don't want to change your list when printing it (as your current code does...)
How about something like this:
int printlist(EXAMPLE * sorting) {
for (EXAMPLE * current = sorting; current != 0; current = current->next)
{
cout << current << " " << current->value << " -> " << current->next << endl;
}
return 0;
}
I also changed the output a little bit to show more interesting data.
You are trying to access the tail of the list when sorting->next reaches the last element. With the second code you access only list elements.
Clear, thanks
I also tried another version
int printlist(EXAMPLE *list) {
if (list != NULL)
{
cout << list->value << "-> " << list->next << endl;
printlist(list->next);
}
return 0;
}
and this is how it was supposed to work from the beginning. In this way by just switching the two rows inside the IF I can change from LIFO to FIFO :)

Not sure where the segmentation fault is

I'm getting problem with segmentation fault when trying to compile a C++ program, but not sure where the problem lies. I suspect that the problem lies with the .find() ..... could it be the iterator operator < and == which are the comparators for find() that is the issue? I hope that someone can point out to me where they think the problem lies.
The following is part of test01.cpp, where I run it to test the code and use print statements to find out where the problem is:
bool confirmEverythingMatches(const btree<long>& testContainer, const set<long>& stableContainer) {
cout << "Confirms the btree and the set "
"contain exactly the same values..." << endl;
for (long i = kMinInteger; i <= kMaxInteger; i++) {
cout << "Start of for-loop to find iterator for comparisons..." << endl;
if (stableContainer.find(i) != stableContainer.end()) {
cout << "can find i (" << i << ") in stableContainer!" << endl;
} else {
cout << "cannot find i (" << i << ") in stableContainer!" << endl;
}
cout << "In between finding i in stable and testContainers..." << endl;
if (testContainer.find(i) != testContainer.end()) {
cout << "can find i (" << i << ") in testContainer!" << endl;
} else {
cout << "cannot find i (" << i << ") in testContainer!" << endl;
}
cout << "Before assigning the find to boolean variables..." << endl;
bool foundInTree = (testContainer.find(i) != testContainer.end());
cout << "testContainer.find(i) != testContainer.end()" << endl;
bool foundInSet = (stableContainer.find(i) != stableContainer.end());
cout << "stableContainer.find(i) != stableContainer.end()" << endl;
if (foundInTree != foundInSet) {
cout << "- btree and set don't contain the same data!" << endl;
cout << "Mismatch at element: " << i << endl;
return false;
} else {cout << "foundInTree == foundInSet!!!" << i << endl;}
}
cout << "- btree checks out just fine." << endl;
return true;
}
} // namespace close
/**
* Codes for testing various bits and pieces. Most of the code is commented out
* you should uncomment it as appropriate.
**/
int main(void) {
// initialise random number generator with 'random' seed
initRandom();
cout << "after initRandom().." << endl;
// insert lots of random numbers and compare with a known correct container
btree<long> testContainer(99);
cout << "after specifying max node elements in testContainer.." << endl;
set<long> stableContainer;
cout << "after constructing stableContainer.." << endl;
insertRandomNumbers(testContainer, stableContainer, 1000000);
cout << "after inserting random numbers into testContainer and for success inserts, also into stableContainer.." << endl;
btree<long> btcpy = testContainer;
cout << "after copy assigning a copy of testContainer to btcopy.." << endl;
confirmEverythingMatches(btcpy, stableContainer);
cout << "after confirming everything internally matches between testContainer and stableContainer.." << endl;
return 0;
}
The output I get when running the program (No problem when compiling) is this:
Confirms the btree and the set contain exactly the same values...
Start of for-loop to find iterator for comparisons...
cannot find i (1000000) in stableContainer!
In between finding i in stable and testContainers...
ASAN:DEADLYSIGNAL
=================================================================
==7345==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000018 (pc 0x000108d132a8 bp 0x000000000000 sp 0x7fff56eee6f0 T0)
#0 0x108d132a7 in btree<long>::find(long const&) const (test01+0x1000022a7)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (test01+0x1000022a7) in btree<long>::find(long const&) const
==7345==ABORTING
Abort trap: 6
I also got this error when I tried to run it on another machine:
==29936==ERROR: AddressSanitizer failed to allocate 0x200000 (2097152) bytes of SizeClassAllocator32: 12
I found that when it goes into the find(), it will have the segmentation fault:
/**
* Identical in functionality to the non-const version of find,
* save the fact that what's pointed to by the returned iterator
* is deemed as const and immutable.
*
* #param elem the client element we are trying to match.
* #return an iterator to the matching element, or whatever the
* const end() returns if no such match was ever found.
*/
template<typename T> typename btree<T>::const_iterator
btree<T>::find(const T& elem) const {
std::cout << "CONST ITERATOR'S FIND" << std::endl;
Node *tmp_ = root_;
std::cout << "1" << std::endl;
while(true) {
std::cout << "2" << std::endl;
size_t i;
std::cout << "3" << std::endl;
// go through all elements from root to tail
for (i = 0; i < tmp_->__occupied_size_; ++i) {
std::cout << "4" << std::endl;
if (tmp_->__elem_[i] == elem) {
std::cout << "5" << std::endl;
// find the elem, return an iterator
return const_iterator(tmp_, i, this);
std::cout << "6" << std::endl;
} else if (tmp_->__elem_[i] > elem) {
std::cout << "7" << std::endl;
// elem is not in current Node, go to descendants
// for the elem.
if (tmp_->__descendants_ == nullptr) {
std::cout << "8" << std::endl;
return cend();
std::cout << "9" << std::endl;
} else {
std::cout << "10" << std::endl;
tmp_ = tmp_->__descendants_[i];
std::cout << "11" << std::endl;
break;
}
}
}
// handling boundaries cases
if (i == tmp_->__occupied_size_) {
std::cout << "12" << std::endl;
if (tmp_->__descendants_[i] == nullptr) {
std::cout << "13" << std::endl;
return cend();
std::cout << "14" << std::endl;
} else {
std::cout << "15" << std::endl;
tmp_ = tmp_->__descendants_[i];
}
}
}
}
The print statements for this find is:
CONST ITERATOR'S FIND
1
2
3
4
4
7
10
11
2
3
4
7
10
11
ASAN:DEADLYSIGNAL
Ok, so based on the implementation of this find function, I think the problem might be located in
if (tmp_->__descendants_ == nullptr) {
std::cout << "8" << std::endl;
return cend();
std::cout << "9" << std::endl;
} else {
std::cout << "10" << std::endl;
tmp_ = tmp_->__descendants_[i];
std::cout << "11" << std::endl;
break;
}
and then
// handling boundaries cases
if (i == tmp_->__occupied_size_) {
std::cout << "12" << std::endl;
if (tmp_->__descendants_[i] == nullptr) {
std::cout << "13" << std::endl;
return cend();
std::cout << "14" << std::endl;
} else {
std::cout << "15" << std::endl;
tmp_ = tmp_->__descendants_[i];
}
}
So, You are checking if tmp->__descendants_ is not null. If it is not, then you set tmp_ = tmp_->descendants_[i];
Note: you are just checking __descendants_ pointer to be null or not, you are not checking the __descendants_ [i] if it is null!
What if the tmp->__descendants_[i] is null (or gets out of the descendants array)?
If that value is null, then tmp_->occupied_size_ might give you segfault.
Note2: For some reason you are using same index "i" for iterating through __elem_ and __descendants_. I am not sure, how descendants are created, but it might be also a problem here.
This is why debuggers exist. Run your program in the debugger, let the program fail, and then the debugger will tell you where and why it's gone wrong.
It looks like you've got potentially a lot of code to trawl through, which no one here will really want to do as it's not a concise question.
Good luck!

C++ Is there a way to loop through a vector and return a message only once it's been searched through entirely

This is just for one of the exercises in my book, where it asks me to search through a vector for a specific name and return a score from another corresponding vector once the name has been found. If the name isn't found, it'll return the message "Name not found!"
int main()
{
vector<string>name;
vector<int>score;
string n = "0";
int s = 0;
while (cin >> n >> s && n != "NoName") {
for (int i = 0; i < name.size(); ++i)
if (n == name[i]) {
cout << "Error! Name is already in database!" << '\n';
break;
}
name.push_back(n);
score.push_back(s);
}
for (int i = 0; i < name.size(); ++i)
cout << "(" << name[i] << " " << score[i] << ")" << '\n';
cout << "Type in a name to find the score" << '\n';
string search = "0";
cin >> search;
for (int i = (name.size() - 1); i >= 0; i = i - 1) {
if (search == name[i])
cout << "Score is " << score[i] << '\n';
else
cout << "Name not found!" << '\n';
}
}
The above is my code. The only problem I'm having is that it'll loop through the vector and return "Name not found!" multiple times because it searches each individual position. I only want it to return the message once the whole vector has been searched. I've tried googling it, and I've found something like this:
#include <algorithm>
...
std::vector<std::string>::const_iterator it = std::find(vec.begin(), vec.end(), "some string");
if (it != vec.end())
{
std::cout << "Found '" << *it << "' in the vector." << std::endl;
}
which, unfortunately, I don't quite understand.
std::vector<std::string>::const_iterator it = std::find(vec.begin(), vec.end(), "some string");
This searches for the string "some string" in the range [vec.begin(), vec.end()[ and returns an iterator to the element in the range if it is found. If it is not found, the end of the range (vec.end()) is returned.
So if (it != vec.end()) is saying if (the string was found).
Regarding your original code and the unwanted prints, there are several ways of fixing that. One way would be:
int i;
for (i = (name.size() - 1); i >= 0; i = i - 1) {
if (search == name[i]) break; // exit the loop as soon as the element is found
}
if (i >= 0) {
cout << "Score is " << score[i] << '\n';
} else {
cout << "Name not found!" << '\n';
}
std::vector<std::string>::const_iterator it = std::find(name.begin(), name.end(), name_to_search);
Please refer to function template std::find. It searches range [name.begin(), name.end()) and compare every element with "name_to_search". It returns an iterator to the first element that is equal to "name_to_search".
If no elements match, the function returns name.end().
P.S. You can also go through the range like this:
int i = 0;
for (; i < name.size(); i++) {
if (search == name[i]){
cout << "Score is " << score[i] << '\n';
break;
}
}
if(i == name.size()){
cout << "Name not found!" << '\n';
}

Using std::next() in Netbeans

I've been writing an XML to JSON converter in C++ in Visual Studio 2012 and I've used std::next() a bunch in my program. Our professor wants us to be using Netbeans to submit out programs, but I went to bring my code over into Netbeans and now everywhere I've been using std::next is now underlined and my code wont compile. Here is an example of where I'm encountering an error. Does anyone know a workaround? Thanks in advance.
void element::printAttributesToFile(ofstream& outFile)
{
map<string, string>::iterator it; //for iterating through the map of attributes and values
if(attributes.size()>1) //if there are more than one attribute, make an array
{
outFile << "[" << endl;
}
for(it=attributes.begin(); it != attributes.end(); ++it) // iterates through the map
{
outFile << "{" << endl; //brackets surrounding ever attribute
outFile<<"\""<<it->first<<"\": "<< "\""<< it->second<<","<<endl;
if(!content.empty()){ // if there is content, print it
outFile<<"\"content\": "<< "\""<< content << "\"" <<endl;
}
outFile << "}" << endl;
if(next(it) != attributes.end()) //is this the last attribute
{
outFile << "," << endl; //if not, print the comma
}else if(next(it)==attributes.end()){ //if it is
outFile << endl; //print a new line
}
}
if(attributes.size()>1) //closing the array
{
outFile << "]" << endl;
}
//outFile<<"]"<<endl;
}

c++ hashmap ; update adding new keys and not updating

I have this code where I take a hashmap, take a key and update the value. However, the loop is never ending as the code is adding new keys to the hashmap rather than updation. Please let me know if you can help :-
typedef indri::utility::HashTable< Gram*, double, Gram::hash,Gram::string_comparator > HGramScore;
HGramScore _gramScores;
HGramScore::iterator iter_score;
cout << "Sizeee " << _gramScores.size() << endl;
int count = 0;
for (iter_score = _gramScores.begin(); iter_score != _gramScores.end() ; iter_score++)
{
count++;
cout << "Sizeee " << _gramScores.size() << endl;
_gramScores.insert(*iter_score->first , *iter_score->second / total_score_count);
cout << count << endl;
}