boost split - cout and vector - explain behaviour of this - c++

I'm quite new to c++ and boost, I don't understand what's actually happening here.
So I'm using cin to get some input from the user. Then I'm splitting that string of spaces into a vector and trying to print the first index of the vector.
My code:
std::string cmd;
std::vector<std::string> args;
while (std::cin >> cmd) {
boost::split(args, cmd, boost::is_any_of(" "), boost::token_compress_on);
Console::print(args[0]);
break;
//reset the vector
//std::cin.clear();
//args.clear();
}
My console print function just uses normal cout, here is the code for it:
int Console::print(std::string message, int color)
{
HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(consoleHandle, brightGreen);
std::cout << "myconsole :: ";
SetConsoleTextAttribute(consoleHandle, color);
std::cout << message << "\n";
return 0;
}
What's happening:
For the sake of this question the input is "start go".
I only want to print the first element. Without the break my program first prints start and then it prints out go. I have determined that the program does 2 loops and each time prints the first element, I know this because if I have the break then there is only start printed and the program ends. Firstly, why is this happening? Why does the first index of the vector get removed and then looped making the first index "go"?
Does this all have something to do with the stringstream/buffer or something. I don't know much about these. That was my guess so I tried to reset the buffer with cin.clear() and empty the vector with args.clear() but that still produced the same results.
Secondly, if I use the code below and try to access the 2nd element "go" my program just crashes. From what I have tried from the above I can assume that I am correctly splitting the string.
Is there some sort of asynchronous behavior going on and the split function just isn't finished yet? Or?
Any help would be awesome. Thanks.

Your problem is that std::cin >> cmd only reads "start", feeds that into the loop (which creates a single element vector and prints the only element), then loops round and does the same with "go".
You need while(std::getline(std::cin, cmd)).
You also need to learn to use your debugger which would have shown you what the problem was.

Related

Keep asking for input and reopen stdin

I have a task to create a program that does some calculation on a vector of numbers. The vector must contain at least 1 number in it and if it doesn't I have to throw an exception and try again. There is a video example how the code should work here: https://asciinema.org/a/283343
I'm guessing that EOF is being signaled using CTRL+D and that's what causes the exception to be thrown.
If they were using Enter (new line), it would leave a blank line behind.
But in my case, after I press CTRL+D, my program just runs in an infinite loop because the stdin stays in a failed state despite me using cin.clear().
Is there another shortcut similar to CTRL+D that they might be using for this, or is there a way to reopen the stream, or restart the whole application.
The program runs fine on Windows when I use CTRL+Z, but on Linux I just can't get it to work the same.
Example code below:
#include<iostream>
#include<vector>
void enter_elements(std::vector<double>& input_list){
double x;
std::cout << "Enter numbers: " << std::endl;
while(std::cin >> x){
input_list.push_back(x);
}
if(input_list.empty()){
throw std::string("You must enter at least 1 number!");
}
}
int main(){
std::vector<double> input_list;
try {
enter_elements(input_list);
} catch (const std::string& e) {
std::cout << "Error: " << e << std::endl;
std::cin.clear();
enter_elements(input_list);
}
return 0;
}
Can anyone help me with this problem or suggest where could I maybe read more about it?
No.
Once the stream is closed, the stream is closed. That's it.
What I'd do is accept a set of numbers on one line. Your input iteration would end at the end of the line. Then you validate those numbers, and ask for another line if necessary.
You can do that by looping over std::getline instead of using formatted extraction. Then you'd need to parse the line you get.
That's not what the video shows, but I don't know how they achieved that. Maybe you should ask them!
Are you asking how to stop the program?
If so, on linux, you should try CTRL+C instead of CTRL+D or CTRL+Z while your program is running
This is the sort of reason why I hate using cin >> anInt. I much prefer to getLine and parse it myself. Then you can make it do anything and decide how you're going to determine end of list, etc.
Yes, it's more code. But you don't run into these weird problems like this.

Filling a cstring using <cstring> with text from a textfile using File I/O C++

I began learning strings yesterday and wanted to manipulate it around by filling it with a text from a text file. However, upon filling it the cstring array only prints out the last word of the text file. I am a complete beginner, so I hope you can keep this beginner friendly. The lines I want to print from the file are:
"Hello World from UAE" - First line
"I like to program" - Second line
Now I did look around and eventually found a way and that is to use std::skipary or something like that but that did not print it the way I had envisioned, it prints letter by letter and skips each line in doing so.
here is my code:
#include <fstream>
#include <iostream>
#include <cstring>
#include <cctype>
using namespace std;
int main() {
ifstream myfile;
myfile.open("output.txt");
int vowels = 0, spaces = 0, upper = 0, lower = 0;
//check for error
if (myfile.fail()) {
cout << "Error opening file: ";
exit(1);
}
char statement[100];
while (!myfile.eof()) {
myfile >> statement;
}
for (int i = 0; i < 30; ++i) {
cout << statement << " ";
}
I'm not exactly sure what you try to do with output.txt's contents, but a clean way to read through a file's contents using C++ Strings goes like this:
if (std::ifstream in("output.txt"); in.good()) {
for (std::string line; std::getline(in, line); ) {
// do something with line
std::cout << line << '\n';
}
}
You wouldn't want to use char[] for that, in fact raw char arrays are hardly ever useful in modern C++.
Also - As you can see, it's much more concise to check if the stream is good than checking for std::ifstream::fail() and std::ifstream::eof(). Be optimistic! :)
Whenever you encounter output issues - either wrong or no output, the best practise is to add print (cout) statements wherever data change is occurring.
So I first modified your code as follows:
while (!myfile.eof()) {
myfile >> statement;
std::cout<<statement;
}
This way, the output I got was - all lines are printed but the last line gets printed twice.
So,
We understood that data is being read correctly and stored in statement.
This raises 2 questions. One is your question, other is why last line is printed twice.
To answer your question exactly, in every loop iteration, you're reading the text completely into statement. You're overwriting existing value. So whatever value you read last is only stored.
Once you fix that, you might come across the second question. It's very common and I myself came across that issue long back. So I'm gonna answer that as well.
Let's say your file has 3 lines:
line1
line2
line3
Initially your file control (pointer) is at the beginning, exactly where line 1 starts. After iterations when it comes to line3, we know it's last line as we input the data. But the loop control doesn't know that. For all it knows, there could be a million more lines. Only after it enters the loop condition THE NEXT TIME will it come to know that the file has ended. So the final value will be printed twice.

Formatting Output c++

Wanting to do some fancy formatting. I have several lines that I want to interact with each other. Get the first two lines. Print out the character in the second line times the integer in the first line. Seperate them all with a asterisk character. No asterisk after the final character is printed. Move onto the next integer and character. Print them on a separate line. Do this for the whole list. The problem I am having is printing them on separate lines. Example:
5
!
2
?
3
#
Desired output:
!*!*!*!*!
?*?
#*#*#
My output:
!*!*!*!*!*?*?*#*#*#*
Below is my code. Another thing to mention is that I am reading the data about the characters and numbers from a separate text file. So I am using the getline function.
Here is a chunk of the code:
ifstream File
File.open("NumbersAndCharacters.txt")
string Number;
string Character;
while(!File.eof(){
getline(File, Number);
getline(File, Character);
//a few lines of stringstream action
for (int i=0; i<=Number; i++){
cout<<Character<<"*";}//end for. I think this is where
//the problem is.
}//end while
File.close();
return 0;
Where is the error? Is it the loop? Or do I not understand getline?
It should be printing an "endl" or "\n" after each multiplication of the character is done.
Thanks to everyone for the responses!
You have not shown your code yet, but what seems to be the issue here is that you simply forgot to add a new line every time you print your characters. For example, you probably have done:
std::cout << "!";
Well, in this context you forgot to add the new line ('\n'), so you have two options here: first insert the new line yourself:
std::cout << "! \n";
Or std::endl;
std::cout << "!" << std::endl;
For comparison of the two, see here and here. Without further description, or more importantly your code that doesn't seem to work properly, we can't make suggestions or solve your problem.

No methods of read a file seem to work, all return nothing - C++

EDIT: Problem solved! Turns out Windows 7 wont let me read/ write to files without explicitly running as administrator. So if i run as admin it works fine, if i dont i get the weird results i explain below.
I've been trying to get a part of a larger program of mine to read a file.
Despite trying multiple methods(istream::getline, std::getline, using the >> operator etc) All of them return with either /0, blank or a random number/what ever i initialised the var with.
My first thought was that the file didn't exist or couldn't be opened, however the state flags .good, .bad and .eof all indicate no problems and the file im trying to read is certainly in the same directory as the debug .exe and contains data.
I'd most like to use istream::getline to read lines into a char array, however reading lines into a string array is possible too.
My current code looks like this:
void startup::load_settings(char filename[]) //master function for opening a file.
{
int i = 0; //count variable
int num = 0; //var containing all the lines we read.
char line[5];
ifstream settings_file (settings.inf);
if (settings_file.is_open());
{
while (settings_file.good())
{
settings_file.getline(line, 5);
cout << line;
}
}
return;
}
As said above, it compiles but just puts /0 into every element of the char array much like all the other methods i've tried.
Thanks for any help.
Firstly your code is not complete, what is settings.inf ?
Secondly most probably your reading everything fine, but the way you are printing is cumbersome
cout << line; where char line[5]; be sure that the last element of the array is \0.
You can do something like this.
line[4] = '\0' or you can manually print the values of each element in array in a loop.
Also you can try printing the character codes in hex for example. Because the values (character codes) in array might be not from the visible character range of ASCII symbols. You can do it like this for example :
cout << hex << (int)line[i]

How can I separate user inputted string and store it into an array

I was wondering if you could help me and figure this out without using something like strtok. This assignment is meant for me to build something that will accept input and direct the user to the right area. I want to get something like....
Help Copy
and it stores it as
array[1] = Help
array[2] = Copy.
I tried to do something like cin>>arr[1]; and cin>>arr[2] but at the same time what if the user enters copy then I am not sure how to do it cause if I put just one cin then what if the user puts help copy.
Basically I am not sure how to accept any size input and store anything they put in as elements in an array.
I would try something like cin.get or getline but they don't seem to really help me and my cin idea was not helpful at all.
This is what I have so far.
int main()
{
string user;
cout<<"Hello there, what is your desired username?"<<endl;
cin >> user;
system("cls");
cout<<"Hello, " << user << "! How are you doing?"<<endl<<endl;
cout<< user << ": ";
return 0;
}
You can do it like this:
Read the entire line using getline
Make an input string stream from that line
Read the content of that string stream into a vector<string>. It will grow automatically to accommodate as many inputs as the user enters
Examine the size of the resultant vector to see how many entries the end-user made
Here is how you can do it in code:
// Prepare the buffer for the line the user enters
string buf;
// This buffer will grow automatically to accommodate the entire line
getline(cin, buf);
// Make a string-based stream from the line entered by the user
istringstream iss(buf);
// Prepare a vector of strings to split the input
vector<string> vs;
// We could use a loop, but using an iterator is more idiomatic to C++
istream_iterator<string> iit(iss);
// back_inserter will add the items one by one to the vector vs
copy(iit, istream_iterator<string>(), back_inserter(vs));
Here is a demo on ideone.
std::vector<std::string> myInputs;
std::cout << "Enter parameters: ";
std::copy(std::istream_iterator<std::string>(std::cin), std::isteram_iterator<std::string>(), std::back_inserter(myInputs));
// do something with the values in myInputs
If the user presses Enter in between each input, this will go until they cease the input (Crtl-D on Windows). If you want them to put all the parameters on a single line, you can read the input into a single string and then split the string up by spaces (or whatever delimiter you wish to use).