Page 1 of 2 12 Last
  • Jump to page:
    #1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    31
    Rep Power
    1

    Class that read file and put them in a string


    Hello
    I'm new to C++ so I'm reading a book called "Thinking in C++" and they ask me to do one exercice, it's creating a text class which got a string called content with a constructor that takes the name of a file in the same repertory of the .exe, copy all the "content" of the file to the string content of the text object, and then showing in the console output the string content of the text object using a getter function.

    The problem is that we can't put strings in constructor of ifstream, they ask to put a char *... In the file fstreams.h, they say I need to convert the string into a char * and use strcopy.
    Even after using strcpy, the file can't be found...
    Here's my program :

    Code:
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <string.h>
    
    using namespace std;
    
    class Text
    {
        public:
    
        Text();
        Text(string fileName);
        ~Text();
        void setFileContent(string content);
        string contents();
    
        private:
    
        string fileContent;
    };
    
    int main()
    {
        Text filetest("essai.txt");
        cout << filetest.contents() << endl;
        return 0;
    }
    
    Text::Text(string fileName)
    {
        char * afileName = new char[fileName.length()+1];
        strcpy(afileName, fileName.c_str());
    
        string line;
        ifstream inputf;
        inputf.open(afileName);
        if(!inputf.eof())
        {
            cout << "Failed to open the file !" << endl;
        }
        else
        {
            while(getline(inputf, line))
            {
            setFileContent(line);
            }
        }
    }
    
    Text::Text()
    {
        cout << "Making a new instance of Test." << endl;
    }
    
    Text::~Text()
    {
        cout << "Destroying an instance of Test." << endl;
    }
    
    void Text::setFileContent(string content)
    {
        fileContent += content;
    }
    
    string Text::contents()
    {
        return fileContent;
    }
    Could you also tell me if I'm writing good C++.
    Thanks in advance ! :)
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    Two questions:

    1. Does a file named "essai.txt" exist?

    2. Where does it exist?

    You are telling your program to look in the current working directory for that file. Do you know what your current working directory is?

    I forget what you're running (Orwell Dev-C++, hence Windows?). Write and run another short program that creates a short text file. Then use Windows Explorer or the equivalent to look for that file. It should be in the same directory as your program's .EXE file. That would be the program's current working directory. It should either be the same directory as the project or a sub-directory of it.

    There are other ways of figuring that out. The main idea is that once you've figured out how your IDE designates the current working directory then you can use that knowledge to position your data files where they need to be.
  4. #3
  5. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,377
    Rep Power
    1871
    Code:
        strcpy(afileName, fileName.c_str());
    
        string line;
        ifstream inputf;
        inputf.open(afileName);
    Did you try this?
    inputf.open(fileName.c_str());

    > if(!inputf.eof())
    This isn't how you test to see if a file was opened successfully.

    Try
    if ( ! inputf )
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    31
    Rep Power
    1
    @salem : I had seen what I wrote on cplusplus.com, I guess that works too (and for the !inputf its what I had done before too, just tried to change, it works too normally).

    @dwise as I said before it IS in the same repertory of the .exe and yes it exists... :(
    And as you know because of my last topic I already made file writing programs and it's always in the same repertory of the .exe. Before it worked nice in C, but in C++ it doesn't work... :(

    Also can I add one string to one string that is non defined ?
    To solve that I changed the setFileContent function :

    Code:
    void Text::setFileContent(string content)
    {
        if(fileContent = "")
        {
            fileContent = content;
        }
        else
        {
            fileContent += content;
        }
    }
    I do not know how to write the expression : "string fileContent points to NULL", so I know when I have to assign content to it and then add content to it again all the other times.

    EDIT: using code::blocks
  8. #5
  9. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    I'm not even sure whether "repertory" exists in English ... OK, I found it with Google and it appears to mean "repository", which is much more common. It is true that most English vocabulary came from French (via Norman Conquest, 1066), but that fact is not always helpful. Besides, the computer term is "directory", not "repository", which would mean something different in a more specialized area of computer science.

    I would recommend that you follow salem's advice on how to test whether the file opened; I just looked it up in Lippman's C++ Primer and he also tests for ( !inputf ).

    While I have several years professional experience with C++, I prefer to avoid using iostreams, having found them to be very clumsy to work with compared with C I/O. As a result, I would have to look everything up, which I recommend that you do as well. Read the documentation for ifstream's open method. While you're at it, also read up on the eof method, especially the part about what it does when the file failed to open.
  10. #6
  11. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    31
    Rep Power
    1
    Yeah sorry for my english, I'll say directory (I wasn't sure and I was saying sometimes directory :p ).

    And !inputf as I said works and I replaced it long time ago.

    Sadly I really want to know how to use iostreams in C++, I want to do the exercices of my book. And I find them to be easier to use than C++ (even if a.t.m they don't work for me :D ).

    And I already checked the open method of ifstream as I said on cplusplus.com, otherwise I wouldn't have changed it to .c_str.

    Could someone try to compile it with some file named "essai.txt" to make sure it's not on my side ?

    And can you tell me how to know if a string is totally empty ?
    Thanks :)
  12. #7
  13. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,377
    Rep Power
    1871
    > if(fileContent = "")
    Now I'm pretty sure your compiler should be warning you about using an assignment as a truth value (you did say code::blocks, which is by default using GCC as the compiler.)

    All you do is every single time, make fileContent an empty string.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper
  14. #8
  15. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    31
    Rep Power
    1
    Oh I didn't copy the code well, I put in my code long time ago that it was "==" and it doesn't copy anything because it always say "fail to open the file" because I said the program to cout "fail to open the file" for (!inputf)...
  16. #9
  17. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    Oops! Sorry! I forgot to include this in my last reply.

    Your code:
    Code:
    void Text::setFileContent(string content)
    {
        if(fileContent = "")
        {
            fileContent = content;
        }
        else
        {
            fileContent += content;
        }
    }
    You are not testing for equality there, but rather you are assigning the empty string to fileContent. That's a common typographical error. Instead, that should have been:
    if(fileContent == "")

    As for testing whether a string, fileContent, is empty, there are a number of ways.
    1. Testing for being equal to the empty string, ""; eg
    if(fileContent == "")

    2. Test the string length for being zero:
    if (!fileContent.length())
    Also, as presented by Lippman:
    if (!fileContent.size())

    3. Test the string for being empty:
    if (fileContent.empty())


    For reading the documentation, I was referring to the man pages. Though I see that cplusplus.com has an on-line reference as well.

    For ifstream.open() (http://www.cplusplus.com/reference/f...ifstream/open/), it says of the return value:
    none

    If the function fails to open a file, the failbit state flag is set for the stream (which may throw ios_base::failure if that state flag was registered using member exceptions).
    Then ifstream has a method, is_open(), which reports whether the file is open. I guess you could also check the failbits directly.

    Using eof() is problematic, since all it does is (http://www.cplusplus.com/reference/ios/ios/eof/):
    Check whether eofbit is set
    Returns true if the eofbit error state flag is set for the stream.

    This flag is set by all standard input operations when the End-of-File is reached in the sequence associated with the stream.
    Now the question would be what the eofbit is set to when the file hasn't been opened. I don't know whether that is defined. We both know to avoid undefined behavior.

    It appears to be better to use is_open().
  18. #10
  19. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,377
    Rep Power
    1871
    > Oh I didn't copy the code well,
    If you're doing something other than ctrl-a (select all), ctrl-c (copy), and then ctrl-v (paste) in your browser edit window, then you're doing it wrong.

    Further, because you've now admitted that the code you post might not be the code in your editor (in all sorts of interesting ways which have nothing to do with the REAL problem), we're all going to be wasting our time pointing out the bleedingly obvious and not getting to the real question you have.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper
  20. #11
  21. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    31
    Rep Power
    1
    Lol you didn't read my messages either. I already said I changed the = to ==....The problem don't come from there but from the fact that it can't find the file :/
  22. #12
  23. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    For that matter, the function you provided (corrected here) appears more complex than it needs to be:
    Code:
    void Text::setFileContent(string content)
    {
        if(fileContent = "")
        {
            fileContent = content;
        }
        else
        {
            fileContent += content;
        }
    }
    When you instantiate a string without an initializer string, it's instantiate as being empty (as I understand it). And concatenating onto an empty string works. So your function could be written as:
    Code:
    void Text::setFileContent(string content)
    {
        fileContent += content;
    }
    There should be no need to test for the string being empty.

    Though mind you, I'm not yet proficient with the basic string class. My schooling in C++ was circa 1991 and a few years later I got a job where I worked with it intensively for two years, such that I ended up with a thorough knowledge of the Annotated C++ Reference Manual (ARM), such that I was the go-to guy at work to answer any question they had about C++. After that, my work was mainly embedded programming in C, such that I didn't even hear about the new 1998 C++ standard (which introduced the basic string class and incorporated the STL) until after I had joined this forum in 2003. And since all our C++ projects here at work are based on MFC, which has its own CString string class and list classes, I haven't had much practical experience with those new features yet. But I do know how to look things up.
  24. #13
  25. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2013
    Posts
    159
    Rep Power
    19
    You also shouldn't be trying to compare a std::string to "", use the empty() member function. I've seen some older compilers that didn't properly handle testing against an empty string.
    Now the question would be what the eofbit is set to when the file hasn't been opened.Now the question would be what the eofbit is set to when the file hasn't been opened.
    No the eof() only tests to see if the eof flag is set.

    To test for every possible problem you should just use the file stream.

    Code:
    ifstream file_stream("someInputFile.txt");
    if(!file_stream)
    {
       // open failed do something about it.
    }
    Did you ask your program to tell you the reason the file didn't open correctly?

    Code:
    #include <cstdio>
    ...
    ifstream file_stream("someInputFile.txt");
    if(!file_stream)
    {
       perror("The file failed to open because: ");
       // open failed do something about it.
    }
    Jim
  26. #14
  27. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    31
    Rep Power
    1
    Thanks for making me know the perror method, it looks very useful.
    It says no file found...
    http://imgur.com/TZ3A8Gp
    Why doesn't it work ;_;
  28. #15
  29. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2013
    Posts
    159
    Rep Power
    19
    Why doesn't it work ;_;
    This is a great hint:
    It says no file found...
    Now you need to find out why the file can't be found.

    First are you sure the file exists where your program expects it to be?

    The current working directory can be different depending on how you are running the program. With many IDEs the working directory is located where the project files are located, not necessarily where the executable is located.

    I find an easy way of determining where the working directory is located is to try to create an output file. The default open mode for an output file will create the file if it doesn't exit so there are fewer failures. Use a distinctive name for the file and be sure to test the opening succeeded. Then if that succeeds use your Operating system find functionality to actually locate the distinctive named file. Your input file should be in that same directory.

    Another thing to do is print the string you used when opening the file, along with the length of the string. If the length reported is different than the number of characters you see then there are probably non-printable characters in your string.


    Jim
Page 1 of 2 12 Last
  • Jump to page:

IMN logo majestic logo threadwatch logo seochat tools logo