fstream stops to read at substitute control character - c++

I'm writing a simple encryption program in C++ to encrypt a text-based file.
It's using a simple XOR cipher algorithm, but this produces ASCII control characters in the output file. When I try to read from the newly encrypted file with std::ifstream, it stumbles upon character #26, it stops and becomes unable to read the rest of the file.
Example if I try to encrypt this text:
This is just a simple sample
text with two rows and one sentence.
It turns it to this
/[[[[[
[[[ [[[U
When I try to read that file in my program, it can't read past the character at position 15, so I get a half encrypted file.
How can I fix this?
Here's the code:
#include <iostream>
#include <Windows.h>
#include <string>
#include <fstream>
void Encrypt(char encryptionKey, std::string filename)
{
std::ifstream sourceFile(filename);
std::ofstream outputFile(filename.substr(0, filename.find_last_of("\\")) + "\\Encrypted" + filename.substr(filename.find_last_of("\\") + 1), std::ofstream::out | std::ofstream::trunc);
std::string sourceLine;
std::string outputLine;
long numLines = 0;
if (sourceFile.is_open())
{
std::cout << "Opening file: " + filename + " for encryption" << std::endl;
while (sourceFile.good()) // This iterates over the whole file, once for each line
{
sourceLine = ""; //Clearing the line for each new line
outputLine = ""; //Clearing the line for each new line
std::getline(sourceFile, sourceLine);
for (int i = 0; i < sourceLine.length(); i++) // Looping through all characters in each line
{
char focusByte = sourceLine[i] ^ encryptionKey;
std::cout << " focusByte: " << focusByte << std::endl;
outputLine.push_back(focusByte);
//std::cout << sourceLine << std::flush;
}
numLines++;
outputFile << outputLine << std::endl;
}
}
sourceFile.close();
outputFile.close();
}
void Decrypt(unsigned int encryptionKey, std::string filename)
{
std::ifstream sourceFile(filename);
std::ofstream outputFile(filename.substr(0, filename.find_last_of("\\")) + "\\Decrypted" + filename.substr(filename.find_last_of("\\") + 1), std::ofstream::out | std::ofstream::trunc);
std::string sourceLine;
std::string outputLine;
long numLines = 0;
if (sourceFile.is_open())
{
std::cout << "Opening file: " + filename + " for decryption" << std::endl;
while (sourceFile.good()) // This iterates over the whole file, once for each line
{
if (sourceFile.fail() == true)
std::cout << "eof" << std::endl;
sourceLine = ""; //Clearing the line for each new line
outputLine = ""; //Clearing the line for each new line
std::getline(sourceFile, sourceLine);
for (int i = 0; i < sourceLine.length(); i++) // Looping through all characters in each line
{
char focusByte = sourceLine[i] ^ encryptionKey;
std::cout << " focusByte: " << focusByte << std::endl;
outputLine.push_back(focusByte);
}
numLines++;
outputFile << outputLine << std::endl;
}
}
sourceFile.close();
outputFile.close();
}
int main(int argument_count,
char * argument_list[])
{
system("color a");
std::string filename;
if (argument_count < 2)
{
std::cout << "You didn't supply a filename" << std::endl;
}
else
{
filename = argument_list[1];
std::cout << "Target file: " << filename << std::endl;
std::cout << "Press e to encrypt the selected file, Press d to decrypt the file > " << std::flush;
char choice;
while (true)
{
std::cin >> choice;
if (choice == 'e')
{
Encrypt(123, filename);
break;
}
else if (choice == 'd')
{
Decrypt(123, filename);
break;
}
else
{
std::cout << "please choose option e or d for encryption respectivly decryption" << std::endl;
}
}
}
std::cout << "\nPaused, press Enter to continue > " << std::flush;
system("Pause");
return EXIT_SUCCESS;
}

In Decrypt(), after the first call to std::getline(), sourceFile.good() is false and sourceFile.fail() is true, which is why you stop reading subsequent lines from the encrypted file.
The reason is because the encrypted file has an encoded 0x1A byte in it, and depending on your platform and STL implementation, that character likely gets interpreted as an EOF condition, thus enabling the std::ifstream's eofbit state, terminating further reading.
In my compiler's STL implementation on Windows, when std::ifstream reads from a file, it ultimately calls a function named _Fgetc():
template<> inline bool _Fgetc(char& _Byte, _Filet *_File)
{ // get a char element from a C stream
int _Meta;
if ((_Meta = fgetc(_File)) == EOF) // <-- here
return (false);
else
{ // got one, convert to char
_Byte = (char)_Meta;
return (true);
}
}
When it tries to read an 0x1A character, fgetc() returns EOF, and when _Fgetc() returns false, std::getline() sets the eofbit on the std::ifstream and exits.
Check your compiler's STL for similar behavior.
This behavior is because you are opening the encrypted file in text mode. You need to open the encrypted file in binary mode instead:
std::ifstream sourceFile(..., std::ifstream::binary);
Also, you should enable binary mode on the encrypted file in Encrypt() as well:
std::ofstream outputFile(..., std::ofstream::binary | std::ofstream::trunc);
Try something more like this instead:
#include <Windows.h>
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
void Encrypt(char encryptionKey, const std::string &filename)
{
std::string::size_type pos = filename.find_last_of("\\");
std::string out_filename = filename.substr(0, pos+1) + "Encrypted" + filename.substr(pos + 1);
std::ifstream sourceFile(filename.c_str());
std::ofstream outputFile(out_filename.c_str(), std::ofstream::binary | std::ofstream::trunc);
if (sourceFile.is_open())
{
std::cout << "Opened file: " + filename + " for encryption" << std::endl;
std::string line;
long numLines = 0;
while (std::getline(sourceFile, line)) // This iterates over the whole file, once for each line
{
for (std::string::size_type i = 0; i < line.length(); ++i) // Looping through all characters in each line
{
char focusByte = line[i] ^ encryptionKey;
std::cout << " focusByte: " << focusByte << std::endl;
line[i] = focusByte;
//std::cout << line << std::flush;
}
outputFile << line << std::endl;
++numLines;
}
}
}
void Decrypt(char encryptionKey, const std::string &filename)
{
std::string::size_type pos = filename.find_last_of("\\");
std::string out_filename = filename.substr(0, pos+1) + "Decrypted" + filename.substr(pos + 1);
std::ifstream sourceFile(filename.c_str(), std::ifstream::binary);
std::ofstream outputFile(out_filename.c_str(), std::ofstream::trunc);
if (sourceFile.is_open())
{
std::cout << "Opened file: " + filename + " for decryption" << std::endl;
std::string line;
long numLines = 0;
while (std::getline(sourceFile, line)) // This iterates over the whole file, once for each line
{
for (std::string::size_type i = 0; i < line.length(); ++i) // Looping through all characters in each line
{
char focusByte = line[i] ^ encryptionKey;
std::cout << " focusByte: " << focusByte << std::endl;
line[i] = focusByte;
}
outputFile << line << std::endl;
++numLines;
}
std::cout << "eof" << std::endl;
}
}
int main(int argument_count, char* argument_list[])
{
std::system("color a");
std::string filename;
if (argument_count < 2)
{
std::cout << "Enter a file to process: " << std::flush;
std::getline(std::cin, filename);
}
else
{
filename = argument_list[1];
}
if (filename.empty())
{
std::cout << "You didn't supply a filename" << std::endl;
return EXIT_FAILURE;
}
std::cout << "Target file: " << filename << std::endl;
std::cout << "Press e to encrypt the file" << std::endl;
std::cout << "Press d to decrypt the file" << std::endl;
char choice;
while (true)
{
std::cout << "> " << std::flush;
std::cin >> choice;
if (choice == 'e')
{
Encrypt(123, filename);
break;
}
else if (choice == 'd')
{
Decrypt(123, filename);
break;
}
else
{
std::cout << "please choose option e or d for encryption or decryption, respectively" << std::endl;
}
}
std::cout << std::endl << "Paused, press Enter to continue" << std::flush;
std::system("pause");
return EXIT_SUCCESS;
}
That being said, keep in mind that when using XOR, some of the encrypted characters might end up being \r (0x0D) or \n (0x0A), which will interfere with std::getline() when decrypting the file later on, producing a decrypted output that does not match the original text input.
Since you should be treating the encrypted file as binary, you should not be reading/writing the file as text at all. Choose a different format for your encrypted output that does not rely on line-break semantics in text vs binary mode.
For example:
#include <Windows.h>
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
void Encrypt(char encryptionKey, const std::string &filename)
{
std::string::size_type pos = filename.find_last_of("\\");
std::string out_filename = filename.substr(0, pos+1) + "Encrypted" + filename.substr(pos + 1);
std::ifstream sourceFile(filename.c_str());
std::ofstream outputFile(out_filename.c_str(), std::ofstream::binary | std::ofstream::trunc);
if (sourceFile.is_open())
{
std::cout << "Opened file: " + filename + " for encryption" << std::endl;
std::string line;
std::string::size_type lineLen;
long numLines = 0;
while (std::getline(sourceFile, line)) // This iterates over the whole file, once for each line
{
lineLen = line.length();
for (std::string::size_type i = 0; i < lineLen; ++i) // Looping through all characters in each line
{
char focusByte = line[i] ^ encryptionKey;
std::cout << " focusByte: " << focusByte << std::endl;
line[i] = focusByte;
//std::cout << line << std::flush;
}
outputFile.write((char*)&lineLen, sizeof(lineLen));
outputFile.write(line.c_str(), lineLen);
++numLines;
}
}
}
void Decrypt(char encryptionKey, const std::string &filename)
{
std::string::size_type pos = filename.find_last_of("\\");
std::string out_filename = filename.substr(0, pos+1) + "Decrypted" + filename.substr(pos + 1);
std::ifstream sourceFile(filename.c_str(), std::ifstream::binary);
std::ofstream outputFile(out_filename.c_str(), std::ofstream::trunc);
if (sourceFile.is_open())
{
std::cout << "Opened file: " + filename + " for decryption" << std::endl;
std::string line;
std::string::size_type lineLen;
long numLines = 0;
while (sourceFile.read((char*)&lineLen, sizeof(lineLen))) // This iterates over the whole file, once for each line
{
line.resize(lineLen);
if (!sourceFile.read(&line[0], lineLen))
break;
for (std::string::size_type i = 0; i < lineLen; ++i) // Looping through all characters in each line
{
char focusByte = line[i] ^ encryptionKey;
std::cout << " focusByte: " << focusByte << std::endl;
line[i] = focusByte;
}
outputFile << line << std::endl;
++numLines;
}
std::cout << "eof" << std::endl;
}
}
int main(int argument_count, char* argument_list[])
{
std::system("color a");
std::string filename;
if (argument_count < 2)
{
std::cout << "Enter a file to process: " << std::flush;
std::getline(std::cin, filename);
}
else
{
filename = argument_list[1];
}
if (filename.empty())
{
std::cout << "You didn't supply a filename" << std::endl;
return EXIT_FAILURE;
}
std::cout << "Target file: " << filename << std::endl;
std::cout << "Press e to encrypt the file" << std::endl;
std::cout << "Press d to decrypt the file" << std::endl;
char choice;
while (true)
{
std::cout << "> " << std::flush;
std::cin >> choice;
if (choice == 'e')
{
Encrypt(123, filename);
break;
}
else if (choice == 'd')
{
Decrypt(123, filename);
break;
}
else
{
std::cout << "please choose option e or d for encryption or decryption, respectively" << std::endl;
}
}
std::cout << std::endl << "Paused, press Enter to continue" << std::flush;
std::system("pause");
return EXIT_SUCCESS;
}

ASCII value 26 is EOF on some operating systems.
You should probably treat your encrypted file as a byte stream rather than a text file for reading and writing. That means either using read() and write() functions of the IOStream or at the very least opening the files in binary mode.
If you're just enciphering your text instead of encrypting, maybe choose a different cipher (eg. ROT13) that is closed on the set of printable ASCII or UTF-8 characters.

I compiled your code in Linux (minus all the Windows stuff)...
I get this when encrypting your sentence with your code:
/[[[[[
[[[ [[[U
It also decrypts back to the original sentence. Without the goofy characters, it is the same as your output so your actual issue seems related to the encoding of the file and the program you are using to view the results. Stephan is correct in saying you should be reading/writing bytes instead of text. This can cause all sorts of issues with the characters you create. For example, line feeds and carriage returns since you are using getline().
Edit: Strange. After editing this answer, all the odd characters disappeared. Here is a screenshot:

Related

Understanding ICU ubidi. Direction is always UBIDI_LTR

I have written a piece of sample code referring to ICU reference, to read a line from a file and get it's base direction and see the result of Unicode Bidi algorithm on it.
in my input file I have written فارسی which is a sequence of right to left characters.
but this line std::cout << ubidi_getBaseDirection(us.getBuffer(), us.length()) << std::endl; prints 0 which is UBIDI_LTR.
And no matter what combination of characters (RTL and LTR combinations) I give in the input file, it will always have one run with direction UBIDI_LTR.
Is there something wrong with my code?
#include "unicode/utypes.h"
#include "unicode/uchar.h"
#include "unicode/localpointer.h"
#include "unicode/ubidi.h"
#include <unicode/unistr.h>
#include<string>
#include<iostream>
#include <fstream>
#include "unicode/ustream.h"
using namespace icu;
using icu::UnicodeString;
int main(int argc, char* argv[])
{
std::string input;
std::string output;
std::ifstream MyReadFile("in.txt");
getline(MyReadFile, input);
UnicodeString us(input.c_str());
UBiDi* bidi = ubidi_open();
UErrorCode errorCode = U_ZERO_ERROR;
ubidi_setPara(bidi, us.getBuffer(), us.length(), UBIDI_RTL, nullptr, &errorCode);
std::cout << (ubidi_getBaseDirection(us.getBuffer(), us.length()) == UBIDI_LTR) << std::endl;
std::ofstream MyFile;
MyFile.open("out.txt");
if (U_SUCCESS(errorCode))
{
UnicodeString Ustring(ubidi_getText(bidi));
std::string Ustr;
Ustring.toUTF8String(Ustr);
int32_t count = ubidi_countRuns(bidi, &errorCode);
int32_t logicalStart, length;
if (count > 0)
MyFile << "VisualRun \t" << "direction" << "\t" << "s" << '\t' << "l" << '\t' << "output" << std::endl;
for (int32_t i = 0; i < count; i++) {
UBiDiDirection dir = ubidi_getVisualRun(bidi, i, &logicalStart, &length);
std::string dirstr = "UBIDI_LTR";
if (dir == UBIDI_RTL)
dirstr = "UBIDI_RTL";
UnicodeString temp = Ustring.tempSubString(logicalStart, length);
char* dest = (char*)malloc(temp.length());
temp.extract(logicalStart, length, dest, strlen(dest));
output = std::string(dest);
MyFile << "VisualRun \t" << dirstr << "\t" << logicalStart << '\t' << length << '\t' << output << std::endl;
}
}
else
{
std::cout << "Failed" << std::endl;
}
MyFile.close();
return 0;
}

Find specific lines in text document

I want to create small program to understand things I need better.
This code can write words to text document, new line under previous in sequential order and keep lines there after starting program again.
Now before adding a new word or phrase to the file, I want to find if the word already exists in my document, if exist, don't add it, but get exist equal one on output, read it from file, and main thing here is somehow also find line under or above current exist line. For example: if exist line index is 3, I want to see +1 line 4 or -1 line 2. If new word doesn't exist in text document just add it.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
std::ofstream outfile("doc.txt", std::ios_base::app);
int main()
{
std::string t;
for (int i = 0; i < 10; i++)
{
cout << "Add new phrase: " << endl;
std::getline(std::cin, t);
cout << t << endl;
outfile << t << std::endl;
}
_getch();
return 0;
}
EDIT:
using namespace std;
std::ofstream outfile("doc.txt", std::ios_base::app);
int main()
{
int length = 100;
std::ifstream infile("doc.txt", std::ifstream::in);
infile.seekg(0, infile.end);
size_t len = infile.tellg();
infile.seekg(0, infile.beg);
char *buf = new char[len];
infile.read(buf, length);
infile.close();
std::string writtenStr(reinterpret_cast<const char *>(buf), len);
std::string t;
for (int i = 0; i < 10; i++)
{
std::getline(std::cin, t);
if (writtenStr.find(t) != std::string::npos)
{
cout << "Line [" << t << "] exist." << endl;
}
else
{
cout << "Line [" << t << "] saved." << endl;
writtenStr += t;
outfile << t << std::endl;
}
}
_getch();
return 0;
}
I'd read the file into a string when the program starts. Then, check the string for the phrase each time i want to add a new word. If the string doesn't contain the phrase, add it to the string and the file, and a delimiter of your choice if desired. For example:
int main()
{
// Read existing file into a string
std::ifstream infile("doc.txt", std::ifstream::in);
infile.seekg(0, infile.end);
size_t len = infile.tellg();
infile.seekg(0, infile.beg);
char *buf = new char[len];
infile.read(buf,length);
infile.close();
std::string writtenStr(reinterpret_cast<const char *>(buf), len);
// Open file for output
std::ofstream outfile("doc.txt", std::ios_base::app);
std::string t;
for (int i = 0; i < 10; i++)
{
// Get new phrase
std::getline(std::cin, t);
// Check if phrase is already in file;
if (writtenStr.find(t) == std::string::npos)
{
cout << "Could not add new phrase: " << endl;
cout << t << endl;
cout << "Phrase already exists in file." << endl;
}
else
{
cout << "Add new phrase: " << endl;
cout << t << endl;
writtenStr += t;
outfile << t << std::endl;
}
}
_getch();
return 0;
}

Where can I use OpenMP in my C++ code

I am writing a C++ code to calculate the code coverage and I want to used the OpenMP to help enhance my code by minimizing the overall run time by making the functions work in parallel so I can get less run time.
Can someone please tell me how and where to use the OpenMP?
int _tmain(int argc, _TCHAR* argv[])
{
std::clock_t start;
start = std::clock();
char inputFilename[] = "Test-Case-3.cs"; // Test Case File
char outputFilename[] = "Result.txt"; // Result File
int totalNumberOfLines = 0;
int numberOfBranches = 0;
int statementsCovered = 0;
float statementCoveragePercentage = 0;
double overallRuntime = 0;
ifstream inFile; // object for reading from a file
ofstream outFile; // object for writing to a file
inFile.open(inputFilename, ios::in);
if (!inFile) {
cerr << "Can't open input file " << inputFilename << endl;
exit(1);
}
totalNumberOfLines = NoOfLines(inFile);
inFile.clear(); // reset
inFile.seekg(0, ios::beg);
numberOfBranches = NoOfBranches(inFile);
inFile.close();
statementsCovered = totalNumberOfLines - numberOfBranches;
statementCoveragePercentage = (float)statementsCovered * 100/ totalNumberOfLines;
outFile.open(outputFilename, ios::out);
if (!outFile) {
cerr << "Can't open output file " << outputFilename << endl;
exit(1);
}
outFile << "Total Number of Lines" << " : " << totalNumberOfLines << endl;
outFile << "Number of Branches" << " : " << numberOfBranches << endl;
outFile << "Statements Covered" << " : " << statementsCovered << endl;
outFile << "Statement Coverage Percentage" << " : " << statementCoveragePercentage <<"%"<< endl;
overallRuntime = (std::clock() - start) / (double)CLOCKS_PER_SEC;
outFile << "Overall Runtime" << " : " << overallRuntime << " Seconds"<< endl;
outFile.close();
}
i want to minimize the time taken to count the number of branches by allowing multiple threads to work in parallel to calculate the number faster? how can i edit the code so that i can use the open mp and here you can find my functions:bool is_only_ascii_whitespace(const std::string& str)
{
auto it = str.begin();
do {
if (it == str.end()) return true;
} while (*it >= 0 && *it <= 0x7f && std::isspace(*(it++)));
// one of these conditions will be optimized away by the compiler,
// which one depends on whether char is signed or not
return false;
}
// Function 1
int NoOfLines(ifstream& inFile)
{
//char line[1000];
string line;
int lines = 0;
while (!inFile.eof()) {
getline(inFile, line);
//cout << line << endl;
if ((line.find("//") == std::string::npos)) // Remove Comments
{
if (!is_only_ascii_whitespace(line)) // Remove Blank
{
lines++;
}
}
//cout << line << "~" <<endl;
}
return lines;
}
// Function 2
int NoOfBranches(ifstream& inFile)
{
//char line[1000];
string line;
int branches = 0;
while (!inFile.eof()) {
getline(inFile, line);
if ((line.find("if") != std::string::npos) || (line.find("else") != std::string::npos))
{
branches++;
}
}
return branches;
}

Reading from a file C++ Ifstream

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.

Issue regarding size_t

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.