Confused with error using ofstream

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • rEvolution27@gmail.com

    Confused with error using ofstream

    I'm a c++ newbie here, trying out some stuff and when I try to compile
    this:

    void create() {
    char name;
    cout << "Creating a new timetable /n Please type a name for this
    timetable";
    cin >name;
    ofstream editFile;
    editFile.open (name, ios::out | ios::app);
    editFile << name << endl;
    }

    I get this:
    invalid conversion from `char' to `const char*'

    I kinda understand why i'm getting this since when I change:
    editFile.open (name, ios::out | ios::app);
    To:
    editFile.open ("Timetable.txt ", ios::out | ios::app); , it compiles
    But how do I get it do do what I want?

  • John Harrison

    #2
    Re: Confused with error using ofstream

    rEvolution27@gm ail.com wrote:
    I'm a c++ newbie here, trying out some stuff and when I try to compile
    this:
    >
    void create() {
    char name;
    cout << "Creating a new timetable /n Please type a name for this
    timetable";
    cin >name;
    ofstream editFile;
    editFile.open (name, ios::out | ios::app);
    editFile << name << endl;
    }
    >
    I get this:
    invalid conversion from `char' to `const char*'
    >
    I kinda understand why i'm getting this since when I change:
    editFile.open (name, ios::out | ios::app);
    To:
    editFile.open ("Timetable.txt ", ios::out | ios::app); , it compiles
    But how do I get it do do what I want?
    >
    char is a single char, a file name is (obviously) multiple chars.

    Put it another way in C++ a char and a string of chars are not the same
    thing.

    The best way in C++ to do what you want is to use the string class. The
    next best way is to use a dynamic array of chars, the worst way is to
    use a static arrays of chars.

    Here's some example code using the string class

    #include <string>
    #include <fstream>
    using namespace std;

    void create() {
    string name;
    cout << "Creating a new timetable \n Please type a name for this
    timetable ";
    cin >name;
    ofstream editFile(name.c _str());
    editFile << name << endl;

    You need the c_str() method to convert a C++ string into what ofstream
    requires.

    char, arrays of chars, dynamic allocation of arrays, strings etc. are a
    big topic which should be covered in great detail in your favourite C++
    book.

    john

    Comment

    • Alan Johnson

      #3
      Re: Confused with error using ofstream

      rEvolution27@gm ail.com wrote:
      I'm a c++ newbie here, trying out some stuff and when I try to compile
      this:
      >
      void create() {
      char name;
      In the above line you define 'name' as a char. That is, a single
      character, 1 byte. Probably not what you want.
      cout << "Creating a new timetable /n Please type a name for this
      timetable";
      cin >name;
      Because, as previously mentioned, name is a char, you read exactly 1
      character here.

      ofstream editFile;
      editFile.open (name, ios::out | ios::app);
      open expects a POINTER to the first character in an null-terminated
      array of characters. If you don't understand pointers and their
      relationship to arrays, now is the appropriate time to drop what you are
      doing and go read about it.

      editFile << name << endl;
      }
      >
      I get this:
      invalid conversion from `char' to `const char*'
      Given the above explanation, this message might make sense now. 'name'
      is a char, but open wants a pointer to a char.
      >
      I kinda understand why i'm getting this since when I change:
      editFile.open (name, ios::out | ios::app);
      To:
      editFile.open ("Timetable.txt ", ios::out | ios::app); , it compiles
      When you use a string literal (e.g. "Timetable.txt" ), you create a
      null-terminated array of characters. And arrays can be implicitly
      converted to a pointer to their first element (again, go read about
      pointers and arrays if that is new to you), therefore open is getting
      what it wants, a pointer to a character.
      But how do I get it do do what I want?
      >
      A number of ways. First, the not particularly safe, but easier to
      understand way:

      // I chose the size 80 arbitrarily. This is unsafe.
      char name[80] ;
      cin >name ;

      This will read from standard input until it sees white space. If there
      are more than 79 characters (the null-terminator takes 1 character, read
      about C-style strings if this is new to you) available then you have
      your classic buffer-overflow problem.

      A second, more complicated solution, would be to dynamically allocate an
      array, and resize it each time it runs out of space. This is not
      trivial to do correctly, so I won't even bother. Let's move on to the
      third solution.

      Use std::string.

      #include <string>

      ....

      std::string name ;
      cin >name ;

      ....

      editFile.open(n ame.c_str(), ios::out | ios::app) ;


      std::string does any necessary memory allocating and reallocating for
      you. You can get pointer to a null-terminated array of characters using
      the c_str method, as demonstrated above.

      --
      Alan Johnson

      Comment

      • rEvolution27@gmail.com

        #4
        Re: Confused with error using ofstream

        Ok, thanks.
        For some reason I thought 'char name' would create a character array
        that matches the size of what's put into it. I guess i'll use strings
        then.

        Comment

        • rEvolution27@gmail.com

          #5
          Re: Confused with error using ofstream

          How would I make it so that the string can accept more than one word?

          I've got this so far...
          void create() {
          string name;
          cout << "Creating a new timetable"<< endl <<"Type a name for this
          timetable" << endl;
          cin >name;
          ofstream editFile;
          editFile.open ("timetable.txt ", ios::out | ios::trunc);
          editFile << name << endl;
          }

          But when I open timetable.txt, I only see the first word of what I
          typed for name.

          Comment

          • Ian Collins

            #6
            Re: Confused with error using ofstream

            rEvolution27@gm ail.com wrote:
            How would I make it so that the string can accept more than one word?
            >
            I've got this so far...
            void create() {
            string name;
            cout << "Creating a new timetable"<< endl <<"Type a name for this
            timetable" << endl;
            cin >name;
            ofstream editFile;
            editFile.open ("timetable.txt ", ios::out | ios::trunc);
            editFile << name << endl;
            }
            >
            But when I open timetable.txt, I only see the first word of what I
            typed for name.
            >
            That's how std::istream& operator( std::istream& std::string& ) works.
            If you want the full line, use getline.

            --
            Ian Collins.

            Comment

            • rEvolution27@gmail.com

              #7
              Re: Confused with error using ofstream

              On Mar 3, 6:04 pm, Ian Collins <ian-n...@hotmail.co mwrote:
              rEvolutio...@gm ail.com wrote:
              How would I make it so that the string can accept more than one word?
              >
              I've got this so far...
              void create() {
              string name;
              cout << "Creating a new timetable"<< endl <<"Type a name for this
              timetable" << endl;
              cin >name;
              ofstream editFile;
              editFile.open ("timetable.txt ", ios::out | ios::trunc);
              editFile << name << endl;
              }
              >
              But when I open timetable.txt, I only see the first word of what I
              typed for name.
              >
              That's how std::istream& operator( std::istream& std::string& ) works.
              If you want the full line, use getline.
              >
              --
              Ian Collins.
              You lost me there....

              Comment

              • Jim Langston

                #8
                Re: Confused with error using ofstream

                <rEvolution27@g mail.comwrote in message
                news:1172959775 .759852.242580@ h3g2000cwc.goog legroups.com...
                On Mar 3, 6:04 pm, Ian Collins <ian-n...@hotmail.co mwrote:
                >rEvolutio...@g mail.com wrote:
                How would I make it so that the string can accept more than one word?
                >>
                I've got this so far...
                void create() {
                string name;
                cout << "Creating a new timetable"<< endl <<"Type a name for this
                timetable" << endl;
                cin >name;
                ofstream editFile;
                editFile.open ("timetable.txt ", ios::out | ios::trunc);
                editFile << name << endl;
                }
                >>
                But when I open timetable.txt, I only see the first word of what I
                typed for name.
                >>
                >That's how std::istream& operator( std::istream& std::string& ) works.
                >If you want the full line, use getline.
                >>
                >--
                >Ian Collins.
                >
                You lost me there....
                std::getline( std::cin, name );


                Comment

                • rEvolution27@gmail.com

                  #9
                  Re: Confused with error using ofstream

                  The following compiles, but the getline doesn't seem to work... am I
                  missing something here?

                  void create() {
                  string name;
                  cout << "Creating a new timetable"<< endl <<"Type a name for this
                  timetable" << endl;
                  getline(cin,nam e);
                  ofstream editFile;
                  editFile.open ("timetable.txt ", ios::out | ios::trunc);
                  editFile << name << endl;
                  system ("pause");





                  Comment

                  • John Harrison

                    #10
                    Re: Confused with error using ofstream

                    rEvolution27@gm ail.com wrote:
                    The following compiles, but the getline doesn't seem to work... am I
                    missing something here?
                    >
                    void create() {
                    string name;
                    cout << "Creating a new timetable"<< endl <<"Type a name for this
                    timetable" << endl;
                    getline(cin,nam e);
                    ofstream editFile;
                    editFile.open ("timetable.txt ", ios::out | ios::trunc);
                    editFile << name << endl;
                    system ("pause");
                    >
                    >
                    >
                    >
                    >
                    Can't tell from the code you've posted, but possibly you've fallen into
                    the well known gotcha described here



                    In other words getline is working, it's just it is reading the newline
                    that was left behind by some previous input.

                    john

                    Comment

                    • rEvolution27@gmail.com

                      #11
                      Re: Confused with error using ofstream

                      On Mar 4, 11:04 am, John Harrison <john_androni.. .@hotmail.comwr ote:
                      rEvolutio...@gm ail.com wrote:
                      The following compiles, but the getline doesn't seem to work... am I
                      missing something here?
                      >
                      void create() {
                      string name;
                      cout << "Creating a new timetable"<< endl <<"Type a name for this
                      timetable" << endl;
                      getline(cin,nam e);
                      ofstream editFile;
                      editFile.open ("timetable.txt ", ios::out | ios::trunc);
                      editFile << name << endl;
                      system ("pause");
                      >
                      Can't tell from the code you've posted, but possibly you've fallen into
                      the well known gotcha described here
                      >

                      >
                      In other words getline is working, it's just it is reading the newline
                      that was left behind by some previous input.
                      >
                      john
                      Oh, thanks alot. I actually had a hunch that that was what was
                      happening. I fixed it with a cin.ignore(); but it looks like a bug
                      that might just happen again and this time be harder to solve. Apart
                      from putting a cin.ingnore(); after every cin is there any way to
                      solve this?
                      Also con someone explain to me how getline works in terms of it's
                      arguments... I don't quite understand it.
                      My C++ book arrives in a few days, I hope it's as useful as you
                      guys.


                      Comment

                      • John Harrison

                        #12
                        Re: Confused with error using ofstream

                        rEvolution27@gm ail.com wrote:
                        On Mar 4, 11:04 am, John Harrison <john_androni.. .@hotmail.comwr ote:
                        >
                        >>rEvolutio...@ gmail.com wrote:
                        >>
                        >>>The following compiles, but the getline doesn't seem to work... am I
                        >>>missing something here?
                        >>
                        >>>void create() {
                        >>>string name;
                        >>>cout << "Creating a new timetable"<< endl <<"Type a name for this
                        >>>timetable" << endl;
                        >>>getline(cin, name);
                        >>>ofstream editFile;
                        >>>editFile.ope n ("timetable.txt ", ios::out | ios::trunc);
                        >>>editFile << name << endl;
                        >>>system ("pause");
                        >>
                        >>Can't tell from the code you've posted, but possibly you've fallen into
                        >>the well known gotcha described here
                        >>
                        >>http://www.parashift.com/c++-faq-lit....html#faq-15.6
                        >>
                        >>In other words getline is working, it's just it is reading the newline
                        >>that was left behind by some previous input.
                        >>
                        >>john
                        >
                        >
                        Oh, thanks alot. I actually had a hunch that that was what was
                        happening. I fixed it with a cin.ignore(); but it looks like a bug
                        that might just happen again and this time be harder to solve. Apart
                        from putting a cin.ingnore(); after every cin is there any way to
                        solve this?
                        It depnds on exactly what you are doing, but in a program that reads
                        from cin my usual choice would be to make all input operations read
                        whole lines, getline does this anyway but cin >does not. So I would add

                        cin.ignore(std: :numeric_limits <std::streamsiz e>::max(), '\n');

                        after each use of cin >>

                        You can even write an 'iostream manipulator' to do that for you.

                        #include <iostream>
                        #include <limits>
                        #include <string>

                        std::istream& skip_to_eol(std ::istream& in)
                        {
                        in.ignore(std:: numeric_limits< int>::max(), '\n');
                        return in;
                        }

                        int main()
                        {
                        int x, y;
                        std::cin >x >y >skip_to_eol;
                        std::string z;
                        std::getline(st d::cin, z);
                        std::cout << x << ' ' << y << ' ' << z << '\n';
                        }

                        See how skip_to_eol is just an easy way to call ignore.
                        Also con someone explain to me how getline works in terms of it's
                        arguments... I don't quite understand it.
                        I'm not sure what there is to understand. getline reads characters from
                        an input stream (the first argument) until an end of line character is
                        read. All characters read (except the end of line character) are
                        accumulated into the string that is the second argument. An optional
                        third argument specifies the end of line character (by default it is '\n').

                        My C++ book arrives in a few days, I hope it's as useful as you
                        guys.
                        >
                        >

                        Comment

                        • rEvolution27@gmail.com

                          #13
                          Re: Confused with error using ofstream

                          I'm not sure what there is to understand. getline reads characters from
                          an input stream (the first argument) until an end of line character is
                          read. All characters read (except the end of line character) are
                          accumulated into the string that is the second argument. An optional
                          third argument specifies the end of line character (by default it is '\n').
                          Ok, the input stream is the first argument, that´s what i needed to
                          know.

                          Ok, this is the last thing for a while... (hopefully :) )
                          I'm going to post all my code so far... I know it ain't alot but I
                          have a few questions. Mainly I want to know how to make the functions
                          more abstract (I think that's the term).

                          // Timetable program, by Evan Skeete
                          // Functionality to build:
                          // Save timetable to file
                          // Create new/delete timetables
                          // Edit time tables??
                          // Timetable reminders

                          #include <iostream>
                          #include <fstream>
                          #include <string>
                          using namespace std;

                          // This function creates a new txt file to contain a timetable with //
                          the name of the timetable as the first line of the file.
                          // I'm going to make it so that the variable name will also be the //
                          name of the .txt file
                          // I'm thinking about removing the inputs and outputs from this
                          // function so it's more abstract

                          void create() {
                          string name;
                          cout << "Creating a new timetable"<< endl <<"Type a name for this
                          timetable" << endl;
                          getline( cin,name );
                          ofstream editFile;
                          editFile.open ("timetable.txt ", ios::out | ios::trunc);
                          editFile << name << endl;
                          }

                          // This function allows the user to type in one letter commands
                          to // make the program do things

                          void options() {
                          do {
                          char choice;
                          cin >choice; // Should I use getline here?
                          cin.ignore(); // I want a way to avoid this
                          switch (choice) {
                          case 'h' :
                          cout << "Type 'n' to create a new timetable" << endl;
                          break;

                          case 'n':
                          create();
                          break;

                          default :
                          cout << "Not a valid command";
                          }
                          } while (choice != 'n') ; //
                          }

                          // I want to eliminate the do while loop here, or find a better way //
                          of doing what it does
                          // as it is, i' m going to hove to add a new condition every time I //
                          add a new case which I don't want to loop

                          int main() {
                          cout << "Welcome to the Timetable Program" << endl;
                          cout << "For help, type 'h'" << endl;
                          void options();
                          return 0;
                          }

                          If you see any improvements I can make please tell me.
                          My coding speed is extremely low :( I guess it's because I'm just
                          starting...

                          Thanks,
                          Evan

                          Comment

                          • Jim Langston

                            #14
                            Re: Confused with error using ofstream

                            <rEvolution27@g mail.comwrote in message >
                            news:1173026695 .822015.271090@ 8g2000cwh.googl egroups.com...
                            I'm not sure what there is to understand. getline reads characters from
                            an input stream (the first argument) until an end of line character is
                            read. All characters read (except the end of line character) are
                            accumulated into the string that is the second argument. An optional
                            third argument specifies the end of line character (by default it is
                            '\n').
                            >
                            Ok, the input stream is the first argument, that´s what i needed to
                            know.
                            >
                            Ok, this is the last thing for a while... (hopefully :) )
                            I'm going to post all my code so far... I know it ain't alot but I
                            have a few questions. Mainly I want to know how to make the functions
                            more abstract (I think that's the term).
                            >
                            // Timetable program, by Evan Skeete
                            // Functionality to build:
                            // Save timetable to file
                            // Create new/delete timetables
                            // Edit time tables??
                            // Timetable reminders
                            >
                            #include <iostream>
                            #include <fstream>
                            #include <string>
                            using namespace std;
                            >
                            // This function creates a new txt file to contain a timetable with //
                            the name of the timetable as the first line of the file.
                            // I'm going to make it so that the variable name will also be the //
                            name of the .txt file
                            // I'm thinking about removing the inputs and outputs from this
                            // function so it's more abstract
                            >
                            void create() {
                            string name;
                            cout << "Creating a new timetable"<< endl <<"Type a name for this
                            timetable" << endl;
                            getline( cin,name );
                            ofstream editFile;
                            editFile is local to the function create()
                            editFile.open ("timetable.txt ", ios::out | ios::trunc);
                            Here you create a file and open it
                            editFile << name << endl;
                            At this point you return from the function, editFile is closed since it goes
                            out of scope. You wont' be able to use the ofstream outside the function.
                            I don't think that's what you wanted.
                            }
                            >
                            // This function allows the user to type in one letter commands
                            to // make the program do things
                            >
                            void options() {
                            do {
                            char choice;
                            cin >choice; // Should I use getline here?
                            I probably would.
                            cin.ignore(); // I want a way to avoid this
                            You can't really. I'm not sure what std::getline( std::cin, choice ); would
                            do if they entered more than a single character, but probably not what you
                            want.
                            switch (choice) {
                            case 'h' :
                            cout << "Type 'n' to create a new timetable" << endl;
                            break;
                            >
                            case 'n':
                            create();
                            break;
                            >
                            default :
                            cout << "Not a valid command";
                            }
                            } while (choice != 'n') ; //
                            Hmm.. can this while statement even see choice which is declared inside the
                            block? I woudl think you would need to declare choice outside the block
                            (before your do { ) but I may be wrong.
                            }
                            >
                            // I want to eliminate the do while loop here, or find a better way //
                            of doing what it does
                            // as it is, i' m going to hove to add a new condition every time I //
                            add a new case which I don't want to loop
                            Normally in this type of program, it's somethign like "Enter a choice, x to
                            exit" and your condition is while ( choice != 'x' ) that way you don't have
                            to keep changing it. Also, the help is usually given before the user input.
                            I.E.

                            std::cout << "Type 'n' to create a new timetable, 'x' to exit ";
                            std::cin >choice;
                            >
                            int main() {
                            cout << "Welcome to the Timetable Program" << endl;
                            cout << "For help, type 'h'" << endl;
                            void options();
                            return 0;
                            }
                            >
                            If you see any improvements I can make please tell me.
                            My coding speed is extremely low :( I guess it's because I'm just
                            starting...
                            >
                            Thanks,
                            Evan
                            >

                            Comment

                            • John Harrison

                              #15
                              Re: Confused with error using ofstream

                              Comments below

                              rEvolution27@gm ail.com wrote:
                              >>I'm not sure what there is to understand. getline reads characters from
                              >>an input stream (the first argument) until an end of line character is
                              >>read. All characters read (except the end of line character) are
                              >>accumulated into the string that is the second argument. An optional
                              >>third argument specifies the end of line character (by default it is '\n').
                              >
                              >
                              Ok, the input stream is the first argument, that´s what i needed to
                              know.
                              >
                              Ok, this is the last thing for a while... (hopefully :) )
                              I'm going to post all my code so far... I know it ain't alot but I
                              have a few questions. Mainly I want to know how to make the functions
                              more abstract (I think that's the term).
                              >
                              // Timetable program, by Evan Skeete
                              // Functionality to build:
                              // Save timetable to file
                              // Create new/delete timetables
                              // Edit time tables??
                              // Timetable reminders
                              >
                              #include <iostream>
                              #include <fstream>
                              #include <string>
                              using namespace std;
                              >
                              // This function creates a new txt file to contain a timetable with //
                              the name of the timetable as the first line of the file.
                              // I'm going to make it so that the variable name will also be the //
                              name of the .txt file
                              // I'm thinking about removing the inputs and outputs from this
                              // function so it's more abstract
                              That's a good idea. By putting the prompts for input into the function
                              you are ensuring that the function can be used in only one situation.
                              It's a good general princple, seperate the code that does the work from
                              the code that is part of the user interface.

                              BTW usually this is called making the code generic rather than abstract.
                              >
                              void create() {
                              string name;
                              cout << "Creating a new timetable"<< endl <<"Type a name for this
                              timetable" << endl;
                              getline( cin,name );
                              ofstream editFile;
                              editFile.open ("timetable.txt ", ios::out | ios::trunc);
                              editFile << name << endl;
                              }
                              >
                              // This function allows the user to type in one letter commands
                              to // make the program do things
                              >
                              void options() {
                              do {
                              char choice;
                              cin >choice; // Should I use getline here?
                              cin.ignore(); // I want a way to avoid this
                              First off cin.ignore() is wrong because it ignores one char acter only,
                              so if the user type 'n', ' ', '\n' you would have exactly same problem
                              you had earlier, the call to ignore would eat up the space but the
                              newline would still be there.

                              You should use

                              cin.ignore(std: :numeric_limits <int>::max(), '\n');

                              which ignores the rest of the line, however long it is. The skip_to_eol
                              manipulator I showed you in my last post is an easy way of doing this

                              cin >choice >skip_to_eol;


                              getline is not a cgood idea here for two reasons. Firslty getline only
                              works on strings not on chars, so you'd have to figure out how to get a
                              char out of the string you read. Secondly using >here actually a
                              couple of things for you, it skip any whitespace, and it doesn't give up
                              until the user has typed something that isn't whitespace. You would have
                              to do that work yourself if you used getline.
                              switch (choice) {
                              case 'h' :
                              cout << "Type 'n' to create a new timetable" << endl;
                              break;
                              >
                              case 'n':
                              create();
                              break;
                              >
                              default :
                              cout << "Not a valid command";
                              }
                              } while (choice != 'n') ; //
                              }
                              >
                              // I want to eliminate the do while loop here, or find a better way //
                              of doing what it does
                              // as it is, i' m going to hove to add a new condition every time I //
                              add a new case which I don't want to loop
                              Not quite sure I follow that.
                              >
                              int main() {
                              cout << "Welcome to the Timetable Program" << endl;
                              cout << "For help, type 'h'" << endl;
                              void options();
                              I think you mean

                              options();
                              return 0;
                              }
                              >
                              If you see any improvements I can make please tell me.
                              My coding speed is extremely low :( I guess it's because I'm just
                              starting...
                              >
                              Thanks,
                              Evan
                              >
                              john

                              Comment

                              Working...