c++: Expected primary-expression - c++

I have been struggling with a certain error that doesn't make sense to me. Whenever I try to compile this program, it tells me that I'm missing a semicolon when I am not.
It seems the error is linked to a specific block of code, that being the if statement that checks stock. Since I know c++ can be platform specific, I'm running debian 9 and the atom ide if that's any help.
Here is the specifc error:
error: expected primary-expression before ',' token
getline(string,line);//gets string`
and the code:
#include <iostream>
#include <fstream>
using namespace std;
int main ()
{
cout << "store stocking system: \n"; // yadda yadda yadda UX
cout << "commands: \n";
cout << " help: shows available commands\n check stock: checks store stock\n enter stock: enter new stock items\n";
cout << " exit: terminates the program\n clean house: deletes all stock\n";
home: // main loop in program
string output;
output = ">> ";
cout << output;
string stock;
string item; // this whole block just defines things and gets input
int itemNumber;
string userInput;
getline(cin,userInput);
if (userInput == "exit")
{
return 0;
}
if (userInput == "enter stock")
{ // enters new stock
cout << "enter item\n>> "; //item name
cin >> item;
cout << "enter amount\n>> "; //amount of item
cin >> itemNumber;
ofstream myfile; //makes file
myfile.open("stock.txt"); //opens myfile
myfile << "\n" << item << "," << itemNumber << "\n"; //writes to file
myfile.close();// closes file
cout << "done";
goto home; //finishes and goes to main loop
}
if (userInput == "check stock") // where the problem is
{
string line;
ifstream file("stock.txt");//checks fo file
file.open("stock.txt");//opens file
getline(string,line);//gets string
file.close();//closes it
cout << line << "\n";
goto home;
}
if (userInput == ""){
goto home;
}
else
{
cout << "\033[1;31mplease use a proper command:\033[0m\n";
goto home;
}
return 0;
}

Are you missing this by any chance?
#include <string>

I believe it simply needs to be getline(file,line) rather than getline(string,line) and then you should be sorted.

string is recognized as a type name, of type std::string which you generously exposed by line using namespace std;. This particular error message is caused by fact that string isn't an expression which can be evaluated . In context of your code it should be
getline(file,line);
PS. Standard would say that you have to include <string> header to use component std::string. Your code compiles thanks to an implementation-defined feature, was imported with <iostream> in this version of header.

Related

More appropriate way to loop input from a file?

I want to be able to loop this file opening and closing to continually search for names.
The first time is no problem and output is what is expected then, when choosing y for yes, an output loop occurs.
Any ideas as to why this would happen? The logic seems more than correct.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string boys, girls, name;
int rank;
char end = 'n';
while (end != 'y' || end != 'Y')
{
cout << "Enter a name to search";
cin >> name;
ifstream input;
input.open("Names2016");
if (input.fail())
cout << "Failed to open file.\n";
while (!input.eof())
{
input >> rank >> boys >> girls;
if (boys == name)
cout << name << " ranks " << rank << " among boys.\n";
if (girls == name)
cout << name << " ranks " << rank << " among girls.\n";
}
input.close();
cout << "Would you like to search another name?\n"
<< "Enter Y for yes or N for no.\n";
cin >> end;
}
return 0;
}
There are a some of things you can do to make this code better,
The first is to use ifstreams and do file input/output the proper idiomatic way in a loop, don't use .eof() to check for end of file in a loop condition (the answer linked in the comments is a good place to start if you want to know why),
The second thing you want to check for validity of the file with a simple if (!file) its much cleaner IMO.
The third thing is, when you have a local file handle like you do in your code, then you can just let it go out of scope and let the destructor cleanup the file and close() it, it's the C++ RAII way of doing things (notice that I have removed the open() method to the constructor call (which does the same thing)
Use cerr instead of cout to report errors
Use char instead of int to represent characters
Not a big change, but using std::toupper like advised in the other answer's comments is a good readable way to check for uppercase and lowercase values at the same time
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
using namespace std;
int main()
{
string boys, girls, name;
int rank;
char end = 'n';
while (std::toupper(end) == 'Y')
{
cout << "Enter a name to search";
cin >> name;
ifstream input{"Names2016"};
// change here
if (!input) {
cerr << "Failed to open file.\n";
}
while (input >> rank >> boys >> girls)
{
if (boys == name)
cout << name << " ranks " << rank << " among boys.\n";
if (girls == name)
cout << name << " ranks " << rank << " among girls.\n";
}
// change below, just let the file handle go out of scope and close
// input.close();
cout << "Would you like to search another name?\n"
<< "Enter Y for yes or N for no.\n";
cin >> end;
}
return 0;
}
But you can do better on the I/O if your file isn't guaranteed to change over different iterations (in which case you probably need to make sure that there is no race anyway, so I am assuming the file does not change much). Read in the file once and save that information to be used later
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
#include <unordered_map>
#include <vector>
using namespace std;
int main()
{
string boys_name, girls_name, name;
int rank;
char end = 'n';
ifstream input{"Names2016"};
if (!input) {
cerr << "Failed to open file" << endl;
}
// preprocess the information and store it in a map
// making a map from string to vector because it is unclear whether
// there is a 1-1 mapping from the name to the rank for each name
unordered_map<string, vector<int>> boys;
unordered_map<string, vector<int>> girls;
while (input >> rank >> boys_name >> girls_name) {
boys[boys_name].push_back(rank);
girls[girls_name].push_back(rank);
}
while (std::toupper(end) == 'Y')
{
cout << "Enter a name to search";
cin >> name;
// use the map to do the lookup, much faster than reading
// the entire file over and over again
}
return 0;
}
First of all, what is this supposed to mean int end = 'n'; Are you assigning an integer with a character value?!
And why are you opening the same file inside the loop. You should probably open it only once at the beginning of the program.
And the eof doesn't have what to check for, because you have to read from a file to reach its end.

Finding String on C++

I got a task from my teacher. I try some code but it confuses me a lot. So here's my code :
#include <iostream>
using namespace std;
char inputChecker [1000];
string source = "10110111000111001101110";
string detected;
int main(){
cout <<"Input:";
cin >> inputChecker;
for (int i=0;i<source.size();i++){
if (source[i]==inputChecker[0]){
cout <<"Data " <<inputChecker <<"is exist" <<endl;
}
else if (source[i]==inputChecker[i]){
cout <<"Data " <<inputChecker <<" isn't exist'" <<endl;
}
}
}
So ,my expectation output is ,when i input 10,it will result "Data 10 is exist". Without looping. I think it needed 2 kind of looping but i dont know where to loop.
My expectation output :
Input : 10
Data 10 is exist
Input : 25
Data 25 isn't exist
Thanks in advance :))
No need for loop
#include <iostream>
using namespace std;
int main() {
string source = "10110111000111001101110";
string input;
cin >> input;
if (source.find(input) != string::npos)
cout << input << " exists\n";
else
cout << input <<" doesn't exist\n";
}
Have a look at other useful std::string methods like find_first_of, find_last_of, etc.

Why can't I write to a file if it is located within an if statement?

I am trying to create a very simple program that writes to a file, but can't understand why it won't let me write to a file if I put it within an if statement! Here's the code:
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
using namespace std;
void readFile();
int main()
{
string line;
string today;
string readOrWrite;
cout << "Do you want to write to a file or read a file? " << endl;
cout << "Type \"write\" or \"read\" ";
cin >> readOrWrite;
if (readOrWrite == "read")
{
readFile();
}
else if (readOrWrite == "write")
{
cout << "How are you today? " << endl;
getline(cin, today);
ofstream myJournal;
myJournal.open("Journal.txt", ios::app);
myJournal << today << " ";
myJournal.close();
}
else
{
return 0;
}
return 0;
}
void readFile()
{
ifstream myJournal;
myJournal.open("Journal.txt");
string line;
if (myJournal.is_open())
{
while (getline(myJournal, line))
{
cout << line << endl;
}
myJournal.close();
}
else
{
cerr << "Error opening file ";
exit(1);
}
}
When I move it out of the if statement, it works smoothly and is able to write to the file, but when I place it inside, it opens the program, asks me the "Do you want to write to a file or read a file? ", I type "write", then it says "How are you today? " and then ends the program, printing "Press any key to continue...". Any help?
it says "How are you today? " and then ends the program, printing "Press any key to continue...". Any help?
std::istream::ignore should help in that case you are encountering.
cout << "How are you today? " << endl;
cin.ignore(10, '\n'); // Inserted
getline(cin, today);
Why do we need that in between?
It takes out 10 characters, which is enough amount of length, from the buffer and stops if it encounters a newline, which is '\n'. (Remember that you press the key 'enter' after typing "wrtie")
By doing so you can move on to the next new line, preventing std::cin from any parse failure.
More info : http://www.cplusplus.com/reference/istream/istream/ignore/

Find a string in a input file - C++

I need to find a string (link name) input by the user in a text file.
How can approach a solution in c++? Do I have to store the file context in structs in order to read the data later? Or can I just open and read the file whenever i want to look for info?
Thank you!
Input file sample
111.176.4.191 www.yahoo.com 01/04/2013
111.176.4.191 www.yahoo.com 01/09/2013
192.168.1.101 www.yahoo.com 01/04/2013
111.176.4.191 www.yahoo.com 01/12/2013
192.168.1.101 www.espn.com 01/05/2013
C++ code
#include <fstream>
#include <iostream>
#include <string>
#include <cstdlib>
#include <string>
using namespace std;
//gobal variables, procedures
void fileinfo1(string);
char IP_Address [12];
char Link_Name [50];
char Date_Accessed [8];
string filename;
int menu;
int main()
{
// the user will input the file name here
cout << "Enter filename> ";
getline( cin, filename );
fstream file( filename.c_str() );
if (!file)
{
cout << "Invalid file.\n";
return EXIT_FAILURE;
}
// the program will display the file context
else
{
string line;
int count = 10;
while ((count > 0) && getline( file, line ))
{
cout << line << '\n';
count--;
}
file.close();
}
return EXIT_SUCCESS;
// The user will be able to choose to see info about all entries or a particular one
cout << "Please select a menu option:";
cout << "1)Link Information in date range";
cout << "2)Information about all links";
cout << "3)Quit the program";
cin >> menu;
switch (menu) {
// see info about a particular link
case 1: fileinfo1(filename);
break;
case 2:
break;
case 3:
break;
default: cout << "Please a choose a number between 1 and 3";
break;
}
// the file is passed to this function
void fileinfo1(string filename) {
//the user will input a link e.g www.espn.com
cout << "What is the link name? ";
cin >> Link_Name;
// and also input date range (start-end)
cout << "What is the starting date? " ;
cin >> Date_Accessed;
cout << "What is the ending date? " ;
cin >> Date_Accessed;
// Now, here's where I'm having trouble
// I need to find the wwww.espn.com in my file based on the range date , so that i will be able to increment the number of hits
unsigned int curLine = 0;
while (getline(filename, line)) { // I changed this, see below
curLine++;
if (line.find(search, 0) != string::npos) {
cout << "found: " << search << "line: " << curLine << endl;
}
}
}
}
Thank you!
This Part of the code shouldnt be written into your main() function.
// the file is passed to this function
void fileinfo1(string filename) {
//the user will input a link e.g www.espn.com
cout << "What is the link name? ";
cin >> Link_Name;
// and also input date range (start-end)
cout << "What is the starting date? " ;
cin >> Date_Accessed;
cout << "What is the ending date? " ;
cin >> Date_Accessed;
// Now, here's where I'm having trouble
// I need to find the wwww.espn.com in my file based on the range date , so that i will be able to increment the number of hits
unsigned int curLine = 0;
while (getline(filename, line)) { // I changed this, see below
curLine++;
if (line.find(search, 0) != string::npos) {
cout << "found: " << search << "line: " << curLine << endl;
}
}
}
and you are using way to many global variables which are really not necessary. And you dident declare the variables line and search. This shoudnt even compile.
Do you want a quick and dirty solution or an elegant one?
For an elegant solution, I would:
Ditch the globals.
Read the entire file into memory before parsing it.
Generate an internal database for your data.
Write a few query functions that return a subset of your data.
For your particular case, you could use a std::multimap < LinkName, DateAndIP > to find all data relating to the link. DateAndIP could be a typedef to std::multimap < Date, IP > . If you've never used multimap, this will be a good learning experience. Write your compare functions and use the find member function to return only what you're looking for.
Good luck and happy coding!

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;
}