Reputation: 51
I have a project where I have to read from a text file and encode its contents using a Book Cipher. The first step I assume would be reading from two text files and count the page/line/column numbers(page numbers are determined by the delimiter '\f' and lines are determined by '\n'). However, I do not want the user to have to rename their file to "message.txt" everytime for the file to be read. Is there anyway for a C++ program to read any text files inputed by the user?
My current test program code:
#include <iostream> // Basic I/O
#include <string> // string classes
#include <fstream> // file stream classes
#include <sstream> // string stream classes
#include <locale> // locale class
using namespace std;
// version 0
int main() {
while (!cin.eof()) {
char ch;
cin >> ch;
cout << ch;
}
}
It gets everything from the file and outputs it correctly, however this way I can only accept one input file. I was hoping I can do something like this:
int main( int argc, char* argv[])
so:
argv[0] = program name
argv[1] = book cipher
argv[2] = message file
argv[3] = output file (encoded message goes here)
Is there a C++ version of this? I tried ifstream read(argv[1]), which did not work as I expected and it threw an exception. I feel like char* argv[] is something that is used in C, but not C++ as C++ has a string and strings are not a char array like in C. Wondering if someone could write me a sample just to see how the syntax work for this in C++.
And what which input function can I use to count escape characters such as '\n' and '\f'? I know from Java, I could use charAt() and do it in a loop or in C, it is just a char array. Input is really confusing for me in C/C++, I will keep looking at looking at tutorials on how these different functions work. Any ideas will be appreciated.
Upvotes: 0
Views: 565
Reputation: 15265
Your understanding of the main
parameters argc
and argv
is basically correct. What you will use as comand line arguments, will be the name of the files.
In order to work with them, you need to open the files with the given filenames, then you can extract data. To open an input file, you can use an std::ifstream
and use its constructor, where you pass the filename along. The boolean ! operator for the std::fstream
has been overwritten and will return the state (result) of the operation. Therefore you can write if (fileStream)
, to check, if the open operation was successfull.
For counting something, there are many possibilities. You can use standard algorithms.
Please see some example code below:
#include <iostream>
#include <fstream>
#include <string>
#include <iterator>
#include <algorithm>
int main(int argc, char* argv[]) {
// Check if the number of parameters are correct
if (4 != argc) {
// Wrong number of arguments, inform the user
std::cerr << "\n*** Wrong comand line parameters: please call with:\n"
<< "encode cipherFileName messageFileName outputFileName\n\n";
}
else
{
// Now, try to open all files. Open cipher file and check if this worked
if (std::ifstream cipherFileStream(argv[1]); cipherFileStream) {
// Open message file and check, if that worked
if (std::ifstream messageFileStream(argv[2]); messageFileStream) {
// And Open output file and check, if that worked
if (std::ofstream outputFileStream(argv[3]); outputFileStream) {
// Read the complete message file into one string
std::string messageData(std::istreambuf_iterator<char>(messageFileStream), {});
// Count some special charcters in the message file
size_t newLines = std::count(messageData.begin(), messageData.end(), '\n');
size_t formFeeds = std::count(messageData.begin(), messageData.end(), '\f');
// Show result to user
std::cout << "\nNew lines: " << newLines << "\nForm feeds: " << formFeeds << "\n";
}
else {
std::cerr << "\n*** Error: Could not open output file\n";
}
}
else {
std::cerr << "\n*** Error: Could not open message file\n";
}
}
else {
std::cerr << "\n*** Error: Could not open book cipher file\n";
}
}
return 0;
}
Upvotes: 1