2012-06-12 9 views
0

프로그램의이 부분은 임의 액세스 바이너리 파일에 저장된 모든 레코드를 인쇄해야합니다. 나는 그것을 실행할 때마다, 그것은 모든 레코드를 출력 한 후 액세스 위반 예외가 발생합니다 :C++의 임의 액세스 파일에서 액세스 위반 읽기.

void readFile() 
{ 
    ifstream inFile("hardware.txt", ios::in | ios::binary); 

    if(!inFile) 
    { 
     cerr<<"File could not be opened."<<endl; 
     exit(1); 
    } 

    cout<<left<<setw(10)<<"Account"<<setw(16) 
      <<"Name"<<setw(11)<<"Quantity"<<left<<setw(10)<<"Price"<<endl; 

    Hardware File; 

    inFile.read(reinterpret_cast<char *>(&File), sizeof(Hardware)); 

    while(inFile && !inFile.eof()) 
    { 
     if(File.getAccountNumber() != 0) 
      outputLine(cout, File); 

     inFile.read(reinterpret_cast<char *>(&File), sizeof(Hardware)); 
    } 
} 

가 명확히하기 위해 "하드웨어"Hardware.h에 저장된 클래스입니다.

hardware.h

#ifndef HARDWARE_H 
#define HARDWARE_H 

#include <string> 
using std::string; 

class Hardware 
{ 
public: 
Hardware (int = 0, string = "", int = 0, double = 0); 

void setAccountNumber(int); 
int getAccountNumber() const; 

void setName(string); 
string getName() const; 

void setAmount(int); 
int getAmount() const; 

void setPrice(double); 
double getPrice() const; 
private: 
int accountNumber; 
string name; 
int amount; 
double price; 
}; 

#endif 

hardware.cpp

#include <string> 
using std::string; 

#include "hardware.h" 

Hardware::Hardware(int accountNumberValue, string nameValue, int amountValue, double priceValue)        

{ 
setAccountNumber(accountNumberValue); 
setName(nameValue); 
setAmount(amountValue); 
setPrice(priceValue); 
} 

void Hardware::setAccountNumber(int accountValue) 
{ 
accountNumber = accountValue; 
} 

int Hardware::getAccountNumber() const 
{ 
return accountNumber; 
} 

void Hardware::setName(string nameValue) 
{ 
name = nameValue; 
} 

string Hardware::getName() const 
{ 
return name; 
} 

void Hardware::setAmount(int amountValue) 
{ 
amount = amountValue; 
} 

int Hardware::getAmount() const 
{ 
return amount; 
} 

void Hardware::setPrice(double priceValue) 
{ 
price = priceValue; 
} 

double Hardware::getPrice() const 
{ 
return price; 
} 
+1

'inFile'과'File' (및'Hardware')는 어떻게 정의되어 있습니까? 지금 당장은 코드가 전혀 이해가되지 않는 것처럼 보입니다. 여러분이 갖고있는 코드가 실제로는 아주 못생긴 것입니다. 당신이 아마도 버퍼를 오버런하고있는 것처럼 접근 위반이 들린다. (아마도'File'을 char의 배열처럼 읽었을 때). 확실히 네 줄의 코드에만 "WTF"가 너무 많습니다 (아, 루프 제어도 분명히 잘못되었습니다). –

+0

나머지 기능을 추가 할 것입니다. (여전히 많은 "wtf"가있을 수 있지만) 명확히해야합니다. – David

+0

파일에서 C++ 객체의 원시 바이트를 읽는 것은 매우 나쁜 생각입니다. 거의 항상 정의되지 않은 동작이므로 충돌이 발생합니다. '하드웨어 '는 어떻게 정의 했습니까? – templatetypedef

답변

1

요아킴 말했듯이, 당신은 그런 std::string로 읽을 수 없습니다.

값 유형이 아닙니다. 내부적으로 텍스트를 포함하는 메모리 영역에 대한 포인터를 보유합니다. 파일에서 2 진수의 임의의 blob을 읽는 경우 해당 문자열 포인터는 아무 곳이나 가리킬 수 있습니다. 그것을 역 참조하는 것은 (예를 들어, 'name'의 값을 얻거나 설정함으로써) 액세스 위반이나 segfault 등을 던질 가능성이 있습니다.

나는이 (컴파일 또는 작동하지 않을 수!)처럼, 새로운 방법의 몇 가지를 추가 할 것

:

객체의 내부 구조의
void Hardware::Serialise(std::ostream& stream) const 
{ 
    stream << accountName << "\n" << accountNumber << "\n" << accountValue << std::endl; 
} 
void Hardware::Deserialise(std::istream& stream) 
{ 
    char[1024] buffer; 
    stream.readsome(buffer, 1024); 
    accountName = buffer; 
    buffer >> accountNumber >> accountValue; 
} 

지식은 꽤 중요하다 (드)를 serialising 바르게. 실패 조건, 레코드 간 분리 문자를 처리하고 이름을 읽는 데 fxied-size 버퍼 대신 stringstream을 사용하는 것은 독자에게 운동으로 남겨 둡니다.

+0

대신 무엇을 사용해야합니까? – David

+0

간단한 예제가 답에 추가되었습니다. – Rook