I'm very new to c++ there is a good bit of code here, so im going to do my best to condense it to the problem area. when I try to get user input using getline im getting this error. Since i don't expect spaces in the file names(i made the files)i use cin << which worked fine, but then got the same error when trying to read the file. the code is as follows
// includes here
using namespace std;
//other prototypes here
string getUserDataFromFile(vector<int>&, int&, string);
int main()
{
vector<int> numbers;
numbers.reserve(50);
int numberOfElements = 0;
int number = 0;
int numToFind = 0;
int numberPosition = -1;
int useFile = 0;
string filename = "";
string fileReadMessage = "";
string output = "";
string outFilename = "";
cout << "Would you like to load the data from a file?(1 for yes 0 for no)";
cin >> useFile;
cin.ignore(INT_MAX, '\n');
//get user data for manual input
if(useFile == 0)
{
//code here for manual input(works fine)...
}
//get userdata for file input
else
{
cout << "Please Enter the file path to be opened" << endl;
//fixed after adding cin.ignore(INT_MAX, '\n');
//see next function for another problem
getline(cin, filename);
fileReadMessage = getUserDataFromFile(numbers, numToFind, filename);
}
//some code to get data for output
return 0;
}
//function to get user data from file
//#param v(vector<int>&) - vector of integers.
//#param numToFind(int&) - the number we are looking for
//#param filename(string) - the filename of the file with data
//#return message(string) - a message containing errors or success.
string getUserDataFromFile(vector<int>& v, int& numToFind, string filename)
{
string message = "File Accepted";
string line = "";
int numOfElements = 0;
int count = 0;
ifstream fileToRead(filename.c_str());
//using 'cin >>' in main, the program runs till here then breaks
//if message is a file, extract message from file
if (fileToRead.is_open())
{
while (getline(fileToRead,line))
{
//code to do stuff with file contents here
}
fileToRead.close();
}
else
{
message = "Unable to open file.";
}
return message;
}
I left a couple of comments in the trouble areas and left out most of the code that i haven't had trouble with or haven't been able to test. Any help is appreciated. Thanks!
So my first issue was fixed by the addition of cin.ignore(INT_MAX, '\n'); any guesses on the next problem? its the line if (fileToRead.is_open()) in the next function
Add
cin.ignore();
before:
getline(cin, filename);
Otherwise, ENTER you typed after entering useFile will be read into filename.
Related
I am having a tough time figuring out the process of reading text files into the program. Down in the get_answer_key_array, I am trying to read and put only the top line of the text file into an array.
The text file looks something like this:
ABDBCBDBABABCBABCB
Bob Bobby adcad abcbd bacb
Every text file tested in this program will have the answer key on the first line. Every line after the first line will have the persons first name, space, last name, space, grades and missing grades will be replaced by a "-" when I get to it.
I am currently working on obtaining the first line and putting it into the answer key array.
I know that once I am done with the first line I can put the persons first name, last name, and answers into three separate parallel arrays. I am having trouble coming up with the right way to check for that first new line so I can get the answer key.
Alright so now I have changed my get_answer_key_array to obtain all of the arrays I will need. Currently I am trying to get the top line (the answer key) into the first array of answer_key[]. I have tried to implement the getline function but am trying to figure out how to only get the top line. Is it possible to keep my eof() loop yet stop at the first endline to transferthe data of the first line into the array? Also my
answer_key[i] = key; needs changed to something else I bet!
I should also mention once I figure out how to get the top line into an array, I want to use this process to get the rest of the data (names and answers) into their own separate arrays via the following workflow:
in_stream >> first_name[i] >> last_name[i] >> answers[i];
while(!in_stream.eof() ) {
i++;
in_stream >> first_name[i] >> last_name[i] >> answers[i];
}
in_stream.close();
START OF PROGRAM BELOW
void get_input_file(ifstream &in_stream); //gets the text file name from the user
void get_arrays(ifstream &in_stream, int answer_key[], string first_name[], string last_name[], int answers[], int &count); //brings the data from text file into all of the parallel arrays
//void score_grader(int &target, string first_name[], string last_name[], int answers[], int &count, int &score);
//void letter_grade(int &score, int &letter_grade);
//void student_report(int &target, string first_name[], string last_name[], int answers []);
int main()
{
ifstream in_stream;
int answer_key[30], count = 0, score = 0; //initializing the answer key array up to 30 answers
string first_name[20]; //initializing the first name array
string last_name[20]; //initializing the last name array
int answers[30]; //initializing the answers array
cout << "Welcome to the Test Grader." << endl; //welcome message
get_input_file(in_stream); //function call to get the file name
get_arrays(in_stream, answer_key, first_name, last_name, answers, count); //function call to create the arrays
}
void get_input_file(ifstream &in_stream) {
string file_name; //initializing the file name string
do {
cout << "Enter the file name you would like to import the data from: " << endl; //asks user to input name of file
cin >> file_name; //user types name of file
in_stream.open(file_name.c_str()); //program opens the stream
if(in_stream.fail()) {
cout << "Error finding file, try again.\n"; //if failed, asks user for file name again
continue; //continues back to the do loop
}
break;
} while(true);
cout << "File Obtained: " << file_name << endl; //alerts user of file success with printed name
}
void get_arrays(ifstream &in_stream, int answer_key[], string first_name[], string last_name[], int answers[],
int &count) {
int i = 0;
string key; //This will be the storage variable for the first line of text file
if (in_stream.is_open() ) { //if the stream is open
getline(in_stream, key);
cout << "Testing: " << key << endl;
while(!in_stream.eof() ) {
i++;
in_stream >> first_name[i] >> last_name[i] >> answers[i];
}
}
cout << first_name[1] << " " << last_name[1] << " " << answers[1] << endl;
in_stream.close();
}
You can simply read the first line this way
void get_answer_key_array(ifstream &in_stream, char *answer_key, int &count) {
in_stream >> answer_key;
count = strlen(answer_key);
}
The answer_key array must be of type char.
And the endline character is '\n' not '/n'
One of the things my program needs to do is validate a file using the isValid function entered by user and it will keep doing this until exit is entered and if I enter nothing but valid file names there are no problems. But when I enter an invalid file name followed by a valid file name it still says the file is invalid and I cannot figure out why and I have tried debugging it and what not and still cannot find the problem. Any help would be greatly appreciated!
# include <iostream>
#include <string>
#include<fstream>
#include<vector>
using namespace std;
void Open_file(string name)
{
ifstream my_file;
my_file.open(name.c_str());
}
bool isValid(ifstream& file, string name)
{
if ((name.substr(name.length() - 4)) != (".htm"))
{
return false;
}
cout << file << endl;
if (file.good())
{
return true;
}
else
{
return false;
}
}
string File_title(ifstream& my_file)
{
string title;
string line;
size_t first_title;
size_t second_title;
string str;
while((getline(my_file,line)))
{
str = str + line;
}
first_title = str.find("<title>");
second_title = str.find("</title>");
title = str.substr(first_title + 7, (second_title) - (first_title + 7));
return title;
}
void Output_function(ifstream& my_file)
{
string line;
ifstream MyFile("titles.txt");
string g = File_title(my_file);
while(getline(MyFile, line))
{
if((g == line))
{
return;
}
}
ofstream out_title("titles.txt", fstream::app);
out_title << g << endl ;
}
void Clear_file()
{
ofstream out_title("titles.txt");
out_title << "" << endl;
}
int main()
{
string file_name;
while (file_name != "exit")
{
cout <<"please enter a HTML file name or hit 'exit' to quit and " << endl;
cout << "if you want to clear file please enter 'clear': ";
getline(cin,file_name);
ifstream my_file(file_name.c_str());
cin.ignore(256, '\n');
if(file_name == "clear")
{
Clear_file();
break;
}
while ((isValid(my_file, file_name) == false))
{
cin.clear();
cout <<"Invalid file name, please enter a valid file name: ";
getline(cin,file_name);
ifstream my_file(file_name.c_str());
}
Open_file(file_name);
Output_function(my_file);
my_file.close();
}
}
ifstream my_file(file_name.c_str());
This doesn't replace the my_file you'd already created in an outer scope. It just makes a new local variable that lives for like a nanosecond.
You'll have to close then re-open the existing my_file, being sure to reset its error flags too.
The logic you are using to exit the loop is flawed.
You need to check the value of file_name right after it is entered, not after it is processed in the while loop once.
You need to use something along the lines of:
while ((file_name = get_file_name()) != "exit")
{
...
}
where
std::string get_file_name()
{
std::string file_name;
cout <<"please enter a HTML file name or hit 'exit' to quit and " << endl;
cout << "if you want to clear file please enter 'clear': ";
getline(cin,file_name);
return file_name;
}
Other improvements:
The call to cin.ignore() is going to be a problem line since std::getline does not leave the newline character in the input stream. You'll have to type Enter one more time. You should remove it.
You don't need the cin.clear() line. You need cin.clear() only if an error was detected in reading from the stream -- such as when using cin >> var; when the input stream did not have the right data suitable for var.
You don't need to open the file if the file is not valid.
You don't need multiple lines ifstream my_file(file_name.c_str());. You only need it once, just before the call to Output_function(my_file).
You don't need to explicitly call my_file.close(). The file will be closed and the end of the scope.
Here's a simplified version of main.
int main()
{
string file_name;
while ((file_name = get_file_name()) != "exit")
{
if(file_name == "clear")
{
Clear_file();
break;
}
while ( isValid(my_file, file_name) == false )
{
cout <<"Invalid file name, please enter a valid file name: ";
getline(cin,file_name);
}
Open_file(file_name);
ifstream my_file(file_name.c_str());
Output_function(my_file);
}
}
Write a simple telephone directory program in C++ that looks up phone numbers in a file containing a list of names and phone numbers. The user should be prompted to enter a first name and last name, and the program then outputs the corresponding number, or indicates that the name isn't in the directory. After each lookup, the program should ask the user whether they want to look up another number, and then either repeat the process or exit the program. The data on the file should be organized so that each line contains a first name, a last name, and a phone number, separated by blanks. You can return to the beginning of the file by closing it an opening it again.
I cant get the line
check = strstr(phoneDirectory, name);
to work strstr part keep giving the error: no instance of overloaded function "strstr" matches the argument list argument types.
Here a copy of my code:
#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
using namespace std;
int arraySize();
int main()
{
const int SIZE = arraySize();
char *phoneDirectory;
int size=0;
char name; //name to look for
char *check = NULL;
bool find = false;
phoneDirectory = new char [SIZE];
ifstream phoneNumbers;
phoneNumbers.open("phoneNumbers.txt");
if (!phoneNumbers)
cout << "Error opening data file\n";
//looping throught the name file
else
{
for (int i = 0; i < SIZE; i++)
{
phoneNumbers >> phoneDirectory;
}
phoneNumbers.close(); //closes data file
}
phoneNumbers.close();
// Get a name or partial name to search for.
cout << "Enter a name or partial name to search for: ";
cin.getline(phoneDirectory, name);
cout << "\nHere are the results of the search: " << endl;
int entries = 0;
for (int i = 0; i < size; i++)
{
check = strstr(phoneDirectory, name);
if (check != NULL)
find = true;
}
if (!find)
cout << "No matches!" << endl;
delete [] phoneDirectory;
return 0;
}
int arraySize()
{
string phoneNum;
int size = 0;
ifstream phoneNumbers; // Input file stream object
// Open the data file.
phoneNumbers.open("phoneNumbers.txt");
if (!phoneNumbers)
cout << "Error opening data file\n";
//looping throught the name file
else
{
while (getline(phoneNumbers, phoneNum))
{
size++;
}
phoneNumbers.close(); //closes data file
}
return size;
}
Your name variable is a char. Should it be a char* instead?
I am trying to get a file location from the user. I've used the same getfile function on dozens of programs with no issues. For some strange reason this one always returns a cannot open file on the 1st try but then accepts it on the 2nd try. I have tried a cin.clear(); before the getline where I get the file location but that was no help. I cant figure out why this is acting so weird. Here is my getfile function:
void maze::getfile()
{
string filename;
char X;
cout << "please enter the location of the file you wish to input: " << endl;
getline(cin, filename);
cin.ignore(100, '\n');
inData.open(filename.c_str()); //opens file
while (!inData) //while the file is accesible
{
cout << "The file could not be opened.\nPlease try again: " << endl;
//error message for input validation
getline(cin, filename);
cin.ignore(100, '\n');
inData.open(filename.c_str());
}
for(int i = 1; i < 11; i++)
{
for(int u = 1; u < 11; u++)
{
inData >> X >>ws;
if(X == '1')
X = 219;
if(X == '0')
X = ' ';
floor[i][u] = X;
}
}
floor[0][0] = 201;
floor[0][11] = 187;
floor[11][0] = 200;
floor[11][11] = 188;
for(int i=1; i < 11; i++)
{
floor[0][i] = 205;
floor[11][i] = 205;
floor[i][0] = 186;
floor[i][11] = 186;
}
inData.close();
}
The only thing that happens before this is the main menu call. I set a variable choice = to a main menu function that returns a char, in this case '1'. Any ideas why it's failing on the first file input and not the 2nd try with the same file?
I'm sure you left a newline(maybe scanf(), cin>>, gets() left in) in the stream before you call std::getline first time, so that it gives you an empty string for the filename, after that, newline is eaten, so it works fine second time.
I am trying to open a .dat file to use as an input for my program. The assignment says I need to convert the name I enter for the file name into c-string datatype so it can be read through the .open("") command. My program compiles but I'm sure I'm doing something wrong when I try to convert file name. I have looked around for people with similar problems but I've had no luck so any suggestions you can give me would be much appreciated!
Here is the function where I attempt to open the file, and the other function where I try to convert the file name.
int main()
{
ifstream fp;
string name[SIZE], filename;
int counter, idx = 0;
float rate[SIZE], sum[SIZE], gross[SIZE], with[SIZE], pay[SIZE], net[SIZE], hours[SIZE];
getfile(fp, filename);
readFile(fp, name, rate, hours);
pay[SIZE] = calcPay(rate, sum);
gross[SIZE] = calcGross(pay);
with[SIZE] = calcAmount(gross);
net[SIZE] = calcNet(gross, with);
output(name, rate, sum, with, gross, net, pay, SIZE);
return 0;
}
//Convert filename into C-string
string convert(ifstream &fp, string filename)
{
fp.open(filename.c_str());
return filename;
}
//Get file name from user.
void getfile(ifstream &fp, string filename)
{
cout <<" Enter the name of the file: ";
cin>>filename;
convert(fp, filename);
fp.open("filename");
if (!fp)
{
cout<<"Error opening file\n";
exit (1);
}
}
cout <<" Enter the name of the file: ";
cin>>filename;
convert(fp, filename);
fp.open("filename");
was probably meant to be (in case of present C++11 support):
cout << " Enter the name of the file: ";
cin >> filename;
fp.open(filename);
or (in C++03):
cout << " Enter the name of the file: ";
cin >> filename;
fp.open(filename.c_str());
Side note: Elements in an array are indexed from 0 to SIZE - 1 so when you declare:
float pay[SIZE];
then when you do:
pay[SIZE] = calcPay(rate, sum);
you are accessing memory "pass" the last element, which causes undefined behavior.