0

I want to make a simple file input output program with an external class "File_Opening_and_Closing.cpp” when I use ”getline ()” function without any loop it works fine but when I use ”getline ()” function with do while loop in “main.cpp” it crushes.

Please tell me where the problem is and how I solve it?

main.cpp

    #include<iostream>
    #include<fstream>
    #include "File_Opening_and_Closing.h" using namespace std;

    int main() {
        int i=1;
        char file_make='y';
        char file_insert='y';

        do
        {
            File_Opening_and_Closing file[i];

            do
            {
                file[i].put_data();
                file[i].show_data();
                cout<<"Do you want to insert text again ? 'y' OR 'n'"<<endl;
                cin>>file_insert;
            }while(file_make=='y');
            i++;
            cout<<"Do you want to Make another file ? 'y' OR 'n'"<<endl;
            cin>>file_make;
        }while(file_insert=='y');

return 0;}

with out loop working fine >>

 int main() {
            File_Opening_and_Closing file;
            file.put_data();
            file.show_data();
 return 0;}

File_Opening_and_Closing.cpp

#include "File_Opening_and_Closing.h"

File_Opening_and_Closing::File_Opening_and_Closing()
{
    cout<<"Enter the file name and type => ";
    cin>>file_name;
}

void File_Opening_and_Closing::put_data(){
    ofstream file_out;
    file_out.open(file_name);

    cin.ignore();
    cout<<"Enter the string => ";
    cin.ignore();

//  getline is not working here!

    getline(cin,data);

    data = "Hello World!";

    file_out<<data;
    file_out.close();
}

void File_Opening_and_Closing::show_data(){
    ifstream file_in;

    file_in.open(file_name);

    getline(file_in,data);
    cout<<data;

    file_in.close();
}

File_Opening_and_Closing.h

#ifndef FILE_OPENING_AND_CLOSING_H
#define FILE_OPENING_AND_CLOSING_H
#include<iostream>
#include<fstream>
using namespace std;


class File_Opening_and_Closing
{
    private:
        string file_name;
        string data;
    public:
        File_Opening_and_Closing();
        void put_data();
        void show_data();
    protected:
};

#endif // FILE_OPENING_AND_CLOSING_H

Problem picture

  • 1
    Perhaps the same problem as https://stackoverflow.com/questions/12691316/getline-does-not-work-if-used-after-some-inputs. – R Sahu Mar 19 '19 at 04:09
  • `main.cpp` - *"ISO C++ forbids variable length array"* `‘file’`?? – David C. Rankin Mar 19 '19 at 04:13
  • Unrelated: It looks like you may have `while(file_make=='y')` and `while(file_insert=='y');` swapped. – user4581301 Mar 19 '19 at 04:51
  • @user4581301 both while loops are not "Unrelated" because first one is asking for if i want insert another string into the same file and second while is for checking if i want to make another file and insert something else into it. :) –  Mar 19 '19 at 05:37
  • Thank you @Mr. David C. Rankin i will use vector for this but the constructor is executing fine and i already see we can assign array length in run-time in mingw compiler and thanks for the link. –  Mar 19 '19 at 05:45
  • @SumanMandal I call it unrelated because this is a different bug from the one you've asked about. I agree that you need the while loops, but take a closer look at `cin>>file_insert; }while(file_make=='y');` The code reads `file_insert` from the user. Then it tests `file_make`, not `file_insert`. At this point in the code `file_make` can only be `'y'`, resulting in an infinite loop. My expectation is `file_insert` should be tested and `file_make` will be tested later in the outer loop. – user4581301 Mar 19 '19 at 05:46
  • Ooo yes yes thanks @user4581301 –  Mar 19 '19 at 05:59

1 Answers1

1

You have a whole host of issues, not the least of what is a How to debug small programs issue where you have mixed up the variables used to test both do .. while (...); loops, e.g.

            ...
            cin>>file_insert;
        }while(file_make=='y');
        // i++; (not needed and VLA's not allowed in C++
        cout<<"Do you want to Make another file ? 'y' OR 'n'"<<endl;
        cin>>file_make;
    }while(file_insert=='y');

Secondly, as mentioned in the comments, Standard C++ does not allow Variable Length Arrays.

    File_Opening_and_Closing file[i];

If you need more than 1 instance of your class, the use a vector of classes or array of classes. However, there is no need in your code for either. Since you create a new instance of File_Opening_and_Closing each iteration through the do { ... } while (..); loop, you can simply use:

    File_Opening_and_Closing file;

You are making things incredibly hard on yourself by declaring file_make and file_insert as type char. Instead, simply make them std::string and test with, e.g. if (file_make == "y"). This will allow you to read all input with getline avoiding the problems with mixed std::cin and getline use.

The remaining issues are a complete failure to validate the file openings with, e.g. if (!file_out.is_open()) { /* handle error */ } with similar tests needed for each input to ensure you can trap a input cancellation by the user generating a manual EOF with Ctrl+d (or Ctrl+z on windows).

Also, avoid putting using namespace std; in header files. There is no need to pull the standard namespace into every file utilizing your header (though you did do a good job and protect against multiple inclusions with the header guards FILE_OPENING_AND_CLOSING_H). In fact there is no reason for using namespace std; at all here. Just use the std:: namespace resolution operator for cin, cout, etc..

Leaving the validations for you to add, addressing the other issues, you could do something similar to:

File_Opening_and_Closing.h

#ifndef FILE_OPENING_AND_CLOSING_H
#define FILE_OPENING_AND_CLOSING_H

#include<iostream>
#include<fstream>

class File_Opening_and_Closing
{
    private:
        std::string file_name;
        std::string data;
    public:
        File_Opening_and_Closing();
        void put_data();
        void show_data();
    protected:
};

#endif

File_Opening_and_Closing.cpp

#include "File_Opening_and_Closing.h"

File_Opening_and_Closing::File_Opening_and_Closing()
{
    std::cout << "Enter the file name and type => ";
    getline (std::cin, file_name);
}

void File_Opening_and_Closing::put_data(){
    std::ofstream file_out;
    file_out.open(file_name);

    std::cout<<"Enter the string => ";

    getline (std::cin, data);


    file_out << data << '\n';
    file_out.close();
}

void File_Opening_and_Closing::show_data(){
    std::ifstream file_in;

    file_in.open (file_name);

    getline (file_in,data);
    std::cout << data << '\n';

    file_in.close();
}

main.cpp

#include<iostream>
#include<fstream>

#include "File_Opening_and_Closing.h"

int main (void) {

    std::string file_make = "y";
    std::string file_insert = "y";

    do
    {
        File_Opening_and_Closing file;

        do
        {
            file.put_data();
            file.show_data();
            std::cout << "Do you want to insert text again ? 'y' OR 'n'\n";
            getline (std::cin, file_insert);
        } while (file_insert == "y");
        std::cout << "Do you want to Make another file ? 'y' OR 'n'\n";
        getline (std::cin, file_make);
    } while (file_make == "y");

    return 0;
}

It will now create as many files as you need (though you will want to look into std::ios::app mode if you want to add more than one string.

Example Use/Output

$ ./bin/main
Enter the file name and type => out1
Enter the string => foobar
foobar
Do you want to insert text again ? 'y' OR 'n'
y
Enter the string => barbaz
barbaz
Do you want to insert text again ? 'y' OR 'n'
n
Do you want to Make another file ? 'y' OR 'n'
y
Enter the file name and type => out2
Enter the string => bazbuz
bazbuz
Do you want to insert text again ? 'y' OR 'n'
n
Do you want to Make another file ? 'y' OR 'n'
n

Resulting Output Files

$ cat out1
barbaz

$ cat out2
bazbuz

Let me know if you have further questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85