2015-11-30 5 views
1

Я только начал изучать файлы, и я понимаю, как настроить его и заставить его работать. Я должен написать эту программу, где я должен разрешить пользователю вводить некоторую информацию, и пользователь также обновляет и корректирует любые данные, используя двоичный файл. Так что я могу написать до момента, когда пользователь может писать и читать из файла. Но я не знаю, как разрешить пользователю настраивать данные или добавлять данные.У меня возникли проблемы с пониманием файлов в C++

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

using namespace std; 

class client { 
public: 
    string name; 
    int balance; 
    string id; 

}; 

int main() 
{ 
    int ans; 
    int x; 
    string nameIn; 
    string adjName; 
    client client1; 
    ofstream out("client1.dat", ios::binary); 

    cout << "\nDo you want to add information or update info" << endl; 
    cin >> ans; 
    if (ans == 1) 
    { 
    cout << "\nPlease enter the name of your client" << endl; 
    cin >> nameIn; 
    x = nameIn.length(); 
    if (x <= 10) 
    { 
     for (int i; i < 10; i++) 
     { 
      adjName[i] = nameIn[i]; 
     } 
    } 
    else 
    { 

     for (int i = x; i < 10; i++) 
     { 
      adjName[i] = ' '; 
     } 
    } 
    client1.name = adjName; 
    cout << "\nPlease enter the balance of your client" << endl; 
    cin >> client1.balance; 
    cout << "\nPlease enter the id of your client" << endl; 
    cin >> client1.id; 

    cout << "\nThe name of your client is " << endl << client1.name 
     << endl << "\nThe balance of your client is " << endl 
     << client1.balance << endl << "\nThe id of your client is " 
     << endl << client1.id; 

    out.write(reinterpret_cast<const char*> (&client1), sizeof(client)); 

} 
/* 

else if (ans == 2) 
{ 
    string answer, newName,line; 
    cout << "\nWhat name do you want to update? " << endl; 
    cin >> answer; 
    cout << "\nWhat is the new name?" << endl; 
    cin >> newName; 

    if (out) 


} 
*/ 
system("pause"); 
return 0; 

}

поэтому имя должно быть длиной всего 10 символов, так что мы можем настроить/обновить. Он компилируется и запускается, но каждый раз, когда компилятор добирается до той части, где он проверяет длину имени, он угасает и говорит, что «ошибка отладки не выполнена» строковый индекс вне диапазона.

Также об этом коде - если я запускаю его без битов, где вы настраиваете имя на определенную длину массива, программа запускается и сохраняет все красиво. Но когда я пытаюсь прочитать файл .dat, он читает его обратно, но выходит с нарушением прав доступа, заставляя меня вручную остановить отладку. Что я делаю не так?

это код для чтения файла

#include <iostream> 
#include <fstream> 
#include <string> 
using namespace std; 
class client { 
public: 
string name; 
int balance; 
string id; 
}; 

int main() 
{ 
    client client1; 
    char ans; 
    cout << "\nDo you want to view the information about your client?" 
    << endl; 
    cin >> ans; 
    ifstream in("client1.dat", ios::binary); 

    if (ans == 'y' || ans == 'Y') 
    { 
     in.read(reinterpret_cast<char*> (&client1), sizeof(client)); 
     cout << "The name is " << endl << client1.name << endl 
      << "The balance is " << endl << client1.balance << endl 
      << "The id is " << endl << client1.id << endl; 
} 
    system("pause"); 
    return 0; 
} 
+1

Вы не можете сериализовать не такие типы POD, как 'std :: string', в двоичный файл. 'std :: string' внутренне содержит указатель на данные в куче, которые не могут быть восстановлены после чтения из файла. –

+0

Привет, не могли бы вы прояснить. POD? Я все еще новичок и потеряюсь с файлами. Связано ли это с reinterpret_cast? –

+1

Добро пожаловать в переполнение стека. Этот код слишком длинный и сложный для проблемы, которую вы пытаетесь решить. При написании кода вы должны разрабатывать новые функции в изоляции, и при обращении за помощью вы должны отправить [минимальный полный пример] (http://stackoverflow.com/help/mcve). Кажется, вы спрашиваете о нескольких ошибках; выберите один и подготовьте код, который пытается сделать * одну вещь *, и если это не сработает, покажите нам это. – Beta

ответ

1

Что касается 1-й части:

for (int i; i < 10; i++) 
     //^

промаха для инициализации i к нулю. И что, если ввод был меньше 10 символов? Вы получите доступ к std::string за пределы. Вы должны заменить if/else и петли с просто

adjName = nameIn; 
while(adjName.length() <= 10) { 
    adjName += ' '; 
} 

, чтобы избавиться от отладки утверждения.


Для 2-й части вопроса, как уже упоминалось в комментариях вы не можете сделать это со структурой, содержащей классы, как std::string.

reinterpret_cast<char*> (&client1) просто зафускирует, что std::string использует указатель на динамически выделенные символьные данные внутри, и это невозможно восстановить осмысленно при чтении сохраненных данных позже (следовательно, нарушение прав доступа вы получаете).

жизнеспособный способ может использовать что-то вроде

struct client { 
    char name[11]; 
    int balance; 
    char id[5]; 
}; 

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

Но вы быстро можете увидеть недостатки, что данные символов должны быть исправлены по размеру, и вы не можете иметь произвольные длины строк. Я никогда не использовал бы такой код для готового продукта.

Еще одна ошибка (как упоминалось выше) заключается в том, что int не представляется таким же образом (порядка байтов, используемых, например, endianess) одинаковым образом для разных архитектур процессора. Таким образом, двоичный файл нельзя использовать портативно с разными компьютерами.


Самое простое решение не использовать бинарный файл, но текстовый файл в формате и перегружать std::ostream& operator<<(std::ostream&, const client&) и std::istream& operator>>(std::istream&, client&) выход/вход операторов.

Или используйте некоторую стороннюю библиотеку, например boost::serialization, или буферы протокола google, которые поддерживают дезадаптацию/сериализацию в двоичные файлы.

+0

хорошо, поэтому я следил за вашими инструкциями, и вот где я добрался до –

+0

@JackFaber Хорошо, если вы считаете, что ответ был полезен и решил ваши проблемы, подумайте о том, чтобы принять его, нажав на большую белую галочку на левой стороне :-) ... –

+0

Я не мог опубликовать код здесь, поэтому я разместил его как ответ - не могли бы вы его просмотреть. спасибо –

Смежные вопросы