Prevent splitting inputs at spaces and automatically using later words for later inputs - input

I have a Function that outputs a string that it's been given to the console via cout, initializes a new string, writes user input into that string and returns it.
I summarized my problem in this piece of code:
#include <iostream>
std::string GetUserInput(std::string question) {
std::cout << question;
std::string inputedData;
std::cin >> inputedData;
return inputedData;
}
int main()
{
std::string userInput1 = GetUserInput("Your first input: ");
std::string userInput2 = GetUserInput("Your second input: ");
std::string userInput3 = GetUserInput("Your third input: ");
std::cout << userInput1 << std::endl;
std::cout << userInput2 << std::endl;
std::cout << userInput3 << std::endl;
}
This works, als long as the user doesn't input any spaces. For example if the input is:
Joe
Walther
Alex
Then the Output will be as expected:
Your first input: Joe
Your second input: Walther
Your third input: Alex
Joe
Walther
Alex
But if a user tries to input something that has a space in it, the input will be split at every space character and the words that come after the first will automatically be used as inputs that are requested at later points in time. For that reason, the output looks something like this:
Your first input: Joe Smith
Your second input: Your third input: Walther Jones
Joe
Smith
Walther
What do I need to do in order to write a complete input string with spaces into a variable and then have other inputs right after that are completely independent of the first input and each other?

Related

Point Set Shape Detection: save planar shapes to file

Although I don't know how to write C++ I am trying to use CGAL for trying to derive building shapes from LiDAR point clouds using Point Set Shape Detection. Using the examples I can read points and normals from a file, whereupon CGAL detects shapes. The program is set to detect only planar shapes.
I would like to save the planar shapes to a file, so that I can use them in other software. But I was unable to find examples of how that can be achieved. The test program I use is based on the efficient_RANSAC_parameters.cpp code. It has a part when it iterates through all detected shapes. Could it be possible to add something there that will write the planar shapes to a file? I see the OFF format is a popular and simple way (in CGAL) to save polygons to a file, so that could be a good candidate file format.
A colleague who does know how to write C++ has helped me with this problem. He came up with the following:
while (it != shapes.end()) {
if (Plane* plane = dynamic_cast<Plane*>(it->get()))
{
std::cout << "PLANE_" << count++ << "[" << std::endl;
const std::vector<size_t> indices = it->get()->indices_of_assigned_points();
std::vector<size_t>::const_iterator iti = indices.begin();
while (iti != indices.end()) {
// Retrieves point
Point_with_normal pw = *(points.begin() + (*iti));
Kernel::Point_3 p = pw.first;
std::cout << "POINT[" << p.x() << "," << p.y() << "," << p.z() << "]" << std::endl;
// Proceeds with next point.
iti++;
}
std::cout << "]" << std::endl;
}
// Proceeds with next detected shape.
it++;
}
This block can replace loop in the efficient_RANSAC_parameters.cpp example. The output looks like this:
PLANE_0[
POINT[34.96,584.49,0.47]
POINT[34.97,585.24,0.54]
POINT[34.88,584.51,0.49]
POINT[34.98,584.75,0.49]
]
That gives me something to work with. In my case, I use sed to transform this output to SQL insert queries that allow me to transfer the data to a relational database for further processing.
In the example in the user manual you can see that once you have a plane shape object
if(Plane* plane = dynamic_cast<Plane*>(it->get())){..} you can obtain from the plane shape object a CGAL::Plane_3, from which you can obtain a point and a normal, or the coefficients of the plane.

Letters stored as integers

#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << "Please enter an integer between 1 and 5" << endl;
int x; //Selection of menu prompt
cin >> x;
while (x < 1 || x > 5) //Tossing out garbage input
{
cout << "Invalid selection, please make another." << endl;
cin >> x;
}
return 0;
}
When this is run, entering "a" for example, enters the while loop, but does not wait for user input at "cin >> x;" and instead loops infinitely through. Can someone explain to me why this happens and how I might fix the issue? I can only imagine it is something to do with the keyboard buffer.
In this code, it's possible for cin to enter an error state. If the user does not enter an integer, it will fail.
That is, if the user enters a, then cin >> x does not set x, and future calls to cin >> x do not block. You see an endless loop.
You can check for this failure status and clear it. before continuing using code similar to:
if (cin.fail())
{
cin.clear();
cin.ignore();
cerr << "Invalid selection, please make another." << endl;
}
You really should use cin.clear() and cin.ignore() after accepting the input.
cin.clear() clears the error flag on cin, and then cin.ignore(5000, '\n') skips to the next newline. It will skip up to 5000 characters, so the code is assuming the user will not put in a very long.

Filestreams reading and writing to text file, then convert to binary in c++

What I am trying to do is fairly elementary however I am having trouble with my project. My project is too large to include everything, so I will just include the two functions that I am writing along with what the txt file looks like. This is in c++.
bookmark.cfg
No Title
0 0 0 0 0 0
No Title
1 1 1 1 1 1
No Title
2 2 2 2 2 2
No Title
3 3 3 3 3 3
No Title
4 4 4 4 4 4
No Title
5 5 5 5 5 5
These are my two functions for writing and reading to the text file and my class's private structure
struct BookMark {
std::string strFilename;
unsigned id;
unsigned bookID;
unsigned chapterNumber;
unsigned pageNumber;
unsigned lineNumber;
unsigned columnNumber;
}; // BookMark
// ----------------------------------------------------------------------------
// readConfigFile()
bool BookManager::readConfigFile() {
using namespace std;
// Just To Be Safe Incase This Function Is Called In Multiple Places
_mBookMarks.clear();
ifstream inFile( _strConfigFilename );
if ( inFile.fail() ) {
throw ExceptionHandler( __FUNCTION__ + std::string( " failed, could not open " ) + _strConfigFilename + std::string( " \nfor reading in book mark information \nInvalid file or file does not exist" ) );
}
// Read In The Book Mark Contents
std::vector<BookMark> vBookMarks;
BookMark bookMark;
string tempString = "";
if ( inFile.is_open() ) {
while ( !inFile.eof() ) {
BookMark bookMark;
getline( inFile, bookMark.strFilename );
inFile >> bookMark.id;
inFile >> bookMark.bookID;
inFile >> bookMark.chapterNumber;
inFile >> bookMark.pageNumber;
inFile >> bookMark.lineNumber;
inFile >> bookMark.columnNumber;
getline( iniFile, tempString );
//_mBookMarks.insert( make_pair( bookMark.id, bookMark ) );
vBookMarks.push_back( bookMark );
}
}
inFile.close();
return true;
} // readConfigFile
// ----------------------------------------------------------------------------
// writeConfigFile()
bool BookManager::writeConfigFile() {
using namespace std;
ofstream outFile;
outFile.open( _strConfigFilename, fstream::out );
if ( outFile.fail() ) {
throw ExceptionHandler( __FUNCTION__ + std::string( " failed, could not open " ) + _strConfigFilename + std::string( " \nfor writing book mark contents to file." ) );
}
// Write Out Book Mark Contents
if ( outFile.is_open() ) {
unsigned i = 0;
for ( i = 0; i < _mBookMarks.size(); i++ ) {
outFile << _mBookMarks.at( i ).strFilename << endl;
outFile << _mBookMarks.at( i ).id << " ";
outFile << _mBookMarks.at( i ).bookID << " ";
outFile << _mBookMarks.at( i ).chapterNumber << " ";
outFile << _mBookMarks.at( i ).pageNumber << " ";
outFile << _mBookMarks.at( i ).lineNumber << " ";
outFile << _mBookMarks.at( i ).columnNumber << endl << endl;
}
}
outFile.close();
return true;
} // writeConfigFile
The problem I am having is, when I call the write function all the text is being displayed properly in my text file. The first line should be a string that contains the book's title or filename. The second line should be all unsigned ints to specify parameters to know the position of the bookmark's location. As of now I just populated my classes structure with arbitrary data using a for loop and incrementing each bookmarks parameters just to test these functions. Somewhere else in my code I call my write method first to create this text file and write the contents. This seems to be working fine. Then I call my read method to read in the file and populate a temporary vector of my structure to see if the contents being read from the file are valid. Once I get this to work properly I'll then just populate my class's member variable structure instead.
Here I am reading in the first line using getline function then I am using the stream operators to get the rest of the contents. While I am debugging my code going through the read method and checking my temp vector the first element has the correct value with No Title and each of the parameters are 0. When I check the next element there is no string in the next BookMark structure object and all values are 0. Also there should only be 5 elements in my temp vector and it should break out of the loop, but it continues and never breaks out of the loop. Why is the code behaving like this? What is it that I am doing wrong? How can I change this to get the behavior I am looking for?
If you need to see this class in full let me know, but I think the rest of the class is not important as to what I am trying to do, only these two functions should be enough to describe my situation. Once I get this to work properly then I'll just change the read and write methods to work in binary as opposed to text.
I believe I have solved my own problem. In my read method, I had to add a second getline( this fileStream, tempString ); And now my code appears to be working properly. My vector has the correct values and it only has 5 elements and now breaks out of the loop.

How to specify the output format for Null node in yaml-cpp?

I use current(2013/12/12) latest revision of yaml-cpp.
I noticed that both YAML::Load("")
and YAML::Load("---\n...") results in a Null node,
i.e. YAML::Load("").Type() == YAML::NodeType::Null
yet when sent to std::ostream the former outputs an empty string
but the latter outputs tilde (~).
I want both nodes to output an empty string.
How can I achieve it?
I want to do so because I noticed tilde is interpreted as a string when I use YAML::Load.
Here is the code to show this difference.
#include <yaml-cpp/yaml.h>
#include <iostream>
#include <cassert>
int main() {
YAML::Node node1 = YAML::Load("");
YAML::Node node2 = YAML::Load("---\n...");
assert (node1.Type() == YAML::NodeType::Null);
assert (node2.Type() == YAML::NodeType::Null);
std::cout << node1 << std::endl;
std::cout << node2 << std::endl;
}
/* OUTPUT:
~
*/
According to the Github Issue, this behavior was fixed in 2016.

writing output to a file in Graphchi

I wrote a shortest path code in Graphchi and I wanted to print the output of that in a file. I was trying to use the template shown in the examples but I get error if I use the sameway of writing to a file as in other examples.
I have got stuck here. As the output I just want to print (vertex id,its minimum distance from source).
How can i do that.
Here is example how you can output values of all vertices to the console. It is easy to modify it to write the output to a file. Note that if you can handle binary files, GraphChi already has the vertex values in a file: .B.vout, where is sizeof(VertexDataType).
1) You need to define a callback-function, which will take vertex id and value as parameter
class OutputVertexCallback : public VCallback<VertexDataType> {
public:
virtual void callback(vid_t vertex_id, VertexDataType &value) {
std::cout << vertex_id << "=" << value << std::endl;
}
};
2) Then you need to call foreach_vertices() as follows to get the output:
OutputVertexCallback callback;
foreach_vertices<VertexDataType>(filename, 0, engine.num_vertices(), callback);