1

I have tried to make it using dynamic string array but when I tried to add 2 lines it only adds one I don't know why here is my code

#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
    int x;
    string name;
    string* lines;
    cout << "Input the file name to be opened : ";
    cin >> name;
    cout << endl << "Input the number of lines to be written : ";
    cin >> x;
    lines = new string[x];
    cout << endl << "The lines are :";
    for (int i = 0; i < x; i++)
    {
        getline(cin,lines[i]);
    }
    fstream File(name, ios::out | ios::app);
    for (int i = 0; i < x; i++)
    {
        File << lines[i] << endl;
    }
    File.close();
}

and it gives me this warning: C6385 Reading invalid data from 'lines': the readable size is '(unsigned int)*28+4' bytes, but '56' bytes may be read

  • 7
    Save yourself headaches and use `std::vector`. It will relieve you of issues like you are having. – Thomas Matthews Apr 07 '20 at 22:13
  • 2
    Alternatively, just append each line to the file (in the input loop) as you read it. There is no apparent need for this program to store all the lines in memory. – paddy Apr 07 '20 at 22:22
  • 3
    Note also that after `cin >> x`, any extra whitespace or characters that follow an integer input, including the newline, will still be unread. When you call `getline`, those characters will constitute the first line, so if you typed a number and pressed Enter, then the first line read will be empty. – paddy Apr 07 '20 at 22:28
  • Note that the above does not mean sprinkle "Just In Case" `cin.ignore()`s around your code. If you need to `ignore`, do it AFTER the the operation that left stuff in the stream that you need gone. If you preemptively place an `ignore` before a read, sooner or later you'll find a case where there's nothing you want ignored and instead you accidentally delete an input you did want. – user4581301 Apr 07 '20 at 22:36
  • @user4581301 @paddy as you both said I tried using `cin.ignore()` before the `getline` it worked only for the first line but it deleted a letter from the second one so i used this code ` for (int i = 0; i < x; i++) { if(i == 0) cin.ignore(); getline(cin, lines); File << endl << lines ; } ` , Thanks for help :D – hussein medhat Apr 07 '20 at 22:53
  • You've misinterpreted what I wrote, done the opposite, and found exactly the bug I warned about. Find the input that doesn't read the newline you need removed, `cin >> x;`. Place the call to `ignore` AFTER that. By placing the `ignore()` pretty much anywhere else you have to complicate the code to prevent `ignore()`ing characters you do want. – user4581301 Apr 07 '20 at 23:33

1 Answers1

2

To store your strings you can use an std::vector which is a variable size C++ container and is preferred to the C type arrays, here is an example with comments:

Live sample

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <limits>

using namespace std; //for test purposes, in real code you shoud use std:: scope

int main()
{
    int x;
    string name, line;
    vector<string> lines; //container

    cout << "Input the file name to be opened : ";
    cin >> name;

    fstream File(name, ios::app | ios::out);

    cout << endl
         << "Input the number of lines to be written : ";
    cin >> x;
    cin.ignore(numeric_limits<streamsize>::max(), '\n'); //needed because getline does not ignore new line characters
                                                         //explicitly looking to clear buffer till '\n', improves clarity
    cout << endl
         << "The lines are :";

    while (x > 0)
    {
        getline(cin, line);
        lines.push_back(line); //add lines to vector, this is assuming you need the lines in memory
        x--;                   //otherwise you could save them directly to the file
    }

    if (File.is_open())
    {
        for (string s : lines)  //writing all the lines to file
        {
            File << s << endl;
        }
        File.close();
    }
}
anastaciu
  • 23,467
  • 7
  • 28
  • 53
  • 1
    This answer has the `ignore()` in the correct place. See how much easier that is? Plus with the `ignore` in close proximity to `cin >> x;` the relationship is more apparent. The only thing I would do different is make it explicit that we're hunting for wascawy newlines and eat up any other debris with [`cin.ignore(numeric_limits::max(), '\n')`](https://stackoverflow.com/questions/25020129/cin-ignorenumeric-limitsstreamsizemax-n) – user4581301 Apr 07 '20 at 23:40
  • @user4581301, yes, I reckon that it's an improvement. – anastaciu Apr 08 '20 at 21:24