Thread: fopen with std::string

  1. #1
    Registered User
    Join Date
    Dec 2007
    Posts
    930

    fopen with std::string

    Im trying to find a way to open several files with different names.
    My first problem creating this program is, how come that 'fopen()' which is a C++ function takes a C const char* argument?
    I thought we were supposed to use strings with C++.

    This is what i have so far, trying to figure out how to use strings.

    Code:
    #include <iostream>
    #include <string>
    using namespace std;
    
    
    int main ()
    {
      FILE * pFile;
      int i = 0;
      char ch[5] = {0,1,2,3,4};
      string str = "file.txt", str2;
      pFile = fopen (str,"w");
      while (i<5)
      {
        cout << "Enter word: "; cin >> str2;
        str.append(ch[i]);
        fprintf(pFile, str2);
        fclose (pFile);
        i++;
      }
      return 0;
    }
    Using Windows 10 with Code Blocks and MingW.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Ducky
    My first problem creating this program is, how come that 'fopen()' which is a C++ function takes a C const char* argument?
    I thought we were supposed to use strings with C++.
    Well, fopen() is actually inherited from the C standard library. That said, the C++ standard file streams also use a const char* parameter. The solution lies with the c_str() member function, e.g.,
    Code:
    pFile = fopen(str.c_str(), "w");
    By the way, it looks like you are closing the file in the loop. Also, you should #include <cstdio> for std::fopen().
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> My first problem creating this program is, how come that 'fopen()' which is a C++ function takes a C const char* argument?

    fopen is a C function (but still valid for C++, of course). Incidentally, fstreams also take a const char*, which I've always found a bit odd. Anyway, you just need to invoke the std::string::c_str( ) function to get a pointer to the bytes.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  4. #4
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> Incidentally, fstreams also take a const char*, which I've always found a bit odd.

    I agree. I'm pretty sure it's fixed in the next standard.

  5. #5
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    Thank you Laserlight and Sebastiani!

    "By the way, it looks like you are closing the file in the loop."
    Yes you are right thanks for recalling me but on second thoughts if i wanna open a new file every time i think i would have to close the precedent.

    I corrected the code. Now i just need to find out how to append a number each time to the filename.
    For a reason 'strcpy' wont accept the first arg.

    Code:
    #include <cstdio>
    #include <iostream>
    #include <string>
    using namespace std;
    
    
    int main ()
    {
     FILE * pFile;
      int i = 0;
      char ch[5] = {0,1,2,3,4};
      string filename = "file.txt", str2;
      pFile = fopen (filename.c_str(),"w");
      while (i<5)
      {
        cout << "Enter word: "; cin >> str2;
        strcpy(filename.c_str(), ch[i]);
        pFile = fopen (filename.c_str(),"w");
        fprintf(pFile, str2.c_str());
        fclose (pFile);
        i++;
      }
      return 0;
    }
    Using Windows 10 with Code Blocks and MingW.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Ducky
    Now i just need to find out how to append a number each time to the filename.
    You can use a stringstream. Here is the idea expressed as an example program:
    Code:
    #include <sstream>
    #include <string>
    #include <iostream>
    
    int main()
    {
        using namespace std;
    
        const string filename = "file";
        const string extension = ".txt";
        for (int i = 0; i < 5; ++i)
        {
            stringstream ss;
            ss << filename << i << extension;
            cout << ss.str() << endl;
        }
    }
    Speaking of which, is there a reason why you are not using std::fstream?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> strcpy(filename.c_str(), ch[i]);

    >> For a reason 'strcpy' wont accept the first arg.

    You should never alter an std::string like that - any function that potentially transforms the size of the bytes (with respect to the null terminator) will lead to undefined behaviour. Furthermore, character transforms are safe, of course, unless the resulting character is itself the null terminator for that character type. The correct way would be simply:

    filename = ch[i];

    EDIT:
    I hadn't noticed the type of ch. Yes, use Laserlight's suggestion.
    Last edited by Sebastiani; 07-28-2009 at 02:49 PM.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  8. #8
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    Thank you very much again both of you!

    Of course, i forgot how easy it was to concatenate with strings, i just went complicating things again.

    "is there a reason why you are not using std::fstream?"

    No there isn't. Actually i just found this comparison between the two and it looks like std::fstream is faster.
    So im gonna use std::fstream instead. Thank you!

    http://social.msdn.microsoft.com/For...2-36248f86a8ce

    Ok, have a good day or night everybody, whatever is it over there, its already night here.
    Last edited by Ducky; 07-28-2009 at 03:39 PM.
    Using Windows 10 with Code Blocks and MingW.

  9. #9
    C++11 User Tux0r's Avatar
    Join Date
    Nov 2008
    Location
    Sweden
    Posts
    135
    Quote Originally Posted by Ducky View Post
    Actually i just found this comparison between the two and it looks like std::fstream is faster.
    Read it again. The buffering is intensive.

  10. #10
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    "The buffering is intensive."

    Is it a bad thing?
    Using Windows 10 with Code Blocks and MingW.

  11. #11
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> Is it a bad thing?

    fstreams do have a bit more overhead, but you get what you pay for, and I think most would agree that the benefits outweigh the the drawbacks.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  12. #12
    C++11 User Tux0r's Avatar
    Join Date
    Nov 2008
    Location
    Sweden
    Posts
    135
    Just the fact that they use RAII is enough for me! And not to mention << and >>.

  13. #13
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    Ok, thanks Tux0r for your help!
    I dont understand right now what you're saying but i will look after it later when i'll have the time.

    For now i got Laserlight and Sebastiani telling me to prefer fstream so i rewrote the program with fstream.

    For a reason 'cout' accepts stringstream ss.str() but 'filestr.open()' won't.

    Code:
    #include <iostream>
    #include <string>
    #include <sstream>
    #include <fstream>
    
    using namespace std;
    
    
    int main ()
    {
        fstream filestr;
        filestr.open ("test.txt", fstream::in | fstream::out | fstream::app);
    
        const string filename  = "file";
        const string extension = ".txt";
        stringstream ss;
        string word;
    
        for (int i = 0; i < 5; ++i)
        {
            cout << "Enter word: "; cin >> word;
            ss << filename << i << extension;
            filestr.open (ss.str(), fstream::in | fstream::out | fstream::app);
            filestr << word.c_str() << endl;
            filestr.close();
        }
    
    
         return 0;
    }
    Using Windows 10 with Code Blocks and MingW.

  14. #14
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Should be:

    Code:
    filestr.open (ss.str().c_str(), fstream::in | fstream::out | fstream::app);
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  15. #15
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    Thank you!
    Using Windows 10 with Code Blocks and MingW.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 13
    Last Post: 12-14-2007, 03:34 PM
  2. std::string: Has my compiler gone nuts??
    By Andruu75 in forum C++ Programming
    Replies: 9
    Last Post: 09-28-2007, 04:02 AM
  3. Debugging help
    By cuddlez.ini in forum C++ Programming
    Replies: 3
    Last Post: 10-24-2004, 07:08 PM
  4. DLL and std::string woes!
    By Magos in forum C++ Programming
    Replies: 7
    Last Post: 09-08-2004, 12:34 PM
  5. returning std::string
    By Unregistered in forum C++ Programming
    Replies: 3
    Last Post: 09-24-2001, 08:31 PM