-1

I am trying to get this constructor to do these set of things:

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.

I am having trouble currently, when I try to run my program I get an error as it is not even reading my file and having trouble not understanding the problem. Any help would be appreciated thanks.

Constructor:

Message::Message(std::string filename) {
    fstream fin(filename);
    if (fin.fail())
    {
        cout << "failed";
    }
    else {
        length = getFileSize(fin);
        message = new char[length];
        fin.getline(message, length); {
            fin >> message;
        }
    }
    fin.close();
}

.h File:

#ifndef MESSAGE_H_
#define MESSAGE_H_

#include <fstream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>

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:
    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;
};

Here are my files:

OBJECT.CPP:

#include "Message.h"

using namespace std;

Message::Message(std::string filename) {
    fstream fin(filename);
    if (fin.fail())
    {
        cout << "failed";
    }
    else {
        length = getFileSize(fin);
        message = new char[length];
        fin.getline(message, length); {
            fin >> message;
        }
    }
    fin.close();
}

Message::~Message()
{
    //dtor
}
void Message::decode() {
    int offset;
    strcpy(code, "iztohndbeqrkglmacsvwfuypjx");
    for (int i = 0; i < strlen(message); i++) {
        if (message[i] == ' ') continue;
        if (message[i] == ',') continue;
        if (message[i] == '.') continue;
        offset = int(message[i] - 'a');
        message[i] = code[offset];
    }
}

void Message::fixCapitalization() {
    for (int i = 0; i < strlen(message); i++) {
        if (message[0] != ' ' || message[0] != ',') {
            message[0] = toupper(message[0]);
        }
        if (message[i] == '.' || message[i] == '?' || message[i] == ',') {
            message[i + 2] = toupper(message[i + 2]);
        }
    }
}

void Message::dump() const {
    for (int i = 0; i < strlen(message); i++) {
        cout << message[i];
    }
}

bool Message::isEmpty() const {
    if (length == 0) {
        return true;
    }
    else {
        return false;
    }
}

.H file:

/*
* Message.h
*
*  Created on: Dec 11, 2016
*      Author: hellenpacheco
*/

#ifndef MESSAGE_H_
#define MESSAGE_H_

#include <fstream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>

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;
};



#endif /* MESSAGE_H_ */

MAIN.CPP:

#include <iostream>
#include <stdlib.h>
#include <fstream>
#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())
    {
        cout << "Could not read message";
        return EXIT_FAILURE;
    }
    cout << "Original message: " << std::endl;
    m.dump();
    cout << std::endl << std::endl;
    m.decode();
    m.fixCapitalization();
    cout << "Decoded message: " << std::endl;
    m.dump();
    cout << std::endl << std::endl;

    return EXIT_SUCCESS;
}

The following file is the .txt file I am trying to open and "decode" and is all on 1 line:

ifqkwxcadf ar cei fpoi masif cd cei xkdqirr du pxxnwafm pf pnmdkaceo cd p oirrpmi, teaqe rqkpohnir cei gpcp af ac-oplafm ac sikw gauuaqvnc pfg caoi qdfrvoafm, au fdc xkpqcaqpnnw aoxdrrahni, cd gigvqi cei dkamafpn masif dfnw cei ifqdgig gpcp. afxvcr cd cei pnmdkaceo cwxaqpnnw afsdnsi pggacadfpn riqkic gpcp qpnnig liwr, teaqe xkisifcr cei oirrpmi ukdo hiafm giqdgig-isif au cei pnmdkaceo ar xvhnaqnw lfdtf.
Donald Duck
  • 8,409
  • 22
  • 75
  • 99
Max Millin
  • 9
  • 1
  • 3

1 Answers1

0

Problems with

    message = new char[length];
    fin.getline (message, length); {
        fin >> message;
    }
  1. getline will stop if a newline character is encountered.
  2. The fin >> message; line will overwrite what was read in getline.
  3. The { and } don't make sense at all. They are not problems per se but they lead me to think that you are not clear on what you are trying to do.

I would change those lines to

    message = new char[length + 1];  // Add an extra character if
                                     // message is supposed to be null
                                     // terminated.
    fine.read(message, length);
    message[length] = '\0';
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Ok, so I did those but now all I am getting is gibberish and they don't seem to be the length of the entire document. Since I know there is atleast 100+ chars I am just getting a garbage of 5-10 chars. – Max Millin Feb 25 '17 at 07:58
  • @MaxMillin, the problem could be related to [The Rule of Three](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three). – R Sahu Feb 25 '17 at 08:03
  • I'm still reading it so basically I have to write my destructor which could be causing the problem all together? – Max Millin Feb 25 '17 at 08:06
  • @MaxMillin, if you haven't written a destructor, there will be memory leaks but that won't corrupt live objects. – R Sahu Feb 25 '17 at 08:09
  • 1
    @MaxMillin Worse still, you leave your entire member variable set *uninitialized* if the file fails to open in your constructor, and no possible mechanism for the create of a `Message` to have any clue whatsoever that actually happened. Harden your code, and read up on the link provided about Rule-of-Three programming. Then, switch to RAII idioms by using `std::vector`, etc, and be glad rule-of-three is no longer a problem. – WhozCraig Feb 25 '17 at 10:14
  • @WhozCraig Why exactly would it matter if the variables are uninitialized if the file doesn't open? Since the file is opening shouldn't it at the very least store the .txt contents inside of the message pointer char? – Max Millin Feb 25 '17 at 20:45
  • 1
    It would *exactly* matter in the very case where the file does *not* open and process successfully. There is no way for the owner of a `Message` to know that. Further, if you do properly author a destructor and it `delete []`' s the member `message`, how *exactly* do you know what is being deleted? `message` could be *anything* including a valid pointer because the file processing worked, or *indeterminate* because file processing did *not* work. The point is, unless you *know* the value held by your data is reputable, taking action based on said-value is wrong. – WhozCraig Feb 26 '17 at 00:43