I'm making a very simple file parser, in CSV style. The compilation runs smoothly, and when I run it, I'm having a segfault (core dumped). The only printed line is the one telling "Done" to say that the file succesfully opened. So my guess is that the Segfault happened during while(getline(myfile, line)).
Here's my code (parser.cpp):
#include "parser.h"
vector<string> str_explode(string const & s, char delim)
{
vector<string> result;
istringstream iss(s);
for (string token; getline(iss, token, delim); )
{
result.push_back(move(token));
}
return result;
}
vector<vector<string>> getTokensFromFile(string fileName)
{
bool verbose = true;
if(verbose)
cout << "Entering getTokensFromFile(" << fileName << ")" << endl ;
/* declaring what we'll need :
* string line -> the line beeing parsed
* ifstream myfile -> the file that name has been given as parameter
* vector <vector <string> > tokens -> the return value
*
* Putting all line into tokens
*/
string line;
ifstream myfile(fileName);
vector< vector<string> > tokens;
if(verbose)
cout << "Opening file " << fileName << " ... ";
if (myfile.is_open())
{
if(verbose)
cout << "Done !" << endl;
while (getline (myfile,line))
{
if(verbose)
cout << "Parsing line '" << line << "'. ";
// If line is blank or start with # (comment)
// then we don't parse it
if((line.length() == 0) || (line.at(0) == '#'))
{
if(verbose)
cout << "Empty or comment, passing.";
continue;
}
else
{
vector <string> tmptokens;
if(verbose)
cout << "Adding token " << tmptokens[0] << " and its values.";
tokens.push_back(tmptokens);
}
cout << endl;
}
}
else
{
cout << "Unable to open file " << fileName << endl;
throw exception();
}
if(verbose)
cout << "Exiting getTokensFromFile(" << fileName << ")" << endl;
return tokens;
}
main.cpp
#include "parser.h"
int main()
{
getTokensFromFile("testfile.csv");
return 0;
}
And my testfile.csv
version;1.3
###### SPECIE ######
SpecieID;Value1
VariantID;Value2
####################
##### IDENTITY #####
Name;Value3
DOName;Value4
####################
All files are in the same folder.
Do you have any clue why I'm having this segfault?
Thanks
Here is one obvious error, where you are accessing a vector's element out-of-bounds. Accessing an out-of-bounds element is undefined behavior.
else
{
vector <string> tmptokens;
if(verbose)
cout << "Adding token " << tmptokens[0] << " and its values.";
tokens.push_back(tmptokens);
}
Since tmptokens is empty, there is no tmptokens[0].
If the vector is empty, you could have done this:
else
{
if(verbose)
cout << "Adding new token and its values.";
tokens.push_back({});
}
There is no need to manually create an empty vector starting with C++11.
Related
I'm trying to read in a fasta file. I want to remove/ignore the header/info lines that begin with ">" and store the following sequences into sperate strings. Below is the code I have to do that (partially reworked from https://rosettacode.org/wiki/FASTA_format#C++, as what I had originally worked even less). They have a good example of what I want to do.
My problem is given this fasta file:
">sequence_1
MSTAGKVIKCKAAVLWELHKPFTIEDIEVAPPKAHEVRIKMVATGVCRSDDHVVSGTLVTPLPAVLGHE
GAGIVEGVTCVKPGDKVIPLFSPQCGECRICKHPESNFCSRSDLLMPRGTLREGTSRFSCKGKQIHNFI
STSTFSQYTVVDDIAVAKIDGASPLDKVCLIGCGFSTGYGSAVKVAKVTPGSTCAVFGLGGVGLSVIIG
CKAAGAARIIAVDINKDKFAKAKELGATECIYSKPIQEVLQEMTDGGVDFSFEVIGRLDTMTSALLSCH
AACGVSVVVGVPPNAQNLSMNPMLLLLGRTWKGAIFGGFKSKDSVPKLVAKKFPLDPLITHVLPFEKIN
EAFDLLRSGKSIRTVLTF
">sequence_2
MNQGKVIKCKAAVLWEVKKPFSIEDVEVAPPKAYEVRIKMVAVGICHTDDHVVSGNLVTPLPVILGHEA
AGIVESVGEGVTTVKPGDKVIPLFTCRVCKNPESNYCLKNDLGNPRGTLQDGTRRFTCRGKPIHHFLGT
STFSQYTVVDENAVAKIDAASPLEKVCLIGCGFSTGYGSAVNVAKVTPGSTCAVFGLGGVGLSAVMGCK
AAGAARIIAVDINKDKFAKAKELGATECINPQDYKLPIQEVLKEMTDGSTVIGRLDTMMASLLCCGTSV
IVEDTPASQNLSINPMLLLTGRTWKGAVYGGFKSKEGIPKLVADFMAKKFSLDALITHVLPFEKINEGF
DLLHSGKSIRTVLTF
My output:
Sequence 1: MSTAGKVIKCKAAVLWELHKPFTIEDIEVAPPKAHEVRIKMVATGVCRSDDHVVSGTLVTPLPAVLGHEGAGIVEGVTCVKPGDKVIPLFSPQCGECRICKHPESNFCSRSDLLMPRGTLREGTSRFSCKGKQIHNFISTSTFSQYTVVDDIAVAKIDGASPLDKVCLIGCGFSTGYGSAVKVAKVTPGSTCAVFGLGGVGLSVIIGCKAAGAARIIAVDINKDKFAKAKELGATECIYSKPIQEVLQEMTDGGVDFSFEVIGRLDTMTSALLSCHAACGVSVVVGVPPNAQNLSMNPMLLLLGRTWKGAIFGGFKSKDSVPKLVAKKFPLDPLITHVLPFEKINEAFDLLRSGKSIRTVLTF
Sequence 2: MNQGKVIKCKAAVLWEVKKPFSIEDVEVAPPKAYEVRIKMVAVGICHTDDHVVSGNLVTPLPVILGHEAAGIVESVGEGVTTVKPGDKVIPLFTCRVCKNPESNYCLKNDLGNPRGTLQDGTRRFTCRGKPIHHFLGTSTFSQYTVVDENAVAKIDAASPLEKVCLIGCGFSTGYGSAVNVAKVTPGSTCAVFGLGGVGLSAVMGCKAAGAARIIAVDINKDKFAKAKELGATECINPQDYKLPIQEVLKEMTDGSTVIGRLDTMMASLLCCGTSVIVEDTPASQNLSINPMLLLTGRTWKGAVYGGFKSKEGIPKLVADFMAKKFSLDALITHVLPFEKINEGF
The last line or so of Sequence 2 is cut off..... Any help/solutions?
void read_in_Protein(string Protein_filename)
{ // read in the sequences
fstream myfile;
myfile.open(Protein_filename, ios::in);
if (!myfile.is_open()) {
cerr << "Error can not open file" << endl;
exit(1);
}
string Protein_Sequences{};
string Protein_Seq_names{};
// string temp{};
string Prot_Seq1{};
string Prot_Seq2{};
string line{};
while (getline(myfile, line).good()) {
//std::cout << "Line input received (" << line.length() << "): " << line << std::endl;
if (line.empty() || line[0] == '>') { // Identifier marker
if (!Protein_Seq_names.empty()) { // Print out what we read from the last entry
//std::cout << "\tReseting to new sequence" << std::endl;
// cout << Protein_Sequences << endl;
Protein_Seq_names.clear();
Prot_Seq1 = Protein_Sequences;
}
if (!line.empty()) {
//std::cout << "\tSetting sequence start" << std::endl;
Protein_Seq_names = line.substr(1);
}
// std::cout << "\tClearing sequences..." << std::endl;
Protein_Sequences.clear();
}
else if (!Protein_Seq_names.empty()) {
line = line.substr(0, line.length() - 1);
if (line.find(' ') != string::npos) { // Invalid sequence--no spaces allowed
//std::cout << "\tSpace found, clearing buffers..." << std::endl;
Protein_Seq_names.clear();
Protein_Sequences.clear();
}
else {
//std::cout << "\tAppending line to protein sequence..." << std::endl;
Protein_Sequences += line;
}
}
//std::cout << "Protein_Sequences: " << Protein_Sequences << std::endl;
}
if (!Protein_Seq_names.empty()) { // Print out what we read from the last entry
// cout << Protein_Sequences << endl;
Prot_Seq2 = Protein_Sequences;
}
cout << "\nSequence 1: " << Prot_Seq1 << endl;
cout << Prot_Seq1.length();
cout << "\nSequence 2: " << Prot_Seq2 << endl;
cout << Prot_Seq2.length();
}
Assuming your file doesn't end with a new line then the last call to std::getline will set the eof bit to indicate that it reached the end of the file before finding the line ending. As you are checking .good() in your while loop the last line will be discarded. You should instead check !fail() (or just the boolean value of the stream itself which is equivalent to !fail()):
while (getline(myfile, line))
After reading the final line the next iteration of the loop will try to read whilst the stream is in the eof state and immediately fail and break out of the loop.
I'm learning C++. I'm developing a simple "library management" application that allows users to create an account, check out books, etc. Each book is managed using a unique text file. The text file contains three lines as follows, however the third line is the only important thing here, as it contains the owner of the book.
The following code prints the contents of an additional text file that contains a list of all the books, but that shouldn't be relevant to the error. It converts the contents of the text file to a string, and then checks to see if "NA" is present. If "NA" is present, it is replaced with the current username. The file is then reopened using ios::trunc to wipe the file, and the new string is passed into the file. This works fine.
The issue is that when running the application, if a username is already there instead of "NA", I get a Debug Error that only reads abort() has been called. I've tried debugging, but I can't get any more information.
This is the error and the code:
void bookCheckout()
{
system("CLS");
string line;
string bookChoice;
ifstream checkBookList;
ofstream checkOutBook;
checkBookList.open("books/booklist.txt");
string sTotal;
string s;
cout << "<---Avaliable Books--->" << endl;
while (getline(checkBookList, line)) {
cout << line << endl;
}
checkBookList.close();
cout << "\nWhat Book Would You Like?:";
cin >> bookChoice;
checkBookList.open("books/" + bookChoice + ".txt");
while (!checkBookList.eof()) {
getline(checkBookList, s);
sTotal += s + "\n";
}
checkBookList.close();
if (sTotal.find("NA")) {
sTotal.replace(sTotal.find("NA"), 2, globalUsername);
checkOutBook.open("books/" + bookChoice + ".txt", ios::trunc);
checkOutBook << sTotal;
checkOutBook.close();
}
else if (!sTotal.find("NA")) {
cout << "Book already checked out!" << endl;
}
checkOutBook.close();
system("PAUSE");
}
There are a few issues with your code:
lack of error handling.
while (!checkBookList.eof()) - see Why is iostream::eof inside a loop condition (i.e. while (!stream.eof())) considered wrong?
if (sTotal.find("NA")) - string::find() returns an INDEX, not a BOOLEAN. If 0 is returned, that will be evaluated as false. All other values will be evaluated as true, including string::npos (-1), which is what string::find() returns if a match is not found.
Also, your goal is to check if the 3RD LINE SPECIFICALLY is "NA", so using string::find() is not the best choice for that purpose. Think of what would happen if the 1st or 2nd line happened to contain the letters NA. Your code logic would not behave properly.
else if (!sTotal.find("NA")) - no need to call find() in the else at all. Just use else by itself.
With that said, try something more like this:
void bookCheckout()
{
system("CLS");
ifstream checkBookList;
checkBookList.open("books/booklist.txt");
if (!checkBookList.is_open()) {
cerr << "Unable to open booklist.txt" << endl;
return;
}
string line;
cout << "<---Available Books--->" << endl;
while (getline(checkBookList, line)) {
cout << line << endl;
}
checkBookList.close();
cout << "\nWhat Book Would You Like?:";
string bookChoice;
getline(cin, bookChoice);
checkBookList.open("books/" + bookChoice + ".txt");
if (!checkBookList.is_open()) {
cerr << "Unable to open " + bookChoice + ".txt for reading" << endl;
return;
}
string sTotal, sOwner;
int lineNum = 0;
string::size_type ownerIndex = string::npos;
while (getline(checkBookList, line)) {
++lineNum;
if (lineNum == 3) {
sOwner = line;
ownerIndex = sTotal.size();
}
sTotal += line + "\n";
}
checkBookList.close();
if (sOwner == "NA") {
sTotal.replace(ownerIndex, 2, globalUsername);
ofstream checkOutBook("books/" + bookChoice + ".txt", ios::trunc);
if (!checkOutBook.is_open()) {
cerr << "Unable to open " + bookChoice + ".txt for writing" << endl;
return;
}
checkOutBook << sTotal;
checkOutBook.close();
cout << "Book checked out!" << endl;
}
else {
cout << "Book already checked out by " << sOwner << "!" << endl;
}
system("PAUSE");
}
Alternatively, use a std::vector to gather the book contents, that will give you indexed access to each line:
#include <vector>
void bookCheckout()
{
system("CLS");
ifstream checkBookList;
checkBookList.open("books/booklist.txt");
if (!checkBookList.is_open()) {
cerr << "Unable to open booklist.txt" << endl;
return;
}
string line;
cout << "<---Available Books--->" << endl;
while (getline(checkBookList, line)) {
cout << line << endl;
}
checkBookList.close();
cout << "\nWhat Book Would You Like?:";
string bookChoice;
getline(cin, bookChoice);
checkBookList.open("books/" + bookChoice + ".txt");
if (!checkBookList.is_open()) {
cerr << "Unable to open " + bookChoice + ".txt for reading" << endl;
return;
}
vector<string> sTotal;
sTotal.reserve(3);
while (getline(checkBookList, line)) {
sTotal.push_back(line);
}
while (sTotal.size() < 3) {
sTotal.push_back("");
}
checkBookList.close();
if (sTotal[2] == "" || sTotal[2] == "NA") {
sTotal[2] = globalUsername;
ofstream checkOutBook("books/" + bookChoice + ".txt", ios::trunc);
if (!checkOutBook.is_open()) {
cerr << "Unable to open " + bookChoice + ".txt for writing" << endl;
return;
}
for(size_t i = 0; i < sTotal.size(); ++i) {
checkOutBook << sTotal[i] << '\n';
}
checkOutBook.close();
cout << "Book checked out!" << endl;
}
else {
cout << "Book already checked out by " << sTotal[2] << "!" << endl;
}
system("PAUSE");
}
I've written a readFile function for a project I'm working on. I call it once, load in a file and read in it's contents - works fine
However, when I try to load it a second time, attempting to change the file name - it loads it in, saves it to a static string 'path' that I access in a different function - but then the function is not printing the data
The question is, how do I change the file name, and read it in successfully on the second iteration? The part that has me stumped is that it works once, but not twice
Ive attempted to use cin.ignore(); cin.clear(); cin.sync() on the second iteration of fileName function - but none of them allow a separate file to be read successfully.
Minimum Reproducible Example:
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <vector>
#include <sstream>
#include <iomanip>
#include <iostream>
using namespace std;
static string path;
string opt;
void readFile();
int fileName();
void menu() { // put in while loop - while True
cout << "----------------------" << endl;
cout << "R(ead) -" << "Read File" << endl;
cout << "F(ile) -" << "Set Filename" << endl;
cout << "\nPlease select from the above options" << endl;
cin >> opt;
cout << "\nInput entered: " << opt << endl;
if (opt == "R") {
readFile();
}
if (opt == "F") {
fileName();
}
}
void readFile() { // doing this twice
ifstream readFile;
readFile.open(path);
if (!readFile.is_open()) {
cout << "Could not read file" << endl;
}
string str;
int i = 0;
while (getline(readFile, str))
{
if (str[0] != '/')
{
cout << "DEBUG: Line is - " << str << endl;
}
}
readFile.clear();
readFile.close();
menu();
}
int fileName() {
cout << "File path: ";
if (path != "") {
cin.ignore();
cin.clear();
cin.sync();
}
getline(cin, path);
ifstream file(path.c_str());
if (!file) {
cout << "Error while opening the file" << endl;
return 1;
}
cout << "(File loaded)" << endl;
cout << "Path contains: " << path << endl;
file.clear();
file.close();
menu();
}
int main()
{
fileName();
}
Sample text, saved as txt file and read in using path:
Data1.txt
// standard test file
123,Frodo inc,2006, lyons,"1,021,000.16",0.0,
U2123,Sam Inc,2006, lyons,"21,600.00",13.10,123
A721,Merry Inc,2604, Kingston,"21,600.10",103.00,
U2122,Pippin Inc,2612, reid,"21,600.00",0
U1123,Huckelberry corp,2612, Turner,"21,600.00",13.10,
Data2.txt
7101003,Mike,23 boinig road,2615,48000,12000,0
7201003,Jane Philips,29 boinig cresent,2616,47000,12000,0
7301003,Philip Jane,23 bong road,2615,49000,000,0
7401004,Peta,23 bong bong road,2615,148000,19000,0
7101205,Abdulla,23 Station st,2615,80000,21000,0
The problem comes from reading in one, and trying to read in the other after the first has been executed.
Enter Filename
Hit Readfile
Return to menu, hit Set Filename
Change to Data2.txt
Readfile again. Not working
My tutor told me "That's not how functions work in c++" but didn't elaborate further, and is unavailable for contact.
In general, do not use global variables. The path variable should be passed as a parameter, not kept as a global variable altered between function calls, as this leads to many side effects and is the source of countless bugs. See the following refactoring:
void menu() { // put in while loop - while True
while(true)
{
//Keep this as a local variable!
std::string opt;
std::string filename;
cout << "----------------------\n";
cout << "R(ead) -" << "Read File\n";
cout << "F(ile) -" << "Set Filename\n";
cout << "\nPlease select from the above options\n";
cin >> opt;
cout << "\nInput entered: " << opt << '\n';
if (opt == "R") {
readFile(filename);
}
if (opt == "F") {
filename = getFileName();
}
}
}
void readFile(const std::string & filename) {
ifstream readFile;
readFile.open(filename);
if (!readFile.is_open()) {
cout << "Could not read file " << filename << '\n';
}
string str;
int i = 0;
while (getline(readFile, str))
{
if (str[0] != '/')
{
cout << "DEBUG: Line is - " << str << '\n';
}
}
readFile.close();
//just return to get back to menu
return;
}
std::string getFileName() {
cout << "File path: ";
std::string path;
getline(cin, path);
ifstream file(path.c_str());
if (!file) {
cout << "Error while opening the file" << '\n';
//Instead of returning an error code use an exception preferably
}
cout << "(File loaded)" << '\n';
cout << "Path contains: " << path << '\n';
file.close();
return path;
}
Other notes:
Ideally, do input in output in just one function, not all three as it gets confusing exactly what each function is responsible for.
If you want something to hold a file and print the contents, you can use an class.
The file is checked if it is openable twice, not really any reason to do this just delegate that responsibility to one function.
One of the best things about C++ is RAII and deterministic lifecycles for objects and primitives - use it!! Do not give everything a long life with global variables - use smart parameters and return values instead.
I am trying to do a problem using dynamic programming to find which items to select from a text file under a certain weight capacity while maximizing value. The file is in the format:
item1, weight, value
item2, weight, value
With a variable number of items. I am having a problem reading the file in the main method, where I am trying to error check for bad input. My problem comes from when I check if the weight is either missing, or is a string instead of an int. I can't figure out how to check separately for a string or if there is nothing in that spot. I am supposed to output a different error depending on which it is. Thanks.
int main(int argc, char * const argv[])
{
std::vector<Item> items;
if (argc != 3)
{
std::cerr << "Usage: ./knapsack <capacity> <filename>";
return -1;
}
int capacity;
std::stringstream iss(argv[1]);
if (!(iss >> capacity) || (capacity < 0))
{
std::cerr << "Error: Bad value '" << argv[1] << "' for capacity." << std::endl;
return -1;
}
std::ifstream ifs(argv[2]);
if (ifs.is_open())
{
std::string description;
unsigned int weight;
unsigned int value;
int line = 1;
while (!ifs.eof())
{
if (!(ifs >> description))
{
std::cerr << "Error: Line number " << line << " does not contain 3 fields." << std::endl;
return -1;
}
if (!(ifs >> weight))
{
if (ifs.eof())
std::cerr << "Error: Line number " << line << " does not contain 3 fields." << std::endl;
else
std::cerr << "Error: Invalid weight '" << ifs << "' on line number " << line << "." << std::endl;
return -1;
}
else if (!(ifs >> weight) || (weight < 0))
{
std::cerr << "Error: Invalid weight '" << ifs << "' on line number " << line << "." << std::endl;
return -1;
}
if (!(ifs >> value))
{
if (ifs.eof())
std::cerr << "Error: Line number " << line << " does not contain 3 fields." << std::endl;
else
std::cerr << "Error: Invalid value '" << ifs << "' on line number " << line << "." << std::endl;
return -1;
}
else if (!(ifs >> value) || (value < 0))
{
std::cerr << "Error: Invalid value '" << ifs << "' on line number " << line << "." << std::endl;
return -1;
}
Item item = Item(line, weight, value, description);
items.push_back(item);
line++;
}
ifs.close();
knapsack(capacity, items, items.size());
}
else
{
std::cerr << "Error: Cannot open file '" << argv[2] << "'." << std::endl;
return -1;
}
return 0;
}
I think better approach will be using getline function, by which you will take a whole line and then you can try to split it into three strings. If three parts are not found or any of the three parts is not in a right format you can output an error.
An example code is give below,
#include<fstream>
#include<iostream>
#include<vector>
#include <sstream>
#include<string>
using namespace std;
void split(const std::string &s, std::vector<std::string> &elems, char delim) {
elems.clear();
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim)) {
elems.push_back(item);
}
}
int main()
{
vector<string> elems;
ifstream fi("YOUR\\PATH");
string inp;
while(getline(fi, inp))
{
split(inp, elems, ' ');
if(elems.size() != 3)
{
cout<<"error\n";
continue;
}
int value;
bool isint = istringstream(elems[1])>>value;
if(!isint)
{
cout << "error\n";
continue;
}
cout<<"value was : " << value << endl;
}
return 0;
}
You could read the whole line at once and check it's format using regular expressions.
If you go in my post history you'll see that i'm trying to develop an interpreter for a language that i'm working on. I want to use size_t using two different codes, but they all return nothing.
Here is the post of what i was trying: http://stackoverflow.com/questions/1215688/read-something-after-a-word-in-c
When i try to use the file that i'm testing it returns me nothing. Here is the sample file(only a print function that i'm trying to develop in my language):
print "This is a print function that i'm trying to develop in my language"
But remember that this is like print in Python, what the user type into the quotes(" ") is what have to be printed to all, remember that the user can choose what put into the quotes, then don't put something like a simple cout, post something that reads what is inside the quotes and print it to all. But here is the two test codes to do this, but all of they don't returns nothing to me:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
int main( int argc, char* argv[] )
{
// Error Messages
string extension = argv[ 1 ];
if(argc != 2)
{
cout << "Error syntax is incorrect!\nSyntax: " << argv[ 0 ] << " <file>\n";
return 0;
}
if(extension[extension.length()-3] != '.')
{
cout << "Extension not valid!" << endl;
cout << "Default extension *.tr" << endl;
return 0;
}
if(extension[extension.length()-2] != 't')
{
cout << "Extension not valid!" << endl;
cout << "Default extension *.tr" << endl;
return 0;
}
if(extension[extension.length()-1] != 'r')
{
cout << "Extension not valid!" << endl;
cout << "Default extension *.tr" << endl;
return 0;
}
// End of the error messages
ifstream file(argv[ 1 ]);
if (!file.good()) {
cout << "File " << argv[1] << " does not exist.\n";
return 0;
}
string linha;
while (!file.eof())
{
getline(file, linha);
if (linha == "print")
{
size_t idx = linha.find("\""); //find the first quote on the line
while ( idx != string::npos ) {
size_t idx_end = linha.find("\"",idx+1); //end of quote
string quotes;
quotes.assign(linha,idx,idx_end-idx+1);
// do not print the start and end " strings
cout << "quotes:" << quotes.substr(1,quotes.length()-2) << endl;
//check for another quote on the same line
idx = linha.find("\"",idx_end+1);
}
}
}
return 0;
}
The second:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
int main( int argc, char* argv[] )
{
// Error Messages
string extension = argv[ 1 ];
if(argc != 2)
{
cout << "Error syntax is incorrect!\nSyntax: " << argv[ 0 ] << " <file>\n";
return 0;
}
if(extension[extension.length()-3] != '.')
{
cout << "Extension not valid!" << endl;
cout << "Default extension *.tr" << endl;
return 0;
}
if(extension[extension.length()-2] != 't')
{
cout << "Extension not valid!" << endl;
cout << "Default extension *.tr" << endl;
return 0;
}
if(extension[extension.length()-1] != 'r')
{
cout << "Extension not valid!" << endl;
cout << "Default extension *.tr" << endl;
return 0;
}
// End of the error messages
ifstream file(argv[ 1 ]);
if (!file.good()) {
cout << "File " << argv[1] << " does not exist.\n";
return 0;
}
string linha;
while (!file.eof())
{
getline(file, linha);
if (linha == "print")
{
string code = " print \" hi \" ";
size_t beg = code.find("\"");
size_t end = code.find("\"", beg+1);
// end-beg-1 = the length of the string between ""
cout << code.substr(beg+1, end-beg-1);
}
}
return 0;
}
And here is what is printed in the console:
ubuntu#ubuntu-laptop:~/Desktop/Tree$ ./tree test.tr
ubuntu#ubuntu-laptop:~/Desktop/Tree$
Like i said, it prints me nothing.
See my post in D.I.C.: http://www.dreamincode.net/forums/showtopic118026.htm
Thanks,
Nathan Paulino Campos
Your problem is the line
if (linha == "print")
which assumes the entire line just read in is "print", not that the line STARTS with print.
Also, why would you use 3 separate checks for a .tr extension, vs. just checking the end of the filename for ".tr"? (You should also be checking that argv[1] is long enough before checking substrings...)
getline(file, linha) will read an entire line from the file, so linha never be equal to print.