-2

I am working on a program that reads data from a text file called "phonebook.txt" and displays it in terminal. It ask how many contacts the user wants to add. The user will input the number of contacts he/she wants and the program will output this along with the old contacts from "phonebook.txt" to "updated-phonebook.txt." Now I chose to use a dynamic array over a vector simply because I wanted to get a feel for how to handle memory allocation.

#include <iostream>
#include <string>
#include <fstream> 

#define nullptr 0;


struct Person
{
  std::string lName, fName, streetAddr, city, state, zip, phoneNum;
};

int main ()
{
  std::ofstream outFile;
  std::string dummy;
  int amount, total, count = 0;
  Person *contact;
  //set the pointer to 0 so its not pointing
  //to anything else in memory 
  contact = nullptr;
  std::ifstream inFile("/home/isemanthaj/My_Programs/Class_Programs/Assignment_3/phonebook/phonebook.txt",std::ios::in);
  if (!inFile)
    {
      std::cout << "File failed to open" << std::endl;
    }
  else

  outFile.open("updated_phonebook.txt", std::ios::out);

  std::cout << "How many contacts do you want to add?" << std::endl;
  std::cin >> amount;
  contact = new Person[amount];
   std::cout << "Contacts in the previous book \n" << std::endl;

   std::cin.ignore();

         while (inFile)
    {
      //dummy stores the contact number which is the first line
      // in the read file. I don't want to carry the number over
      // to the other updated_phonebook.txt file
      std::getline(inFile, dummy);
      std::getline(inFile, contact[count].lName);
      std::getline(inFile, contact[count].fName);
      std::getline(inFile, contact[count].streetAddr);
      std::getline(inFile, contact[count].city);
      std::getline(inFile, contact[count].state);
      std::getline(inFile, contact[count].zip);
      std::getline(inFile, contact[count].phoneNum);

      std::cout << contact[count].lName << std::endl;
      std::cout << contact[count].fName << std::endl;
      std::cout << contact[count].streetAddr << std::endl;
      std::cout << contact[count].city << std::endl;
      std::cout << contact[count].state << std::endl;
      std::cout << contact[count].zip << std::endl;
      std::cout << contact[count].phoneNum << std::endl;


      outFile << contact[count].lName << std::endl;
      outFile << contact[count].fName << std::endl;
      outFile << contact[count].streetAddr << std::endl;
      outFile << contact[count].city << std::endl;
      outFile << contact[count].state << std::endl;
      outFile << contact[count].zip << std::endl;
      outFile << contact[count].phoneNum << std::endl;
      count++;
    }
     // I know this is a little wacky here. 
     // I want the program to display the total amount of contacts
     // to the screen
     total = amount + count;

    for (int index = 0; index < total; index++)
     {

       std::cout << "Last name: ";
       std::getline(std::cin, contact[index].lName);
       std::cout << "First name: ";

       std::getline(std::cin, contact[index].fName);
       std::cout << "Street address: ";
       std::getline(std::cin, contact[index].streetAddr);

       std::cout << "City: ";
       std::getline(std::cin, contact[index].city);

       std::cout << "State: ";
       std::getline(std::cin, contact[index].state);

       std::cout << "Zip code: ";
       std::getline(std::cin, contact[index].zip);

       std::cout << "Phone number: ";
       std::getline(std::cin, contact[index].phoneNum);
       std::cout << std::endl;

       std::cout << "Contact: " << index + 1 << std::endl;
       std::cout << "Last name: " << contact[index].lName << std::endl;
       std::cout << "First name: " << contact[index].fName << std::endl;
       std::cout << "Street address: " << contact[index].streetAddr << std::endl;
       std::cout << "City: " << contact[index].city << std::endl;
       std::cout << "State: " << contact[index].state << std::endl;
       std::cout << "Zip code: " << contact[index].zip << std::endl;
       std::cout << "Phone number: " << contact[index].phoneNum << std::endl;
       std::cout << std::endl;
       outFile << "Last name: " << contact[index].lName << std::endl;
       outFile << "First name: " << contact[index].fName << std::endl;
       outFile << "Street address: " << contact[index].streetAddr << std::endl;
       outFile << "City: " << contact[index].city << std::endl;
       outFile << "State: " << contact[index].state << std::endl;
       outFile << "Zip code: " << contact[index].zip << std::endl;
       outFile << "Phone number: " << contact[index].phoneNum << std::endl;


     }

   inFile.close();
   outFile.close();
   delete [] contact;

return 0; 
}

I am trying to store the new contacts the user created and the old contacts from the read file in one dynamic array of structures. Am I getting this segmentation fault because I am using two different indexes "count" and "index" to store the contacts in the same dynamic array?

ZhangBing
  • 45
  • 1
  • 11

1 Answers1

2

Your segfault is happening because you are trying to access an out-of-bounds element of contact array. The size of contact is amount, and you are iterating it from 0 to amount + count. Obviously, amount + count >= amount, so sooner or later you will run out of bounds.

I would suggest you to use std::vector instead of a plain array. You will always be aware of it's size and will be able to iterate it safely.

If you want to keep the arrays, you will have to either reallocate contact after copying the contacts from the old file, to make it size equal to total, or make two separate arrays: one to hold the records from the old file with the size of amount elements, and another one for the newly-added contacts with the size of count elements.

As it is mentioned in the comments, your end-of-file check is wrong, this and this questions are relevant.

Community
  • 1
  • 1
SingerOfTheFall
  • 29,228
  • 8
  • 68
  • 105
  • and he has no sync between the `eof` and the `amount` he is getting from user. – Minato Oct 14 '15 at 12:34
  • Thank you! I prefer vectors too. But I wanted to use a dynamic array as an example for myself to see how to how they work. I think making two separate arrays is a good idea. I will check the posts you referred me too. – ZhangBing Oct 14 '15 at 13:10