User creating txt files.

I've been working with text files for a bit and I am wondering if there is a more efficient way for the user opening a txt file.


1
2
3
4
5
6
7
8
9
10
11
12
13
#include <fstream>
using namespace std;

int main() {
    char filename[15];
    cout << "input file name" << endl;
    cin >> filename;
    
    ifstream file;
    file.open(filename);
    
    return 0;
}


The problem here is that the user has to write filename.txt
If the user is unaware then it wouldn't work.

I don't know if I can do something similar to this, but what ever I've previously tried hasn't worked.
 
    file.open(filename, ".txt");



My current method that works is to add the .txt onto the array of characters like so:

1
2
3
4
5
6
7
8
9
10
11

    char txt[] = ".txt";
    for (int i = 0; i < 15; i++) {
        if (filename[i] == '\0') {
            for (int j = 0; j < 4; j++) {
                filename[i] = txt[j];
                i++;
            }
            break;
        }
    }


This looks very confusing and inefficient. If anyone has a more convenient way to perform this trick that would be great. Thanks for any help!
If you really wanted to do it with low-level C-style char arrays then you could do it like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstring>

int main() {
    char filename[200]; // no need to be stingy
    std::ifstream file;

    while (true) {
        std::cout << "Filename: ";

        // fgets is the proper way to read a line of text (possibly
        // containing spaces) into a C-style char array without the
        // possibility of overflowing it. If the user enters the EOF
        // char from the terminal (Ctrl-Z in Windows, Ctrl-D otherwise)
        // then we quit.
        if (!std::fgets(filename, sizeof filename - 4, stdin)) {
            std::cout << "Quitting\n";
            return 0;
        }

        // But fgets leaves the newline at the end of the string
        // so we need to remove it.
        char *p = std::strchr(filename, '\n');
        if (p) *p = '\0';

        // strcat concatenates a c-style string onto another c-style string.
        // We left at least 4 chars in the array to have room for ".txt"
        std::strcat(filename, ".txt");

        file.open(filename);
        if (file) break;

        std::cerr << "Can't open " << filename << '\n';
    }

    std::cout << "Opened " << filename << '\n';
    //...
}

But in C++ we have the good fortune of having the std::string class, so we can do it like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <fstream>
#include <string>

int main() {
    std::string filename;    
    std::ifstream file;

    while (true) {
        std::cout << "Filename: ";

        // getline is the proper way to read a line of text (possibly
        // containing spaces) into a C++ style string. The string will
        // automatically grow to the required size. If the user enters
        // the EOF char from the terminal, we quit.
        if (!getline(std::cin, filename)) {
            std::cout << "\nQuitting\n";
            return 0;
        }

        // We can use the overloaded += operator to concatenate to
        // a C++ string.
        filename += ".txt";

        file.open(filename);
        if (file) break; // if no errors, then the file was found and opened.

        std::cerr << "Can't open " << filename << '\n';
    }

    std::cout << "Opened " << filename << '\n';
    //...
}

Last edited on
the trouble with this is that about 50% or more of all text files do not end in txt :) I have .dat, .sql, .cpp, .c, .asm, and about 200 other text file extensions. I just associate the extension with the editor I want so double click works, but I would't want notepad++ taking x.cpp and changing that to x.cpp.txt then telling me it did not exist.

so for the original C version, at the very least I would do something like
char *cp;
cp = strstr(filename, "."); //c++ string uses find() for this idea
if(cp)
///open filename
else
//open filename + .txt added.

even that is an issue if you have extensionless text files, but its one idea.
another idea would be to attempt to open filename, and if that fails, *then* try to open filename with .txt added. Every solution will fail for some scenario because you are fixing a non-issue with an assumption, though, so be aware of that.

You may want to know the C version just in case you use argv as the filename. You can stuff that into a c++ string, but there comes a point when avoiding a line or two of C just to avoid a line or two of C is kinda silly.
Last edited on
Topic archived. No new replies allowed.