Attaching text file to Visual Studio project...? - c++

I'm almost done with a homework assignment but I'm having a hell of a time with one aspect of it. The purpose of the program is to read in a text file, and then do analysis. Now, if I'm on my computer, I can put in the full path of the file and it runs fine.
But it won't run ok if my professor tries to run it. I tried prompting the user to input a full path and that didn't work. I tried attaching the text file to the .exe but I don't think I did it right.
Anyone have any advice?
//int bookinput = 0;
//string whichbook;
//ifstream bookread;
//ifstream bookread(whichbook.c_str());
//cout << "Welcome to the book analysis program.\n";
//cout << "Please type in the full path of the book, remembering to double backslashes: ";
//cin >> whichbook;
//
//if(bookinput == 1){
// bookselect = "1984.txt";
//}
//else if(bookinput == 2){
// bookselect = "conneticutYankeeInKingArthursCourt.txt";
//}
//
//bookread.open(bookselect.c_str());
//bookread.open(whichbook.c_str());
bookread.open(whichbook.c_str());
if(bookread.is_open()){
std::cout << "opening book\n\n";
if(bookread.good()){
cout << "opening of book successful :D";
}
while(bookread.good()){ //reads to end of file
string input;
//getline(bookread, input);
bookread >> input;
//only add alphanumerical strings to the word list
if (isAlphaNumerical(input))
{
words.push_back(input);
}
}
}

This is the problem:
cout << "Please type in the full path of the book, remembering to double backslashes: ";
Double-backslashes are only meaningful to the C++ compiler. When you prompt the user for a path, the compiler isn't involved and double backslashes should NOT be used. (and string input cannot use \t to indicate a tab, etc., unless you implement special processing afterward)

You can keep the source file/exe file and text file in the same folder. Inform your professor to copy the entire folder and run it from there.
On another thought, the Prof. should have his own copy of the text file and he should be giving you instructions on how to locate the file within your program.

This bit of code I'm assuming is where the file path is being entered/decided.
.......
cin >> whichbook;
if(bookinput == 1){
bookselect = "1984.txt";
}
else if(bookinput == 2){
bookselect = "conneticutYankeeInKingArthursCourt.txt";
}
//should'nt this be either one line?
bookread.open(bookselect.c_str());
bookread.open(whichbook.c_str());
So if bookinput is 1 or 2, you're trying to open a file without specifying the path? You could keep the two text files in the same path as the executable and then you have to get the path of the executable and use it with the filename, instead, the easier/crappier route would be, you could hardcode it to a known path
Like:
bookselect = "C:\\Temp\\1984.txt";

Related

Have user type file they want read & appending filenames C++

Disclosure: I am a student right now, so if you see any bad habits in my code, feel free to point them out. I have questions about both the ofstream and ifstream portions of my code.
In the ofstream, the user can create their own shopping list and name it (which will end up being the file name). Once their list is created, the file will save with the data.
Here my question: How do I automatically assign a file type to a file a user named? Here is my current code for it:
void createList(double price[100], double quantity[100], string item[100], double tax, int list_size) {
ofstream saved_list;
string listname;
string fileApplicator = ".txt";
cout << "What would you like to save this list as?: ";
getline(cin, listname.append(fileApplicator));
saved_list.open(listname.c_str());
As for the ofstream part of my code, I want the user to be able to select which file they want read based on the name of the file.
Here's my question: When I run the code, the file fails to open every time. I have a current file saved as safeway.txt but it will not open when I attempt it. Here is the code for it:
void reviewList(void) {
ifstream saved_list;
string listname;
string fileApplicator = ".txt";
char viewAnother = 'Y';
do {
cout << "Which list would like to open: ";
getline(cin, listname.append(fileApplicator));
saved_list.open(listname.c_str());
if (saved_list.is_open()) {
......//other code
}
cout << "Would you like to view a different list (Y/N): ";
cin >> viewAnother;
viewAnother = toupper(viewAnother);
if (viewAnother == 'N')
break;
}
else {
cout << "List not found. Please try again.\n";
}
} while (viewAnother == 'Y');
}
Solution to this problem:
getline(cin,listname.append(fileApplicator)); is the error. The append needs to be processed AFTER the getline, like this:
getline(cin,listname);
listname.append(fileApplicator);
This will allow the user to not only name a file and have it automatically saved as the programmer's desired file type but will also automatically select the desired file to be read without the user needing to enter the extension (at least on Windows OS's). I.E.: User can enter "Filename" rather than "Filename.txt".
Thank you #user4581301 and #drescherjm for helping to solve this issue!

std::cin working for small number of lines, but not larger ones

I'm writing a part of a program that takes a list of filenames provided by the user and stores them in a vector. So far, testing with small numbers of filenames (I've done up to 11) works fine and the program continues, but trying to import 70 or more filenames makes it so that the program will not continue.
Here is my code:
//******************************* Get List of Filenames ********************************
cin.ignore(1000, '\n');
cout << "Please paste all of the Scans files here: ";
vector<string> filenameList;
string filenameString;
//can change the quit value to anything you want
while (cin >> filenameString && filenameString != "b")
{
filenameList.push_back(filenameString);
}
cout << "The filenames entered are:\n";
for (int i = 0; i < filenameList.size(); i++)
{
cout << filenameList[i] << endl;
}
cout << endl << filenameList.size();
The error is that the program hangs and looks like it is still waiting for input, but does not do anything else, even after entering the exit code "b".
We are copying and pasting the filenames directly into the console and then using cin to put them into a vector.
Here is an example of a list of the filenames that we are using:
MSS279_S10_B112_F8_p001.jpg
MSS279_S10_B112_F8_p002.jpg
MSS279_S10_B112_F8_p003.jpg
MSS279_S10_B112_F8_p004.jpg
MSS279_S10_B112_F8_p005.jpg
MSS279_S10_B112_F8_p006.jpg
MSS279_S10_B112_F8_p007.jpg
MSS279_S10_B112_F8_p008.jpg
MSS279_S10_B112_F8_p009.jpg
MSS279_S10_B112_F8_p010.jpg
MSS279_S10_B112_F8_p011.jpg
MSS279_S10_B112_F8_p012.jpg
MSS279_S10_B112_F8_p013.jpg
MSS279_S10_B112_F8_p014.jpg
MSS279_S10_B112_F8_p015.jpg
MSS279_S10_B112_F8_p016.jpg
MSS279_S10_B112_F8_p017.jpg
MSS279_S10_B112_F8_p018.jpg
MSS279_S10_B112_F8_p019.jpg
MSS279_S10_B112_F8_p020.jpg
MSS279_S10_B112_F8_p021.jpg
MSS279_S10_B112_F8_p022.jpg
MSS279_S10_B112_F8_p023.jpg
MSS279_S10_B112_F8_p024.jpg
MSS279_S10_B112_F8_p025.jpg
MSS279_S10_B112_F8_p026.jpg
MSS279_S10_B112_F8_p027.jpg
MSS279_S10_B112_F8_p028.jpg
MSS279_S10_B112_F8_p029.jpg
MSS279_S10_B112_F8_p030.jpg
MSS279_S10_B112_F8_p031.jpg
MSS279_S10_B112_F8_p032.jpg
MSS279_S10_B112_F8_p033.jpg
MSS279_S10_B112_F8_p034.jpg
MSS279_S10_B112_F8_p035.jpg
MSS279_S10_B112_F8_p036.jpg
MSS279_S10_B112_F8_p037.jpg
MSS279_S10_B112_F8_p038.jpg
MSS279_S10_B112_F8_p039.jpg
MSS279_S10_B112_F8_p040.jpg
MSS279_S10_B112_F8_p041.jpg
MSS279_S10_B112_F8_p042.jpg
MSS279_S10_B112_F8_p043.jpg
MSS279_S10_B112_F8_p044.jpg
MSS279_S10_B112_F8_p045.jpg
MSS279_S10_B112_F8_p046.jpg
MSS279_S10_B112_F8_p047.jpg
MSS279_S10_B112_F8_p048.jpg
MSS279_S10_B112_F8_p049.jpg
MSS279_S10_B112_F8_p050.jpg
MSS279_S10_B112_F8_p051.jpg
MSS279_S10_B112_F8_p052.jpg
MSS279_S10_B112_F8_p053.jpg
MSS279_S10_B112_F8_p054.jpg
MSS279_S10_B112_F8_p055.jpg
MSS279_S10_B112_F8_p056.jpg
MSS279_S10_B112_F8_p057.jpg
MSS279_S10_B112_F8_p058.jpg
MSS279_S10_B112_F8_p059.jpg
MSS279_S10_B112_F8_p060.jpg
MSS279_S10_B112_F8_p061.jpg
MSS279_S10_B112_F8_p062.jpg
MSS279_S10_B112_F8_p063.jpg
MSS279_S10_B112_F8_p064.jpg
MSS279_S10_B112_F8_p065.jpg
MSS279_S10_B112_F8_p066.jpg
MSS279_S10_B112_F8_p067.jpg
MSS279_S10_B112_F8_p068.jpg
MSS279_S10_B112_F8_p069.jpg
MSS279_S10_B112_F8_p070.jpg
MSS279_S10_B112_F8_p071.jpg
MSS279_S10_B112_F8_p072.jpg
MSS279_S10_B112_F8_p073.jpg
MSS279_S10_B112_F8_p074.jpg
MSS279_S10_B112_F8_p075.jpg
MSS279_S10_B112_F8_p076.jpg
Try separating cin >> filenameString && filenameString != "b" into two lines of code. Maybe put the second part inside the loop, in an if statement like this: if (filenameString != "b") break; I have a suspicion that assigning to filenameString and then comparing it in the same line may not always behave as you think it should.
I never figured out why, but I think there is a limit to the number of characters Xcode could import for some reason (somewhere around 1000 characters).
I switched over to Visual Studio on a PC and everything worked out perfectly...

How to extract specific substring from getline function in C++?

I'm fairly new to C++ so please forgive me if my terminology or methodology isn't correct.
I'm trying to write a simple program that:
Opens two input files ("infileicd" and "infilesel").
Opens a single output file "list.txt".
Compares "infilesel" to "infileicd" line by line.
If a line from "infilesel" is found in "infileicd", it writes that line from "infileicd" to "list.txt", effectively making a separate log file.
I am using the getline() function to do this but have run into trouble when trying to compare each file line. I think it might be easier if I could use only the substring of interest to use as a comparison.
The problem is that there are multiple words within the entire getline string and I am only really interested in the second one. Here are two examples:
"1529 nic1_mau_op_mode_3 "8664afm007-01" "1" OUTPUT 1 0 LOGICAL 4 4136"
"1523 pilot_mfd_only_sel "8664afm003-02" "1" OUTPUT 1 0 LOGICAL 4 4112"
"nic1_mau_op_mode_3" and "pilot_mfd_only_sel" are the only substrings of interest.
It would make it a lot easier if I could only use that second substring to compare but I don't know how to extract it specifically from the getline() function. I haven't found anything suggesting it is impossible to do this, but if it is impossible, what would be an alternative method for extracting that substring?
This is a personal project so I'm under no time contstraints.
Any assistance is greatly apprecated in advance. Here is my code (so far):
int main()
{
//Open the file to write the selected variables to.
ofstream writer("list.txt");
//Open the selected variabels file to be read.
ifstream infilesel;
infilesel.open("varsel.txt");
//Open the icd file to be read.
ifstream infileicd;
infileicd.open("aic_fdk_host.txt");
//Check icd file for errors.
if (infileicd.fail()){
cerr << "Error opening icd.\n" << endl;
return 1;
}
else {
cout << "The icd file has been opened.\n";
}
//Check selected variables file for errors.
if (infilesel.fail()){
cerr << "Error opening selection file.\n" << endl;
return 1;
}
else {
cout << "The selection file has been opened.\n";
}
//Read each infile and copy contents of icd file to the list file.
string namesel;
string nameicd;
while(!infileicd.eof()){
getline(infileicd, nameicd);
getline(infilesel, namesel);
if (nameicd != namesel){ //This is where I would like to extract and compare the two specific strings
infileicd; //Skip to next line if not the same
} else {
writer << nameicd << namesel << endl;
}
}
writer.close();
infilesel.close();
infileicd.close();
return 0;
}
So, based on what we discussed in the comments, you just need to toss the stuff you don't want. So try this:
string namesel;
string nameicd;
string junk;
while(!infileicd.eof()){
// Get the first section, which we'll ignore
getline(infileicd, junk, ' ');
getline(infilesel, junk, ' ');
// Get the real data
getline(infileicd, nameicd, ' ');
getline(infilesel, namesel, ' ');
// Get the rest of the line, which we'll ignore
getline(infileicd, junk);
getline(infilesel, junk);
Basically, getline takes a delimiter, which by default is a newline. By setting it as a space the first time, you get rid of the first junk section, using the same method, you get the part you want, and then the final portion goes to the end of the line, also ignoring it.

How to "select" current directory?

I am writing a proportion calculator. At the beginning of the program, it loads a ascii text art picture from a .txt in the same folder.
Here is how I am doing it:
//Read picture
string line;
ifstream myfile("/Users/MYNAME/Desktop/MathScripts/Proportions/Value Finder/picture.txt");
if (myfile.is_open()) {
while (!myfile.eof()) {
getline(myfile, line);
cout << line << endl;
}
myfile.close();
} else cout << "Unable to load picture!!!" << endl;
//Finish reading txt
I heard how if the .txt is in the same folder, that you can just use the name and not have to say the directory. Meaning instead of
/Users/MYNAME/Desktop/MathScripts/Proportions/Value Finder/picture.txt
I could just use "picture.txt". That doesn't work for me, and I want the user to be able to move around the "Value Finder" folder without having to edit any code.
I am on Mac and I am using CodeRunner; anything odd?
Please do not tell me to make sure that picture.txt is in the same folder as my code. It is.
In order to open picture.txt without using a fully qualified path it has to reside in the current working directory. When an IDE launches an application it it sets the current working directory to the same one the application resides in. If picture.txt resides in a different directory than the application you will not be able to open it with just it's name. If you need to get the current working directory you can call getcwd like so.
char temp[MAXPATHLEN];
getcwd(temp, MAXPATHLEN);
If you want to allow the user to specify which directory picture.txt is in you can let them pass an argument on the command line. You can then create a fully qualified path with the supplied directory and the picture filename.
int main(int argc, const char **argv)
{
// Add some logic to see if the user passes a path as an argument
// and grab it. here we just assume it was passed on the command line.
const string user_path = arg[1];
//Read picture
string line;
ifstream myfile(user_path + "/picture.txt");
if (myfile.is_open())
{
while (!myfile.eof()) {
getline(myfile, line);
cout << line << endl;
}
myfile.close();
}
else
{
cout << "Unable to load picture!!!" << endl;
}
//Finish reading txt
return 0;
}
Now you can do something like this:
myapp "/user/USERNAME/Desktop/MathScripts/Proportions/Value Finder"
and it will look in that directory for the picture.txt file. (Quotes are required because there is a space in the pathname).
Note: You can call setcwd() to change the current working directory of the application.

Simple File I/O in C++ - Never Exits This Loop?

I'm a programming student in my second OOP class, my first class was taught in C# and this class is taught in C++. To get our feet wet in C++, our professor has asked us to write a rather large program with File I/O. The problem is, I have a small part of my program that is not working, at least, not for me. The project requires that we code a loop to test if the file could be opened successfully, and the loop I have written doesn't seem to be working.
I don't get any compiler errors, but when I enter in the path to the file, either relative or absolute, it says it's invalid. I have a feeling it has something to do with my conditions in my do-while loop, but I can't pinpoint it.
I don't mean to bring my homework to SO, but I've been scratching my head for two+ hours, and I can't seem to figure this out.
Would you mind helping me fix my loop? And maybe explain what it is that I'm doing wrong? I want to learn.
Thanks!
Code:
Rainfall rData;
ifstream actualReader;
ifstream averageReader;
string aRDataLoc;
char response = 'a';
const int KILL_VALUE = 1;
double actualRainfallD;
double actualRainfallPassedArray[ARRAY_CAPACITY];
double averageRainfallPassedArray[ARRAY_CAPACITY];
int i = 0;
do
{
actualReader.clear();
cout << "\nPlease enter in the path to the file containing the actual rainfall data." << endl;
cout << "Path to file: ";
cin >> aRDataLoc;
actualReader.open(aRDataLoc.c_str());
if (!actualReader.is_open())
{
cout << "Invalid file path! Would you like to enter in a new file path?(y/n): ";
cin >> response;
if (response == 'n') { exit(KILL_VALUE); }
}
}while (!actualReader.is_open() && response == 'y');
I don't know what input you are giving to cin, but be aware that cin will stop at the first whitespace character it encounters. For example, if you give as input the following:
C:\Program Files\directory
then aRDataLog would have the value C:\Program .
In order to read the whole line, you could use getline.
Check also this post.
While I'm not exactly sure what the issue is here, it might be a good idea to print what you're getting from std::cin to ensure you're getting what you're expecting.
you need to put actualReader.close call in else, as the file has open handles and it is not available for open again