Reputation: 29
For my C++ class our latest lab is to write a decoding program like so:
Write a program to read a file containing an encrypted message, which must be decoded and printed on the screen. Use the following key to decode: input text : abcdefghijklmnopqrstuvwxyz decoded text: iztohndbeqrkglmacsvwfuypjx
That means each 'a' in the input text should be replaced with an 'i', each 'b' with a 'z' and so forth. Punctuation and space should be kept as is. You will notice that all the letters in the text are lowercase, so the second step will be to fix the captalization. First letter of each sentence should be capitalized. Print the decoded text to the screen. You must use an object-oriented approach on this lab. The specification of class Message is given in header file Message.h. You need to implement each of the member functions in the Message.cpp, which you will turn in. The main function is also given so you can test your class, but you don't have to turn it in. I have added in the class definition in "Message.h" that explain how to implement each member function. Constructor: Should open the text file and determine its size. To do this, call getFileSize() which is implemented in "Message.h". Check for errors when opening the input file and don't forget to close it at the end. If there is an error, such as the file can't be located, make sure to set length to zero. Otherwise, use the file size to allocate space for message. Destructor: should free the space allocated for message.
decode: decodes the message according to the given key.
fixCapitalization: capitalizes the first letter of each sentence.
dump: prints the content of message on the screen
isEmpty: returns whether message is empty of not.
You only have to turn in message.cpp. You have to make sure it works with the header file that I'm providing, since it will be used to compile your message.cpp.
The header file provided was:
class Message
{
private:
char *message; // holds the message
int length; // holds the the message length
static const short ALPHABET_SIZE = 26;
char code[ALPHABET_SIZE]; // holds the cypher alphabet
// iztohndbeqrkglmacsvwfuypjx
// ex: an 'a' in the original message should be converted to 'i', 'b' should be converted to 'z' and so forth
// returns the input file size in bytes
std::streamsize getFileSize(std::fstream &file) const
{
std::streamsize fsize = 0;
file.seekg (0, std::ios::end);
fsize = file.tellg();
file.seekg (0, std::ios::beg); // moves file pointer back to the beginning
return fsize;
}
public:
/*
* This constructor tries to open the file whose name is passed
* to it in filename. If file opens successfully, calls function
* getFileSize to determine how many bytes should be allocated
* for the message. Allocates space for message and reads the
* content from the file into it. Closes the file at the end.
* Member variable length should be set to the file size.
* If file cannot be found, length should be set to zero.
*/
Message(std::string filename);
// The destructor frees the space allocated to message
virtual ~Message();
// Decodes the message
void decode();
// Capitalizes first letter in each sentence
void fixCapitalization();
// Prints the content of message on the screen
void dump() const;
// Returns true if the message is empty
bool isEmpty() const;
};
What I'm really stuck on is how to use a constructor to open the file, and read the size of it.
I can't even figure out how to open the file with the constructor at all.
I tried to use ifstream in my constructor like so:
Edited 2/24/17 10:36 a.m.:
#include <iostream>
#include <fstream>
#include <string>
#include "Message.h"
using namespace std;
int main()
{
// create a message object with the content of Encrypted.txt
Message m ("Encrypted.txt");
if (m.isEmpty())
{
std::cout << "Could not read message";
return EXIT_FAILURE;
}
std::cout << "Original message: " << std::endl;
m.dump();
std::cout << std::endl << std::endl;
m.decode();
m.fixCapitalization();
std::cout << "Decoded message: " << std::endl;
m.dump();
std::cout << std::endl << std::endl;
return EXIT_SUCCESS;
}
Message::Message(std::string filename)
{
fstream infile;
infile.open(filename.c_str(), std::ifstream::in);
// read contents
// close the file
if (!infile)
{
length=0;
}else
{
// getFileSize and allocate so much space for message
std::streamsize length = getFileSize(infile);
message = new char[length + 1];
//copy contents from file to message
for (int i = 0; i < length + 1; i++)
{
infile >> new char[i];
}
}
infile.close();
}
Message::~Message()
{
}
void Message::decode()
{
}
void Message::fixCapitalization()
{
}
void Message::dump() const
{
cout << message;
}
bool Message::isEmpty() const
{
if (length == 0)
{
return true;
}else
return false;
}
This is what I've put together so far. When I run the program it tells me "Could not read message" so I assume that the file was not opened properly. Can someone check over my code for me and tell me where I went wrong?
Upvotes: 2
Views: 576
Reputation: 1395
This should help you:
Message::Message(std::string filename)
{
std::ifstream infile;
infile.open(filename.c_str(), std::ifstream::in);
// read contents & initialize other member variables.
if (infile.is_open()) {
// getFileSize and allocate so much space for message
length = getFileSize(infile);
message = new char[length + 1];
//copy contents from file to message
}
// close the file finally
infile.close()
}
EDIT for usage
int main () {
Message m("Encrypted.txt");
// other operations on m
return 0;
}
Upvotes: 0
Reputation: 66371
char *message = new char;
*message = message[length];
allocates space for one char
, and then reads the invalid location message[length]
, which is undefined.
You need to allocate length + 1
characters.
I would write it like this:
Message::Message(std::string filename)
: message(nullptr),
length(0)
{
std::ifstream infile(filename);
if (infile)
{
length = getFileSize(infile);
message = new char[length + 1];
// ...
}
}
The destructor of std::ifstream
takes care of closing the stream if it was open, so you don't need to do that by hand. (Tell your teacher about this; they seem to be stuck in a C mindset.)
Side note: a more useful getFileSize
would restore the previous read position and not assume that it was at the beginning:
std::streamsize getFileSize(std::fstream &file) const
{
std::streamsize old_pos = file.tellg();
file.seekg (0, std::ios::end);
std::streamsize fsize = file.tellg();
file.seekg (old_pos, std::ios::beg); // moves file pointer back to the previous position
return fsize;
}
Upvotes: 1