Tell me, please, what is the error.

I have three functions: writing to a file, reading from a file, and counting records in a file.

There are 3 arguments in my program: 1st character, 2nd number of records that I want to output, and 3rd file name. Class declaration:

#pragma once #include <iostream> #include <string> #include "String.h" #include <fstream> #include <vector> #define string String #define END std::endl typedef double d; typedef int i; class City { private: string Name; i Ppl; d Area; i Birth; i Schools; std::ofstream wRecord; std::vector<string> lines; std::ifstream readRecord; public: City(); ~City(); void showInfo(); void getData(); void diskIn(int n,int r ); void diskOut(int num); static int diskCount(); }; 

Definition of class methods:

 #include "City.h" #include "String.h" #include <iostream> #include <fstream> #include <io.h> City::City() : Name("NoName"), Ppl(0), Area(0.0), Birth(0), Schools(0) {} City::~City() { wRecord.close(); readRecord.close(); } void City::showInfo() { std::cout << "Name\t\t" << "People\t\t" << "Area\t\t" << "Birth\t\t" << "Schools\t\t" << END; std::cout <<""<<Name<<"\t\t" << Ppl<<"\t\t" << Area<<"\t\t" << Birth<<"\t\t" << Schools<< END; } void City::getData() { std::cout << "Enter a name of the city: "; (std::cin >> Name).get(); std::cout << "Enter quanity of people in the city: "; std::cin >> Ppl; std::cout << "Enter area of the city: "; std::cin >> Area; std::cout << "Enter a year of foundation of the city: "; std::cin >> Birth; std::cout << "Enter quanity of schools in the city: "; std::cin >> Schools; } void City::diskIn(int n,int r)//Чтение { std::ifstream readRecord; readRecord.open("6.bin", std::ios::binary); readRecord.seekg(n * sizeof(City)); std::cout << n << END; for (int i = 0; i < r; i++) { readRecord.read((char*)this, sizeof(*this)); } } void City::diskOut(int num) //Запись { std::ofstream wRecord; wRecord.open("6.bin", std::ios::binary); for (int i = 0; i < num; i++) { wRecord.write((char*)this, sizeof(*this)); } } int City::diskCount()//Подсчет { std::ifstream readRecord; readRecord.open("6.bin", std::ios::binary); readRecord.seekg(0, std::ios::end); return (int)readRecord.tellg() / sizeof(City); } 

My object:

 City c; if (argv[1] == create){ int n = atoi(argv[2]); std::cout << "1 " << argv[1] <<"2 "<<argv[2] <<"3 "<<argv[3]<< END; for (int j = 0; j < n; j++) { c.getData(); c.diskOut(n); } } if (argv[1] == read) { int n = City::diskCount(); int r = atoi(argv[2]); std::cout << "1 " << argv[1] << "2 " << argv[2] << "3 " << argv[3] <<"r"<<n <<END; std::cout << "In file: " << n << "cities" << END; for (int i = 0; i < n; i++) { c.showInfo(); c.diskIn(i,r); } } 

My problem is that I cannot read from the recording file, only the default constructor is diskIn . The diskIn clearly in diskIn . It is necessary to read not the entire file, but a certain amount in it, if I remove my cycles from diskIn и diskOut , then the program works, BUT reads everything.

I want to ask the user how much he wants to see the records, if he wants more than what is in the file, then output the appropriate message and then output all the entries. And if there are 2 entries out of 3, then output exactly 2.

  • Show the City class declaration. In 99% of cases, read like this - readRecord.read((char*)this, sizeof(*this)); - it's just run into trouble ... Yes, and what does your reading in a cycle in the same place mean? ... - Harry
  • @Harry Fixed, I create my class String , it has been checked several times with no problems. Read in a loop to count readRecord.seekg(n * sizeof(City)); how many in the file place - Nikita Gusev

1 answer 1

With your City class, absolutely forget about writing / reading in a simple binary form! It is possible to write / read just the contents of the memory for what is called plain old data, i.e. fundamental types without pointers ...

For example, you have a string Name; field in it string Name; . What will you record? Think Name Contents? Not a bit, look inside the file yourself. There will most likely be written a pointer to a place in memory where the string itself is located. When reading with the same execution, you can still point to the same place in memory. But save the file, and then read in another program - and you will not understand that in what place ...

I am silent about the vector of lines or flow ...

You must have your own function that correctly writes each field, and, accordingly, reads it correctly. Each one . And the corresponding reading function.

For example, it writes the string as first the length, then the number of bytes of the string specified in the length. Reads - on the contrary: first, length, then allocates a buffer in memory and reads into it ...

Writing to a file and reading things like

 std::ofstream wRecord; 

no sense at all.

And as a PS - for this

 typedef double d; typedef int i; 

as well as for such

 #define string String 

programmers younger coccyx massaged. In a week, you yourself will understand what i . Or why suddenly the compiler hangs mats on

 for(int i = 0; i < N; ++i) 

Just like any attempt to later use the standard line will doom to terrible hemorrhoids ...

Another PPS - why do you keep threads in a class object? What is the deep meaning of it? At a minimum, you yourself cut the possibility of copying, but this is a side effect. Does the city itself contain any file streams? Even if it is not a city, but just an object - why should it contain files from which it is read / written? They are in relation to the object - external entities ...

  • Well, as soon as you take the streams out of the city, the string and vector of strings will remain. The rest of the things you write-read, as always - such as write((char*)Area,sizeof(Area)); . Line - I have already suggested how. A vector is first the total number of lines in it, and then all the lines in turn. To read is exactly the same: first the total number of records, then the cycle for this number of reading lines and inserting into a vector Equip your class line immediately with write and read functions (just pass the stream as a parameter! Do not enter it into the line) - it will be easier to write the city saving / writing. - Harry
  • You are completely right in everything! The mood dropped to 0 :) I understood the mistakes, I will correct myself and look for ways out, thanks for the answer. It takes a lot of time .. - Nikita Gusev
  • one
    Try it in pieces. Work out your line - write / read, there will be practice and understanding. Then go to the next stage ... - Harry
  • @Harry and why can't you do that?) I’ve had lines #typedef pair<int,int> pii and #define int long long (the last one when I continued with the size). - pavel
  • @pavel It is impossible and not recommended - different things. If the compiler is not against it, then it is possible ... but this still does not mean that it should be done this way. Frankly, in your examples, in the first case I would give a more understandable name, and in the second case I would simply not do so, preferring to perform a replacement. - Harry