-1

I am trying to write a program where you register a bank account and modify it. This is the code (Not full but just trying to experiment with file handling; I am a beginner at programming)

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


     std::ofstream outfile;
    std::ifstream infile;
    std::fstream inout;

struct bank{
    int acc_nr;
    std::string emri;
    std::string mbiemri;
};


std::istream& operator>> (std::ifstream& in, bank& klient)
{
    in >> klient.emri;
    in >> klient.mbiemri;
    in >> klient.acc_nr;
    return in;
}

std::ostream& operator<< (std::ofstream& out, bank& klient)
{
    out << klient.emri << std::endl;;
    out << klient.mbiemri << std::endl;
    out << klient.acc_nr << std::endl;
    return out;
}

std::ostream& operator<< (std::fstream& out, bank& klient)
{
    out << klient.emri << std::endl;;
    out << klient.mbiemri << std::endl;
    out << klient.acc_nr<< std::endl;
    return out;
}

std::istream& operator>> (std::fstream& in, bank& klient)
{
    in >> klient.emri;
    in >> klient.mbiemri;
    in >> klient.acc_nr;
    return in;
}

std::istream &read(bank &klient, std::istream &is)
{
    std::cout << "Jepni emrin: ";
    is >> klient.emri;
    std::cout << "Jepni mbiemrin: ";
    is >> klient.mbiemri;
    std::cout << "Jep numrin e akaundit: ";
    is >> klient.acc_nr;
    return is;
}

const std::ostream &print(bank klient, std::ostream &os) 
{
    std::cout << "Emri: ";
    os << klient.emri;
    std::cout << "\nMbiemri: ";
    os << klient.mbiemri;
    std::cout << "\nNumri i akaundit: ";
    os << klient.acc_nr;
    return os;
}

void read_infile(bank &klient)
{
    read(klient, std::cin);
    outfile.open("C:\\publik\\sample.dat", std::ios::app| std::ios::binary);
    outfile.write(reinterpret_cast <char *>(&klient), sizeof(bank));
    outfile.close();
}

void print_outfile(bank klient)
{
    infile.open("C:\\publik\\sample.dat", std::ios::in| std::ios::binary);
    infile.read(reinterpret_cast <char *>(&klient), sizeof(bank));
    infile.close();
}

void kerko(std::string emri, std::streampos& a)
{
    bank temp;
    inout.open("C:\\publik\\sample.dat", std::ios::in | std::ios::out | std::ios::binary);
    while (inout.read(reinterpret_cast <char *>(&temp), sizeof(bank)))
    {
        if (emri == temp.emri)  // emri = name.
        {
            print(temp, std::cout);
            a = inout.tellg();
            inout.close();
        break;
        }
    }
}



int main()
{
    bank klient;
    bank temp2;
    std::string emri;
    std::streampos a;
    std::cin >> emri;
    bank temp;
    kerko(emri,a);
    std::cout <<std::endl;
    system("pause");
    return 0;
}

The code reads a name, searches through the file and then displays its information. The searching and displaying are successful but I get this error

Unhandled exception at 0x77CFDF58 (msvcp120d.dll) in Banke.exe: 0xC0000005: Access violation reading location 0x00DCAB9C.

The code does not execute past the print function call in the while loop.

Thank you for your time.

Paradox
  • 4,602
  • 12
  • 44
  • 88
Ameljo
  • 1
  • 4
  • 1
    Why do you think you can simply read a text file directly into a struct by pretending it is a `char` array? – Scott Hunter May 25 '15 at 20:25
  • 1
    Well like i told i am a beginner i made the function for the operands "<< and >> " and that work to read in and from file, but i could not modify the just a single account in the middle of the file, because it would not read it as a memory block, the char was the only way i could find. I know that it is wrong that's why i'm asking for a better way. – Ameljo May 25 '15 at 20:29
  • 1
    There are probably better duplicates out there, but this shows a way to handle it: http://stackoverflow.com/questions/22961017/read-write-struct-containing-string-property-to-binary-file You need to serialize your data, you can't just write the whole struct as a blob. If you need to be able to modify data in the middle of the file you're probably going to want to either use an actual database or a fixed size block. – Retired Ninja May 25 '15 at 20:34

1 Answers1

1

There are several things that are wrong here.

First of all you cannot do this:

read(klient, std::cin);
outfile.open("C:\\publik\\sample.dat", std::ios::app| std::ios::binary);
outfile.write(reinterpret_cast <char *>(&klient), sizeof(bank));

your &klient is a complex structure, using a type (std::string) of which you know nothing about its internal layout. It may have pointers pointing 'outside' of it. To read a record you should so something like this;

bank klient ;
std::ifstream istream("name", std::ios::app| std::ios::binary); // or use open
istream >> klient ;

And here we get to second point. This definition is quite ok (I would have used std::ostream instead of std::ofstream but that's a minor point)

std::ostream& operator<< (std::ofstream& out, bank& klient)
{
    out << klient.emri << std::endl;;
    out << klient.mbiemri << std::endl;
    out << klient.acc_nr << std::endl;
    return out;
}

The main point is that when you want to read emri or mbiemri how do you know where the first ends, and the second starts? The simplest way could be insert a space. It works only if emri/mbiemri do not contain spaces themselves, but for a beginner could be a good starting point.

And that's all for now, you have enough to think about...

acraig5075
  • 10,588
  • 3
  • 31
  • 50
marom
  • 5,064
  • 10
  • 14
  • Yes i encountered the problem about emri/mbiemri. But doesn't the std:: endl indicate the end of one and the beginning of the other? – Ameljo May 25 '15 at 20:46
  • And if it is not much to ask. Is there a way where i can write a structure to the file as a whole block, and not one member at a time ? – Ameljo May 25 '15 at 20:48
  • No, you cannot write the structure as a block. To do that you would need to replace std::string with somethng chat[32] but this would tie you to a string length, definitly a weaker solution. – marom May 25 '15 at 20:50
  • Yeah i was using the char but i figured out the string was better. So i need to go back to using the operands to write and read from file and figure a better way to modify an account in the middle of the file? If so could you give me any clue (not the solution I like figure out as much as i can) as what to use or do? – Ameljo May 25 '15 at 20:56
  • Changing an account in the middle of a file is a difficult task, what if a name gets much larger? If your records aren't too much you are better off read all of them, change one and rewrite the whole file. Or give a look at a library like sqlite, but that after you have realized the difficulties of the task at hand... – marom May 25 '15 at 21:02
  • @marom: `std::endl` does not "work as a delimiter", since it is a function. – Lightness Races in Orbit May 25 '15 at 21:45