Sorry, but I REALLY don't understand what could possibly be wrong with my code (or maybe it's not my code?).

When I run the writeChar(char*,char) function, my program crashes. I really don't have any idea why, as my pointers (I think, I've checked, but I'm not very good at that) are all initialized by the control reaches the writeChar function.

My code is below.

Functions.h:

#pragma once
#include <fstream>
#include <string.h>
#define nullptr 0
using namespace std;
char newline = '\n';
char supportedChars[] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','x','y','z', \
                         'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','X','Y','Z', \
                         '1','2','3','4','5','6','7','8','9','0' \
                         ,newline,'\t','\\','/','.',',','?','!','@','#','$','%','^','&','*','(',')','-','_','=','+','~','`','<','>','{','[','}',']', '\0'
                        };
class info
{
public:
    bool eof;
    bool good;
    bool fail;
    bool bad;
    char r;
};
info getNextChar(char* to);//read the next char in binary form.
void writeChar(char* to,char x);//writes to the write buffer.
void flush(char* to) {} //writes to the file, and cleans up (if needed)
char rotate(char x);//checks that it's supported, and increments it 13 times.
void all();


char rotate(char x) //Done -- works
{
    //No need to check them, as the char type suppots all (?)
    return (x+13);
}
ifstream& openFile(char* pszFileName)//utility -- works
{
    ifstream* pFileStream = nullptr;
    pFileStream = new ifstream(pszFileName);
    if (pFileStream->good())
    {
        pFileStream->seekg(0);
    }
    return *pFileStream;
}
ofstream& openFile2(char* pszFileName)//utility -- works
{
    ofstream* pFileStream = nullptr;
    pFileStream = new ofstream(pszFileName);
    return *pFileStream;
}
info getNextChar(char* to)//Works
{
    static ifstream& in= openFile(to);
    char r;
    in>>r;
    if(in.good() == false)
        cerr<<"Note that the file open with errors, or some other part of it completed with errors."<<endl;
    info i;
    i.eof = in.eof();
    i.good = in.good();
    i.fail = in.fail();
    i.bad = in.bad();
    i.r = r;
    return i;
}
void writeChar(char* to, char x)
{
    char* dest = "2";
     strcat (dest,to);
     cout<<"writing to file: "<<dest<<endl;
    static ofstream& in = openFile2(to);
    in << x;
}
void all(char* to)
{
    info i;
    bool good;
    //loop through all of the chars.
 writeChar(to, 'w');
 }

main.cpp

#include <iostream>
//#include <stdio.h>
//#include <stdlib.h>
#include "Functions.h"
#define nullptr 0
using namespace std;

int main(/*int nNumberOfArgs, char* pszArgs[]*/)
{
    char* pszArgs[] = {"NAME","Test.txt"};
    cout<<"Encrypt Using ROT13"<<endl;
    cout<<"Rotate file: "<<pszArgs[1]<<"\n[Y/N] >";
    char yn;
    cin>> yn;
    if(yn == 'Y'|| yn == 'y')
    {
//Yes
//run the rotation
        all(pszArgs[1]);
    }
    else
    {
        char* path = nullptr;
        cout<<"You have entered no.\nPlease enter correct file. Enter '0' to exit\n>";
        cin >> path;
        if(path == "0"||path == "'0'")
        {
            flush(pszArgs[1]);
            cout<<"Exiting. Please note that the program has not encrypted anything yet."<<endl;
            // exit(2);//exits with code 2, meaning that this option was used.
        }

//re-run the check.
        bool yes = false;
        while(!yes)
        {
            cout<<"Rotate file: "<<pszArgs[1]<<"\n[Y/N] >";
            cin >> yn;
            if(yn == 'Y'|| yn == 'y')
            {
//Yes
//run the rotation
                yes =true;
                all(pszArgs[1]);
            }
            else
            {
                yes = false;
                continue;
            }
        }
    }
}

This is meant to be a very simple ROT13 program. (Meaning that to encrypt a file, it rotates all of the chars 13 spots.)

Another strange thing is that when I do certain things (can't find the source of the problem here), Windows opens up and says that it can't find a certain dll. The dll is related to g++, my compiler (well, MinGW, but that's just a port of g++ so...).

The whole supported chars but is useless... I really don't know why I made it... took me forever!

Thanks,
Jack

Recommended Answers

All 11 Replies

char* dest = "2";
strcat (dest,to);

You're trying to write over memory that isn't yours to write over. See that "2"? All the memory next to it that you're trying to write over isn't yours. When you use strcat to concatenate two C-style strings, it is up to you to make sure that all the memory next to the string at dest, that will be overwritten, is yours to write over.

Oh... that would make sense.

So, can I resize dest to meet the new size requirements?

Seems like you're writing too much before testing. Write and debug no more than 1 function, or subroutine of a function, at a time.

In your code main() calls all() which calls writeChar() which calls openFile2() which doesn't call anything, so nothing gets done.

You should be able to do this with one call to ifstream and ofstream and no need for static on anything.

Anything you create like this: "some text", is a string literal. It's buried somewhere in a section of memory that you are forbidden from messing with. You can't even write over that text.

If you want to concatenate strings, I suggest that you either:

1) Use proper C++ style strings so that you can just do

concatenatedString = string1 +string2;

or 2)

If you want to use C-style arrays of char, you'll have to allocate a big array up front for dest. Big enough to hold everything, no matter how big what you're concatenating is. There are a number of safer options; strncat, for example, which will stop you writing off the end of the array.

I suggest you go with option one.

Thanks @Moschops !
You suggestion seems to be working.
I do have one question: Is a string allowed to be a parameter to main()?

Right now I'm just defining in main, and not bothering with the arguments.

Thanks,
Jack

The one problem that I have found is that opening the ifstream and ofstream objects is not allowed when using strings.

Is there any way to convert a string to char*.

I have yet to search on Google, so the answer may be very simple.

Is a string allowed to be a parameter to main()?

The short answer is no, just an int and some char pointers in an array.

The longer answer is it's pretty unlikely. The C++ standard mandates that the following two must be acceptable:

int main()
int main(int argc, char* argv[])

It states that main "shall have a return type of type int, but otherwise its type is implementation-defined." It's not impossible, thus that an implementation could accept
int main(string someString)
but it's really unlikely and would be dangerously non-portable and would exist only as some whacky extension on some crazy compiler.

Is there any way to convert a string to char*.

std::string aStringObject("Some letters");
const char* p = aStringObject.c_str();

I think it's time you looked at what a proper grown-up C++ string can do for you; http://www.cplusplus.com/reference/string/string/

Wow, do you guys type fast or what!

To address the last (non-)question first, you could use the predicates from <cctype> to check the characters if you really needed to. You'd probably have to check against a few different things to get exactly the character set you were looking for.

On a side note, with a modern C++ compiler, you want to use <cstring> rather than <string.h> . Just something to note for the future.

A second side note: #pragma statements are compiler-specific, and the once pragma in particular is specific to Visual C++ and GCC. While I don't believe it causes any warnings to come up under other compilers, it also won't have any effect under most of them, either. The usual solution to the multiple inclusion problem is to use include guards, instead. (It's not a big deal, but you should be aware of it.)

A further side note would be that you should separate the declarations of your class member functions from the implementation, preferably in different files, except for very simple (one or two line) functions. This does mean that you'd need to link in the *.cpp files to your main.cpp program file when you go to compile the program, but this shouldn't be difficult. This would give you the following files:

info.h

#pragma once

#define nullptr 0

class info
{
public:
    bool eof;
    bool good;
    bool fail;
    bool bad;
    char r;

    static info getNextChar(char* to);//read the next char in binary form.
    static void writeChar(char* to,char x);//writes to the write buffer.
    static void flush(char* to); //writes to the file, and cleans up (if needed)

    static char rotate(char x)    // short enough to be inline with no problem
    {
        return (x+13);
    };

    static void all(char* to);

private:
    static std::ifstream& openFile(char* pszFileName);
    static std::ofstream& openFile2(char* pszFileName);
};

info.cpp

#include <iostream>
#include <fstream>
#include <cstring>
#include "info.h"

std::ifstream& info::openFile(char* pszFileName)//utility -- works
{
    std::ifstream* pFileStream = nullptr;
    pFileStream = new std::ifstream(pszFileName);
    if (pFileStream->good())
    {
        pFileStream->seekg(0);
    }
    return *pFileStream;
}


std::ofstream& info::openFile2(char* pszFileName)//utility -- works
{
    std::ofstream* pFileStream = nullptr;
    pFileStream = new std::ofstream(pszFileName);
    return *pFileStream;
}


info info::getNextChar(char* to)//Works
{
    static std::ifstream& in = openFile(to);
    char r;
    in>>r;
    if(in.good() == false)
        std::cerr<<"Note that the file open with errors, or some other part of it completed with errors."<<std::endl;
    info i;
    i.eof = in.eof();
    i.good = in.good();
    i.fail = in.fail();
    i.bad = in.bad();
    i.r = r;
    return i;
}


void info::writeChar(char* to, char x)
{
    char* dest = "2";
    strcat (dest, to);
    std::cout << "writing to file: "<< dest << std::endl;
    static std::ofstream& in = openFile2(to);
    in << x;
}


void info::flush(char* to)
{
    return;    // do nothing for now
}


void info::all(char* to)
{
    info i;
    bool good;
    //loop through all of the chars.
    writeChar(to, 'w');
}

main.cpp

#include <iostream>
#include "info.h"

using namespace std;

int main(/*int nNumberOfArgs, char* pszArgs[]*/)
{
    char* pszArgs[] = {"NAME","Test.txt"};
    cout<<"Encrypt Using ROT13"<<endl;
    cout<<"Rotate file: "<<pszArgs[1]<<"\n[Y/N] >";
    char yn;
    cin>> yn;

    if(yn == 'Y'|| yn == 'y')
    {
//Yes
//run the rotation
        info::all(pszArgs[1]);
    }
    else
    {
        char* path = nullptr;
        cout<<"You have entered no.\nPlease enter correct file. Enter '0' to exit\n>";
        cin >> path;
        if(path == "0"||path == "'0'")
        {
            info::flush(pszArgs[1]);
            cout<<"Exiting. Please note that the program has not encrypted anything yet."<<endl;
            // exit(2);//exits with code 2, meaning that this option was used.
        }

//re-run the check.
        bool yes = false;
        while(!yes)
        {
            cout<<"Rotate file: "<<pszArgs[1]<<"\n[Y/N] >";
            cin >> yn;
            if(yn == 'Y'|| yn == 'y')
            {
//Yes
//run the rotation
                yes =true;
                info::all(pszArgs[1]);
            }
            else
            {
                yes = false;
                continue;
            }
        }
    }
}

If you are using an IDE such as Dev-C++ or Code::Blocks, then you can put the *.cpp files in your Project and they will be included automatically.

Finally, you generally don't want to use the using namespace std; directive in a header file, as it then gets set for every file that includes that header.

None of this, sadly, addresses the problem you actually were having, at least not directly. But they are all things you ought to learn about.

OK, I've realized since posting that that you didn't intend for those functions to be part of info ; sorry if I confused you in any way.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.