how to get my string commands by getline() and stringstream - c++

I want to know whether I'm using the right form to get my command in a line and then by some ifs get the info each command needs. This is a part of my code; actually, the first part of my main function:
string line;
stringstream ss;
while (!cin.eof())
{
getline(cin, line);
//i dont know if next line should be used
ss << line;
if (line.size() == 0)
continue;
ss >> command;
if (command == "put")
{
string your_file_ad, destin_ad;
ss >> your_file_ad >> destin_ad;
//baraye history ezafe shod
give_file(your_file_ad, p_online)->index_plus(command);

I tried to run your code with two additional couts in your if, to see what happens when for example user enters put a b.
So, this is my code:
string line;
stringstream ss;
while (true)
{
getline(cin, line);
//i dont know if next line should be used
ss << line;
if (line.size() == 0)
continue;
string command;
ss >> command;
if (command == "put")
{
string your_file_ad, destin_ad;
ss >> your_file_ad >> destin_ad;
cout << "input #1 is " << your_file_ad << endl;
cout << "input #2 is " << destin_ad << endl;
}
}
When I run this code, then if I write put a b in the console, I'll see this result, which is correct:
input #1 is a
input #2 is b
But it seems that this only works for the first command. after that commands couldn't process correctly.
So, I read the code again, and found out that the problem is, you are initializing your stringstream outside of the while.
I'm not sure why exactly it doesn't work (maybe already reached EOF and can't continue reading anymore?), but if you move stringstream ss; inside the while, it'll work correctly:
string line;
while (true)
{
stringstream ss;
getline(cin, line);
//i dont know if next line should be used
ss << line;
if (line.size() == 0)
continue;
string command;
ss >> command;
if (command == "put")
{
string your_file_ad, destin_ad;
ss >> your_file_ad >> destin_ad;
cout << "input #1 is " << your_file_ad << endl;
cout << "input #2 is " << destin_ad << endl;
}
}
Update: read #LightnessRacesinOrbit comment below about the issue with the first code.

Related

C++ while loop Issues

I am trying to read lines of a file (cityName, hiTemp, loTemp) into a struct array. I was able to use >> to read the first several lines until I hit a city with a space in it's name.
I then tried using getline() to read the lines, but then my while loop stopped working.
I have no clue why this would happen.
int LoadData()
{
int count = 0;
string path;
cout << "Specify the input file path: ";
ifstream inFile;
cin >> path;
inFile.open(path.c_str());
if (!inFile.is_open())
{
cout << "Error - could not open file: " << path;
return (-1);
}
else
{
while (!inFile.eof())
{
cities[count].city = "";
getline(inFile, cities[count].city);
if (cities[count].city.length() == 0)
{
break;
}
char comma;
inFile >> (cities[count].high) >> comma >> cities[count].low;
cout << cities[count].city << " " << cities[count].high << " " << cities[count].low << endl;
count++;
}
inFile.close();
inFile.clear(std::ios_base::goodbit);
return count;
}
}
while (!inFile.eof())
For getting every line in the file, you should use:
while(getline(inFile, cities[count].city)) {
// ...
This works and is recommended over using the .eof() method.
You can also use this in your if-statement:
if (!getline(inFile, str))
break;
As an aside, you can read this site:
Why is “while ( !feof (file) )” always wrong? - StackOverflow post
It gives insight into why using the .eof() is not the preferred method to use in a while loop to check whether the end-of-file has been reached.
Use getline as loop condition. You can also replace the second read with a getline too and use a stringstream to parse it.
#include <sstream>
// ...
while(getline(inFile, cities[count].city)) {
if (cities[count].city.empty()) break;
// read next line with high and low values
string str;
if (!getline(inFile, str)) break; // error in file format
stringstream ss(str);
char comma;
ss >> cities[count].high >> comma >> cities[count].low; // parse it
}

why is my compiler complaining when i try to clear the cin buffer

i am writing a program where i am trying to implement the following code:
int main(){
string inputcmd;
while (getline(cin, inputcmd)){
cout << "TYPE A COMMAND" << endl;
cin >> inputcmd;
cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
if (inputcmd == "make"){
cout << "MAKING NEW PROJECT" << endl;
get_project(cin);
}
else if (inputcmd == "retrieve"){
cout << "RETRIEVING YOUR PROJECT" << endl;
}
}
return 0;
}
i am trying to use the cin.ignore property to clear the buffer of the newline character currently residing in the buffer at that given time, however when i try and compile it is giving me a bunch of gibberish compiler error? why is this how can i fix this?
Assuming you included
#include <string>
#include <iostream>
using namespace std;
Then I'm not getting any error.
You need to press an extra newline because you read the input twice. First with getline and a second time with cin >> ....
If you can have arguments to the commands, I recommend you remove the cin >> ... part, together with the cin.ignore() call, and use only getline and std::istringstream:
std::cout << "Enter command: ";
while (std::getline(std::cin, line))
{
std::istringstream iss(line);
// Get the command
std::string command;
iss >> command;
if (command == "make")
{
...
}
...
std::cout << "Enter command: ";
}
This way, you can easily get the space-separated arguments to the command as well.
And yes, you have code to print the prompt twice, but that is a smaller and negligible problem in my opinion.
Or if you want to be even more general, use e.g. a std::vector to store the command and arguments, and do something like
std::cout << "Enter command: ";
while (std::getline(cin, line))
{
std::istringstream iss(line);
std::vector<std::string> args;
// Get the command and all arguments, and put them into the `args` vector
std::copy(std::istream_iterator<std::string>(iss),
std::istream_iterator<std::string>(),
std::back_inserter(args));
if (args[0] == "make")
{
...
}
...
std::cout << "Enter command: ";
}
See e.g. these references:
std::copy
std::istream_iterator
std::back_inserter
You're using a strange combination of getline and cin... If you're using getline, you don't have to call cin.ignore at all. Don't mix both like you did or you will get confusing results.
This example propably runs like you want:
#include <string>
#include <iostream>
using namespace std;
int main(){
string inputcmd;
bool running = true;
while (running){
cout << "TYPE A COMMAND" << endl;
getline(cin, inputcmd);
if (inputcmd.substr(0, inputcmd.find(" ")) == "make"){
if(inputcmd.find(" ")!=string::npos){
inputcmd = inputcmd.substr(inputcmd.find(" ")+1);
cout << "MAKING NEW PROJECT: " << inputcmd << endl;
//get_project(cin);
}else{
cout << "make: not enough arguments" << endl;
}
}else if (inputcmd == "retrieve"){
cout << "RETRIEVING YOUR PROJECT" << endl;
}else if(inputcmd == ""){
running = false;
}
}
return 0;
}

The program doesn't proceed inside the input file to read it

Those are the parts of the code I have:
ifstream inFile;
inFile.open("Product1.wrl");
...
if (!inFile.is_open()){
cout << "Could not open file to read" << endl;
return 0;
}
else
while(!inFile.eof()){
getline(inFile, line);
cout << line << endl; //this statement only to chech the info stored in "line" string
if (line.find("PointSet"))
inFile >> Point1;
}
The output shows me the same string over and over again. So this means that the cursor inside the file does not proceed and getline reads the same line.
What might be the problem of this odd behavior?
If this is relevant:
The file does open as a .txt file and contains the exact information I need.
Okay I figured the problem:
Even after first eteration the return value of line.find("PointSet")is: 429467295... while my line string contains only one letter "S". Why?
Change
while(!inFile.eof()){
getline(inFile, line);
to
while( getline(inFile, line) ) {
I don't know why people get bitten by eof() quite so often, but they do.
Mixing getline with >> is problematic, because the >> will leave a '\n' in the stream, so the next getline will come back empty. Change that to use getline as well.
if (line.find("PointSet")) isn't what you want either. find returns the position in the string, or std::string::npos if it wasn't found.
Also, you can change
ifstream inFile;
inFile.open("Product1.wrl");
to
ifstream inFile ("Product1.wrl");
Here's a version showing the reads:
class Point
{
public:
int i, j;
};
template <typename CharT>
std::basic_istream<CharT>& operator>>
(std::basic_istream<CharT>& is, Point& p)
{
is >> p.i >> p.j;
return is;
}
int main()
{
Point point1;
std::string line;
while(std::getline(std::cin, line))
{
std::cout << line << '\n'; //this statement only to chech the info stored in "line" string
if (line.find("PointSet") != std::string::npos)
{
std::string pointString;
if (std::getline(std::cin, pointString))
{
std::istringstream iss(pointString);
iss >> point1;
std::cout << "Got point " << point1.i << ", " << point1.j << '\n';
}
else
{
std::cout << "Uhoh, forget to provide a line with a PointSet!\n";
}
}
}
}

using sstream header file in C++

so I was trying to utilise the istringstream to parse through a text file. The idea is to break down each line by space and based on the substring do stuff. The code works fine except for two things, it double counts last substring for each line and it seg faults when its done reading through the file. I have not used sstream before so any insight would be helpful.
file.getline(str,80);
while(!file.eof())
{
cout<<str<<endl;
istringstream iss(str);
while (iss)
{
iss >> sstr;
cout << "Substring: " <<sstr << endl;
}
file.getline(str,80);
}
The while loops should go like this:
std::string line;
while (std::getline(file, line))
{
std::istringstream iss(line);
std::string token;
while (iss >> token)
{
cout << "Substring: " << token << endl;
}
}
The getline and input operations return the stream object, which itself has a specialized conversion to bool that indicates whether the operation succeeded, and it will fail precisely when you've reached the end of the respective stream.
while !eof is almost always wrong.
Switch to a different C++ book, and tell us which one you're using now so that we may mock and warn accordingly.
while (file.getline(str,80)) {
cout<<str<<endl;
istringstream iss(str);
while (iss >> sstr) {
cout << "Substring: " <<sstr << endl;
}
}

Trouble getting working directory

This is how I am trying to get the current working directory:
char* ch;
if( (ch = _getcwd( NULL, 0 )) == NULL )
{
cout << "Could not get working directory!" << endl;
}
// skonvertujme char* na string, s tym sa nizsie bude lahsie pracovat
stringstream ss;
string workingDirectory;
ss << ch;
ss >> workingDirectory;
cout << workingDirectory << endl;
cin.get();
cin.get();
Which prints out:
C:\Users\Richard\Documents\Visual
Instead of the actual working directory:
C:\Users\Richard\Documents\Visual Studio 2010\Projects\Client\Debug
It seems like ti cuts everything after a space.
How can I get the working directory correctly even if there are spaces in the path?
The >> operator stops at the first space. Instead of the stringstream manipulation try
string workingDirectory(ch);
Just replace this:
stringstream ss;
string workingDirectory;
ss << ch;
ss >> workingDirectory;
with this:
string workingDirectory(ch);
Use getline(ss, workingDirectory)
The reason that happens is that the << operator in stringstream stops reading when it encounters whitespace.
If you really want to use your solution - which is overkill - use the noskipws io-manipulator like so:
ss >> noskipws >> workingDirectory;