This is my code:

void removeAppointments()
  {
  vector <string> newfile;
  string line;
  int i;
  int n;
  ifstream Appointments;
  ofstream newAppointments;

  Appointments.open(DATAFILE);
  newAppointments.open(newDATAFILE);

  if (Appointments.is_open() && newAppointments.is_open())
    {
    // Read the file until it's finished, displaying lines as we go.
    while (!Appointments.eof())
      {
      getline(Appointments, line, '\n'); // getline reads a line at a time
      newfile.push_back(line);
      }

          while (n != i && n <= newfile.size())
            {
            n = 0;
            newAppointments << newfile[n] << '\n';
            n++;
            }
       
            
    }
  else   // Some kind of error opening the file
    {
    cout << "ERROR: Could not open the datafile(s)" << endl;
    exit(1);
    }
  
  newAppointments.close();
  Appointments.close();
  remove(DATAFILE);
  rename(newDATAFILE, DATAFILE);
 }

int main(int argc, char *argv[])
    {
    //Appointment appointment;
    int i = atoi(argv[1]) - 1;
    removeAppointments();
    }

However when I use the program, it simply deletes the entire datafile.

Dani AI

Generated

The behavior described is classic: the program opens the new file (which truncates it), then fails to write the expected lines because of logic/initialization/index errors, and finally replaces the original with an empty file. pointed toward the right areas, but a few additional, concrete fixes will make the routine robust and easy to debug.

Prefer streaming into a temporary file and skipping the unwanted line while reading; this avoids holding the whole file in memory and prevents out‑of‑range indexing. Example (different from the code in the thread):

bool remove_line_at(const std::string& path, std::size_t remove_index) {
  std::ifstream in(path);
  std::ofstream out(path + ".tmp");
  if (!in || !out) return false;
  std::string line;
  std::size_t idx = 0;
  while (std::getline(in, line)) {
    if (idx++ == remove_index) continue;
    out << line << '\n';
  }
  in.close();
  out.close();
  return std::remove(path.c_str()) == 0 && std::rename((path + ".tmp").c_str(), path.c_str()) == 0;
}

Practical debugging and safety checklist:

  • Validate command-line input (check argc) and convert safely (catch exceptions from std::stoul). Subtracting 1 can underflow; guard against that.
  • Use std::getline in the loop condition (not while(!eof())).
  • Use std::size_t for sizes/indices and initialize all locals before use (uninitialized int i, n; causes undefined behavior).
  • Only remove/rename the original after a successful write/close; test return codes from remove/rename.
  • Add simple debug prints (index value, number of lines processed) while developing.

These steps complement the loop-fix ideas already posted and will prevent the whole-file-truncation symptom while making the function safe and predictable. , after applying the above, the second-line case should no longer erase everything after the removed line.

Recommended Answers

All 7 Replies

This is my code:

void removeAppointments()
  {
  vector <string> newfile;
  string line;
  int i;
  int n;
  ifstream Appointments;
  ofstream newAppointments;

  Appointments.open(DATAFILE);
  newAppointments.open(newDATAFILE);

  if (Appointments.is_open() && newAppointments.is_open())
    {
    // Read the file until it's finished, displaying lines as we go.
    while (!Appointments.eof())
      {
      getline(Appointments, line, '\n'); // getline reads a line at a time
      newfile.push_back(line);
      }

          while (n != i && n <= newfile.size())
            {
            n = 0;
            newAppointments << newfile[n] << '\n';
            n++;
            }
       
            
    }
  else   // Some kind of error opening the file
    {
    cout << "ERROR: Could not open the datafile(s)" << endl;
    exit(1);
    }
  
  newAppointments.close();
  Appointments.close();
  remove(DATAFILE);
  rename(newDATAFILE, DATAFILE);
 }

int main(int argc, char *argv[])
    {
    //Appointment appointment;
    int i = atoi(argv[1]) - 1;
    removeAppointments();
    }

However when I use the program, it simply deletes the entire datafile.

I assume you mean it doesn't delete the original file, rather the new file you produce is 0 bytes? The two obvious problems are your "i" and "n" variables. The first problem: You must pass "i" to your function removeAppointments. Right now you declare "i" inside main, so it is only visible to main. Therefore your function declaration should be void removeAppointments(int i).

The other problem is that you are setting n = 0 inside your while loop. How will "n" ever be as large as "i" if you set it to 0 at the beginning of each iteration? Move n = 0 to before the while loop starts.

On a side note: if (_open() && _open()) with all of your code inside is fine, but it's a little strange for simple programs. Most programmers put those right after the open function. i.e.
fin.open(file);
if (!fin.is_open()) exit(1);
And then you can just simply write all your code after that and not worry about it.

Thanks I have done what you have told me so far.. However when I use the program and i remove the last line of the file, everything works perfectly. But when I, say, remove the second line of the file, all the lines after that second line also get removed...

I can kind of see why that might be myself.. due to the line

while (n != i && n <= newfile.size())

But I'm not sure how else to go about it.

Yeah if you break out of the loop once the "i" line is encountered, then obviously you won't write the rest of the file. You only want to skip one iteration of the loop. Also, you should have the condition "n < newfile.size()" and NOT "n <= newfile.size()". Why? Remember vectors and arrays start at 0, not 1. So if if you're allowing n to be equal to size(), well... what happens if for example the size() is equal to 1? In your vector, only newfile[0] would contain an element, but you'd be accessing newfile[1] which is out of range!

To skip only 1 line in a file, you would put:

while (n < newfile.size()){
  if (i == n) {n++; continue;}  //increments n and goes to beginning of loop
  newAppointments << newfile[n] << '\n';  
  n++;                     
}

Wow so the 'continue' allows the n to skip? Thanks for the tremendous help from both of you!

Both of me? I do the job of two mans. Especially in the bedroom areas... you know... with the ladies.

Hahahaahha you were too good I thought you had to be two different people :D

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.