C++ Loading user input into vector - c++

I am trying to create a command line app, where the user can type in commands and data, but I don't really get how istream_iterator is working, how can I get a whole input (until enter) into a vector? Right now it creates a new while loop on every word, that is not what is want.
int main(int argc, char* argv[])
{
string buffer;
//vector<string> vbuff;
CliHandler clihandler(argc, argv);
int state = clihandler.State();
while (state != CliHandler::STATE_EXIT) {
cout << ">>";
//Beolvasás
cin >> buffer;
stringstream sstream(buffer);
istream_iterator<string> begin(sstream);
istream_iterator<string> end;
vector<string> vbuff(begin,end);
copy(vbuff.begin(), vbuff.end(), std::ostream_iterator<string>(std::cout, "\n"));//test
//vbuff = vector<string>((istream_iterator<string>(cin)), istream_iterator<string>());
//copy(vbuff.begin(), vbuff.end(), std::ostream_iterator<string>(std::cout, "\n"));
switch(clihandler.State(vbuff[0])) {
// [command] [data1] [data2] ...
}
}
return 0;
}

Why don't you just use the argc and argv parameters? Something like this..(haven't tested)
int main(int argc, char* argv[])
{
vector<string> vbuff(argc);
for (int i = 0; i < argc; ++i)
{
vbuff[i] = argv[i];
}
// From here, you can use vbuff for your own purposes.
}

I m not very sure what u want(my poor english..), maybe you want to get input of the whole line until enter
I think you can use cin.getline
char mbuf[1024];
cin.getline(buffer,1024);

Based on your comment: "I am reading input interactively. exit command would leave the while loop and end the program"
You'd be better off getting that simple loop to work first, before trying to process the input string.
std::string inputCommand;
while(inputCommand != "Exit")
{
cin >> inputCommand;
//do stuff with it
}
Then you could consider splitting and handling the string
bool shouldExit(false);
std::vector<std::string> inputsReceived;
while(!shouldExit)
{
char delim ('#'); //here put whatever character your inputs are separated by
std::string buffer;
cin >> buffer;
std::stringstream ss;
ss << buffer;
std::string item;
while (std::getline(ss, item, delim))
{
if (item == "Exit") //case sensitive
{
shouldExit = true;
break;
}
else
{
//do whatever with input
}
//if you want to keep a record of the inputs in a vector
inputsReceived.push_back(item);
}
}

Related

how to read line by line string in a text file?

this code will only read and calculate the first input in the input.txt file and ignore the rest of the inputs in the input file.I have been trying to solve it so that it can read all the rest of the inputs and calculate them.
this is my code i think there is something wrong with it.
i have tried several looping methods
int main()
{
string inputLine;
ifstream file ("input.txt");// input file to be read
ofstream file1;
file1.open("output.txt");
freopen("output.txt", "w", stdout);// store all the output to this file
while (std::getline (file, inputLine)) // read the strings in the input file
{
if( strncmp( "----", inputLine.c_str(), 4 ) == 0 )
continue;
//calculating binary and hexadecimal values
char *opr = "^+-/%*=,()";
std::string::iterator end_pos = std::remove(inputLine.begin(),
inputLine.end(), ' ');
inputLine.erase(end_pos, inputLine.end());
string str=inputLine;
string str2="";
int length=str.length();
char t[length];
str.copy(t, length);
t[length] = '\0';
char* tok;
char *cop=new char [length];
str.copy(cop,length);
char *w = strtok_fixed( t, opr );
while (w!=NULL)
{
string w2=w;
std::stringstream tr;
tr << w2;
w2.clear();
tr >> w2;
int x=w2.length();
int y=x-3;
string check= w2.substr(0,3);
string check1=w2.substr(0,x);
if(check.find("0x") != std::string::npos)
{
unsigned int x= strtol(w2.c_str(), NULL, 0);
std::ostringstream s;
s << x;
const std::string ii(s.str());
str2=str2+ ii;
}
else if (check1.find("b")!=std::string::npos)
{
w2.pop_back();
long bin=std::strtol(w2.c_str(),0,2);
std::ostringstream s2;
s2<<bin;
const std::string t2(s2.str());
//inputLine.replace(inputLine.find(w2),(w2.length()+1),t2);
str2=str2+t2;
}
else
{
str2=str2+w2;
}
char a =cop[w-t+strlen(w)];
string s1="";
s1=s1+a;
std::stringstream tr1;
tr1 << s1;
s1.clear();
tr1 >> s1;
str2=str2+s1;
w = strtok_fixed (NULL, opr);
}
//str2 should be taken to the parser for final evaluations
Parser p(str2);
double value = p.Evaluate ();
std::cout<<"----------------------"<<endl;
std::cout << "Result = " << value << std::endl;
std::cout<<"----------------------"<<endl;
return 0;
}
}
The problem is at the end
return 0;
}
}
should be
}
return 0;
}
You are returning from inside your while loop instead of after your while loop finishes.
You should spend the time to indent your code correctly. It will help you spot this kind of error. You should also learn to break up your code into smaller functions. Again this will help you understand your own code a bit better.

C++, reading chars into a vector<char> from a file, character by character

I am trying to read in the first 7 chars of a file named "board.txt" into a vector<'char> but I am having issues for some reason. I am not too familiar with C++ so any advice would be appreciated, here is the code I have so far
//rack
int charCount = 0;
char ch;
ifstream rackIn("board.txt");
while(rackIn.get(ch) && charCount < 7){
this->getMyRack().push_back(ch);
}
And here is the function getMyRack used in the code above:
vector<char> board::getMyRack(){
return this->myRack;
}
myRack is a char vector
I tried to test this in my main using this:
for (int i = 0; i < test->getMyRack().size(); ++i){
cout << test->getMyRack().at(i);
}
but it does not output anything, why are the chars i am reading in not being added into my char vectors?
Because you don't put char in your vector. Your function getMyRack() returns vector but not address of your vector. You can add method to your class board for adding char, for example:
void board::addChar(char c){
this->myRack.push_back(c);
}
And then call this function:
while(rackIn.get(ch) && charCount < 7){
this->addChar(ch);
}
Or change the return type of your function.
read line one or (how much lines required) from file to a string
create substring of 7 chars from beginning
std::ifstream file("board.txt");
std::string str;
// to read single line
std::getline(file, str);
// to read 7 chars
str= str.substr(0,7);
vector<char> char_buf;
for(size_t i =0; i <= str.size();i++)
{
char_buf.push_back(str[i])
}
// use the char_buf
easier or second way is use
#include<fstream> // for ifstream
#include <cstdlib> // for exit()
std::string file_name ="board.txt";
std::ifstream input_stream;
std::vector<char> char_buf;
input_stream.open(file_name);
if(input_stream.fail()) { exit(0);}
int char_no=0;
while(i<=7)
{
char c = input_stream.get();
char_buf.push_back(c);
i++;
}
// use char_buf
std::string str;
int char_count=0;
// Read the next line from File untill it reaches the 7.
while (std::getline(in, str)&& char_count!=7)
{
// Line contains string of length > 0 then save it in vector
if (str.size() > 0)
your_char_vector.push_back(str);
char_count++;
if(char_count==7)
break;
}

Converting string to char**

I have a problem with my code and i dont know whats wrong :(
I want to convert a string to a char* array and print it out at the end.
The output is currently 3 times the last word of the sentence i entered.
void parse(std::string &s, char **argv)
{
std::istringstream iss(s);
std::string tmp;
while(iss >> tmp)
{
*argv++ = (char*) tmp.c_str();
}
}
int main()
{
std::string input;
while (1)
{
std::getline(std::cin, input);
int argCount = countArgs(input);
char *argv[argCount];
parse(input, argv);
for(int i=0; i<argCount; ++i)
{
std::cout << argv[i] << std::endl;
}
}
return 0;
}
I won't get into details why your current code does not work, because what you are doing is basically not-really-safe/good/sane thing. Please rethink your approach.
Why use char* if you can use string?
If possible, instead of
char *argv[argCount];
...
void parse(std::string &s, char **argv)
...
*argv++ = (char*) tmp.c_str();
use
string argv[argCount];
...
void parse(std::string &s, string* argv)
...
*argv++ = tmp;
it will work almost identically to what you have now, "just" using a different datatype.
However, note that this all will still not be really C++'y, as you are using string argv[argCount]; with non-constant argCount. I'm suprised your compiler actually compiles it, you must be using some C-compliance compilation flag. You should be using std::vector or std::list to keep an "array of variable length".
You can avoid the issues mentioned in the comments by calling strdup() before saving your char *:
void parse(std::string &s, char **argv)
{
std::istringstream iss(s);
std::string tmp;
while(iss >> tmp)
{
*argv++ = strdup( tmp.c_str() );
}
}
You'll need to free (not delete()) these copies later.
for (int i = 0; i < argCount; ++i)
{
std::cout << argv[i] << std::endl;
free( argv[i] );
}

Set illegal indirection error?

I'm getting a "set illegal indirection error" but I can't figure out what I am doing wrong.
What I am trying to do is take input from input.txt file that has a form
string1 string2
string3 string4
etc.
And number the strings in ascending order without duplicates, then use them in some functions and store the values in struct StringInt. But I am getting this weird error and I don't know where to start fixing it.
struct StringInt {
std::string name; // associate name and number for each input string
int number;
};
int main(int argc, char* argv[]) {
tot_strings = 100;
std::string vert1, vert2;
std::set<std::string> inGraph(0, tot_strings); // this is the set in question
std::set<std::string>::iterator sit;
std::vector<StringInt> stringInts(tot_strings); // Edit: forgot to mention this initially
StringInt* si;
int icv1, icv2;
std::ifstream myfile2 ("input.txt");
if (myfile2.is_open()) {
while(myfile2 >> vert1 >> vert2) {
myfile2 >> vert1 >> vert2;
if (inGraph.find(vert1) != inGraph.end()) { // not sure if I do this correctly
icv1 = i++;
si->name = vert1;
si->number = icv1;
inGraph.insert(vert1); // here's the insert that might be
stringInts.push_back(*si); // causing of the error
}
else {
icv1 = si->number;
}
if (inGraph.find(vert2) != inGraph.end()) {
icv2 = i++;
si->name = vert1;
si->number = icv2;
inGraph.insert(vert2);
stringInts.push_back(*si);
}
else {
icv1 = si->number;
}
// use icv1 and icv2 as int inputs in functions below
}
Does what I have make sense and how can I go about fixing the "set illegal indirection error"?
Edited: included std::vector stringInts(tot_strings) that I had in my code but forgot to include in the example.

How to initializing std::set<std::string> correctly?

Please help me, I have been trying to do this for the past two-three hours, all with no luck. I have a number of strings comming in form input.txt in the format
string1 string2
string3 string4
etc.
that I want to put into a std::set which is initially empty. I want to number the strings as they come in and put them into the set to keep track of the duplicates so I don't number them again. I am trying to initialize std::set<std::string> inGraph but can't make it work. I tried to initialize std::set<std::string> inGraph(0, tot_lines); where 0 to tot_lines is the range of the number of total strings I expect to get form the input. The I tried to initialize all with empty stirng like: std::set<std::string> inGraph(tot_lines, ""); and that failed. Here's what I have now:
struct StringInt {
std::string name; // associate name and number for each input string
int number;
};
int main(int argc, char* argv[]) {
int tot_lines = 100;
int icv1, icv2;
std::string vert1, vert2;
std::set<std::string> inGraph(); // this is the set I want to initialize
std::set<std::string>::iterator sit;
std::vector<StringInt> stringInts(tot_lines*2);
StringInt* si;
std::ifstream myfile2 ("input.txt");
if (myfile2.is_open()) {
while(myfile2 >> vert1 >> vert2) {
// read in input, put it in vars below
myfile2 >> vert1 >> vert2;
if (inGraph.find(vert1) != inGraph.end()) {
icv1 = i++;
si->name = vert1;
si->number = icv1;
inGraph.insert(vert1);
stringInts.push_back(*si);
}
else {
icv1 = si->number;
}
if (inGraph.find(vert2) != inGraph.end()) {
icv2 = i++;
si->name = vert1;
si->number = icv2;
inGraph.insert(vert2);
stringInts.push_back(*si);
}
else {
icv2 = si->number;
}
}
The error I get is: left of '.find' must have class/struct/union Can you please help me figure out how to initialize the std::set<std::string> inGraph so I can number the strings?
The error message is because you are a victim of Most Vexing Parse.
std::set<std::string> inGraph();
It is a function declaration whose return type is std::set<std::string>. Just remove the () after inGraph to make it a object declaration.