3

So, I'm currently writing a line editor as a learning project on I/O, writing files, and the like. It is written in C++, and I am currently trying to write out to a file of the user's choosing. I have CLI arguments implemented, but I currently have no idea how to implement an in program way of specifying the file to write to.

char *filename;
if (argc >= 2){
        filename = argv[1];
} else{
        cout << "file>";
        cin >> filename;
        cin.ignore();
}

This works perfectly well when I use command line arguments; however, whenever I do not, as soon as I start the program, it Segmentation Faults. The place where I use the actual filename is in the save command:

void save(char filename[], int textlen, string file[]){
        ofstream out(filename);
        out << filestring(textlen, file);
        out.close();
}

Which also works perfectly well. Is there any way you can help me? Full source code, for review, is up on https://github.com/GBGamer/SLED

ubsan
  • 70
  • 1
  • 6
  • 1
    Use [`std::string`](http://en.cppreference.com/w/cpp/string/basic_string) and [read this](http://chris-sharpe.blogspot.co.uk/2013/05/reading-input-with-stdgetline.html) (self plug). – BoBTFish Jul 06 '13 at 08:20
  • The problem is that ofstream, if I remember correctly, cannot use strings as an input. Do you have any alternatives that do use strings? – ubsan Jul 06 '13 at 08:23
  • 1
    string has a conversion function `c_str()` which returns type const char *. – suspectus Jul 06 '13 at 08:25

2 Answers2

2

The problem is that char* filename is just a pointer to some memory containing characters. It does not own any memory itself. When you use the command line argument, the program handles storing that string somewhere, and you get a pointer to it. When you try to read using cin >> filename there isn't actually anywhere to store the read data.

Solution: Replace char* filename with std::string filename (and #include <string>).

Then to open the output file, you need a c-style string (null terminated char array). std::string has a function for this. You would write

std::ofstream out(filename.c_str());
                           ^^^^^

Or, in fact, if you can use a recent compiler with c++11 features, you don't even need to use c_str(). A new std::ofstream constructor has been added to accept a std::string.

BoBTFish
  • 19,167
  • 3
  • 49
  • 76
  • But what about using ofstream? Is there an alternative that allows strings? EDIT: Never mind, saw suspectus. – ubsan Jul 06 '13 at 08:25
-1

Your filename variable points to argv[1] when command line argument is provided, it does not need memory to be allocated but when going in else block, you have not allocated memory to filename. Its just a pointer.

Use malloc to assign filename some memory then take user input.

filename = (char *)malloc(sizeof(char)*(FILE_NAME_LENGTH+1))
Shashwat Kumar
  • 5,159
  • 2
  • 30
  • 66
  • 1
    Whoa, whoa, whoa! Seriously? You think the best solution for someone who has just started learning to handle input is manual memory management with `malloc`? – BoBTFish Jul 06 '13 at 08:32
  • 1
    I think someone learns C before using functions of std namespace. I learnt malloc long before using std::string and such thing. If someone is getting segmentation fault, you cant avoid explanation of memory if reason is to be told. And just allocating memory to some pointer variable is not a mammoth in manual memory management. – Shashwat Kumar Jul 06 '13 at 08:38
  • That's kind of saying you should learn to write `std::string` before learning to use it. And while I agree `new`/`delete`/`RAII` should be learned about fairly early on, they are quite separate from the nicest ways to deal with user interaction. And your answer (and don't take that personally, I mean anything short enough to be an SO answer) is nowhere near detailed enough to do anything but cause confusion in regards to these topics. – BoBTFish Jul 06 '13 at 08:49