Вложенные структуры, чтение данных из файла, разделенного пустой строкой - PullRequest
0 голосов
/ 18 сентября 2018

В настоящее время я работаю над бухгалтерской программой для моего проекта.Я борюсь с чтением из файла во вложенные структуры.Любое руководство о том, куда я должен пойти с этим?Я знаю, что хочу, чтобы он прекратил чтение данных учетной записи и перешел к следующему клиенту, когда достигну пустой строки (нулевой терминатор).По сути, у некоторых клиентов есть несколько учетных записей, у других - более 2 (но не более 5, массив массива содержит только 5).Сам проект гораздо глубже (структуры содержат больше переменных).В настоящее время я просто использую учебный файл, чтобы попытаться выяснить концепцию ..

Вот мой код:

 struct ACCOUNT
 {
 char acct_num[7];
 char balance[8];
 };

 struct CUSTOMER
{ 
char cust_name[20];
char number[5];
ACCOUNT acct[5];
};

int main()
{
  CUSTOMER person[3];
  fstream fin;
  fin.open("accounts.dat", ios::in);
  int i, j;
  i = 0, j = 0;
  char buff[20];
  char line[20];
  while (fin.getline(buff, 20))
    {
    strncpys(person[i].cust_name, buff, 10);
    fin.getline(line, 10);
    strncpy(person[i].number, line, 10);


    do {
        fin.getline(line, 20, ' ');
        strncpy(person[i].acct[j].acct_num, line, 10);
        fin.getline(line, 20);
        strncpy(person[i].acct[j].balance, line, 10);
        j++;
        cin.getline(line, 20);

    } while (*line != 0);
    i++;
}
return 0;
}

Файл данных, который я пытаюсь прочитать:

Jane Smith
FD12
SSDFSS 64.51
SD5545 88.51

John Smith
FD45
SFG789 77.21
NM4521 21.223
MM7888 33.33

John Doe
FSS4
SFGSGG 77.65
HN5555 22.31

1 Ответ

0 голосов
/ 18 сентября 2018

Проблемы, которые я заметил:

Задача 1

strncpys(person[i].cust_name, buff, 10);

Полагаю, вы хотели использовать strncpy, а не strncpys. Даже тогда 10 слишком мало. Вам нужно было использовать 20.

Задача 2

strncpy(person[i].number, line, 10);

Здесь 10 слишком велико. Вам нужно использовать 5.

Задача 3

j необходимо переинициализировать до 0 внутри внешнего цикла.

Задача 4

Логика проверки пустых строк во внутреннем цикле while некорректна. Вы использовали

    cin.getline(line, 20);

как последняя строка в цикле, но я предполагаю, что это ошибка при публикации в SO. Я думаю, что у вас есть

    fin.getline(line, 20);

Это проблема, так как вы используете следующую строку из файла, но данные, содержащиеся в нем, просто отброшены.


Однако, более важные предложения, которые у меня есть:

  1. Переосмыслите стратегию анализа входного файла. Я считаю, что проще всего построчно читать содержимое файла, а затем обрабатывать каждую строку отдельно.

  2. Создайте меньшие функции для чтения различных частей ввода и используйте их из main.

  3. Запишите на стандартный вывод то, что вы прочитали, чтобы вы могли четко видеть, где данные не были прочитаны, как вы и надеялись.

Я бы предложил следующее обновление до main.

int main()
{
   CUSTOMER person[3];
   fstream fin;
   fin.open("socc.in", ios::in);
   int i = 0;

   std::string line;
   while ( getline(fin, line) )
   {
      read_customer_name(line, person[i]);
      std::cout << "cust_name: " << person[i].cust_name << std::endl;

      if ( getline(fin, line) )
      {
         read_customer_number(line, person[i]);
         std::cout << "number: " << person[i].number << std::endl;
      }
      else
      {
         // Read was not successful.
         // Break the loop.
         break;
      }

      // Define it in this scope only.
      int j = 0;
      while ( getline(fin, line) )
      {
         if ( line.empty() )
         {
            break;
         }

         read_customer_account(line, person[i].acct[j]);
         std::cout << "acct[j].acct_num: " << person[i].acct[j].acct_num << std::endl;
         std::cout << "acct[j].balance: " << person[i].acct[j].balance << std::endl;

         j++;
      }
   }
   return 0;
}

где вспомогательные функции:

void read_customer_name(std::string const& line, CUSTOMER& person)
{
   strncpy(person.cust_name, line.c_str(), 20);
}

void read_customer_number(std::string const& line, CUSTOMER& person)
{
   strncpy(person.number, line.c_str(), 5);
}

void read_customer_account(std::string const& line, ACCOUNT& acct)
{
   std::istringstream str(line);
   str.getline(acct.acct_num, 10, ' ');
   str.getline(acct.balance, 10);
}
...