IPB
ЛогинПароль:

> Внимание!

1. Пользуйтесь тегами кода. - [code] ... [/code]
2. Точно указывайте язык, название и версию компилятора (интерпретатора).
3. Название темы должно быть информативным.
В описании темы указываем язык!!!

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

 
 Ответить  Открыть новую тему 
> Запись и чтение контейнеров(а именно vector), через операторы вставки и извлечения.
сообщение
Сообщение #1


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


Можете привести примеры чтения и записи вектора через операторы << и >>?
я просто пока плохо представляю как это реализовать.. norespect.gif

допустим вот для этого пример :

class Team
{
public :
friend ostream& operator << (ostream& outs, const vector<Team>&);
friend istream& operator >> (istream& sin, vector<Team>&);
friend void file_save(const vector<Team>&);
private:

string TeamName;
int win;
int lose;
int draw;
int score;

};




ostream&  operator << (ostream& outs, const vector<Team>& v) 
{
outs << "Team " << " Wins " << "Loses " << "Draws " << "Scores\n";
for (unsigned int i=0;i<v.size();i++)
{

outs << v[i].TeamName;
set_spaces_t(v,i);
outs << v[i].win << " " << v[i].lose << " " << v[i].draw << " " << v[i].score << "\n";

}

return outs;
}


Как надо правильно переопределить оператор >> для чтения из файла?.
вот функция записи допустим
:
void file_save(const vector<Team>& v){
char filename[15];
cout <<"Enter a file name(without extension) : ";
cin >> filename;
//filename=filename+".sys";
ofstream outfile(filename);
outfile << v;
}



Извиняюсь,Если как-то плохо объяснил что нужно,или наплел тут чуши - голова уже не варит к концу дня.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гость






А зачем, собственно, тебе перегружать операцию ввода/вывода именно для вектора? Это чем-то обосновано? Почему не перегрузить именно для класса, и не читать/добавлять в вектор, пока не достигнем конца файла?

Кстати, пример файла, из которого читаются данные, можно привести?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


ну как видно по коду,он так же будет создан не правильно,ибо туда вводиться все то,что выводит оператор << для класса Team.
Это грубо не правильно,и я это понимаю.Я только решил попробывать.Хм..тоесть ,читать объект,потом делать push_back к этому объекту?в цикле читать..хм..просто я хотел написать метод,который бы читал сразу весь вектор..
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гость






Ну, так напиши себе метод (скажем, такой:

class Team {
public:
file_read(ifstream& fin, vector<Team>& vt);
...
};

), который будет читать поэлементно и делать push_back в вектор. А перегрузку >> делай именно для Team...

Сообщение отредактировано: volvo -
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


хм..сейчас попробую.Кстате,вопрос такой : почему дружественные функции не нарушают принципы инкапсуляции?
Ещё один : почему нельзя для outfile передавать имя файла как string?только чар?а если я хочу что бы пользователь не задавал расширение файла,мне же проще будет написать так :

string filename;
cout <<"Enter a file name(without extension) : ";
cin >> filename;
filename=filename+".sys";
ofstream outfile(filename);

безусловно,в чар-строку можно тоже добавить символы.Просто так же проще,вроде..?


Сообщение отредактировано: Andrewshkovskii -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Гость






Потому, что дружественная функция - это часть интерфейса класса, определяемая разработчиком, а не пользователем, а значит, при правильном использовании дружественных функций, никто ИЗВНЕ доступа туда, куда не надо не получит...

Цитата
почему нельзя для outfile передавать имя файла как string?только чар?а если я хочу что бы пользователь не задавал расширение файла,мне же проще будет написать так :
Собственно, кто мешает:

string filename;
cout <<"Enter a file name(without extension) : ";
cin >> filename;
filename=filename+".sys";
ofstream outfile(filename.c_str(), ios::out);

?

Сообщение отредактировано: volvo -
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


хм..спасибо=)
Написал тут кое-что..только почему-то не хочеть работать..

вот функция сохранения в файл :

void file_save(const vector<Team>& v){
char filename[15];
cout <<"Enter a file name(without extension) : ";
cin >> filename;
//filename=filename+".sys";
ofstream outfile(filename);
for (unsigned int i=0;i<v.size();i++)
outfile << v[i].TeamName <<v[i].win <<v[i].lose << v[i].draw << v[i].score; ;
}


Чтения :
void file_read (vector<Team>& v)
{
Team temp_obj;
char filename[15];
cout << "Input file name : ";
cin >> filename;
ifstream infile(filename);
for (unsigned int i=0;i<v.size();i++)
{
infile >> temp_obj.TeamName >> temp_obj.win >> temp_obj.lose >> temp_obj.draw >> temp_obj.score;
//cout << " here!" << temp_obj.TeamName;
v.push_back(temp_obj);
}

}

Но вектор пуст.Почему?..
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Гость






Цитата
Но вектор пуст.Почему?..
Сам не догадываешься? Чему равен размер вектора при начале операции чтения из файла? 0... А ты поставил условие i < v.size(), которое сразу же НЕ выполняется...

Читать из файла надо, пока ФАЙЛ не закончится, а не зависеть от размера вектора...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


Спасибо и в этот раз...надо всетаки нормально в Лафоре прочитать про потоки и файлы..

Добавлено через 13 мин.
бжж..опять..


Функции :

void file_save(const vector<Team>& v){
string filename;
cout <<"Enter a file name(without extension) : ";
cin >> filename;
filename=filename+".sys";
ofstream outfile(filename.c_str(), ios::out);
for (unsigned int i=0;i<v.size();i++)
outfile << v[i].TeamName <<v[i].win <<v[i].lose << v[i].draw << v[i].score; ;
}

void file_read (vector<Team>& v)
{
Team temp_obj;
string filename;
cout << "Input file name : ";
cin >> filename;
filename=filename+".sys";
ifstream infile(filename.c_str());
while (!infile.eof()&& infile.good())
{
infile >> temp_obj.TeamName >> temp_obj.win >> temp_obj.lose >> temp_obj.draw >> temp_obj.score;
cout <<temp_obj.TeamName;
v.push_back(temp_obj);
}

}


В принципе,записываются данные в файл нормально.
А читаются..видимо в один string(TeamName) заноситься сразу вся информация из файла..как этого избежать?.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Гость






Я ж тебя просил привести пример файла, из которого читаешь информацию... Или показывай, как заполняешь вектор данными, чтобы можно было проверить именно на том файле, который записывается через file_save()...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


содержимое файла :

team11236team21236


Как заполняю вектор?а разве в file_read не написано?или я вопрос не понял ?
:



while (!infile.eof()&& infile.good())
{
infile >> temp_obj.TeamName >> temp_obj.win >> temp_obj.lose >> temp_obj.draw >> temp_obj.score;
cout <<temp_obj.TeamName;
v.push_back(temp_obj);
}
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Гость






Нет, так не пойдет... Надо разделять данные... Хотя бы пробелами smile.gif

Смотри:

team.h
#ifndef TEAM_H_
#define TEAM_H_

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Team
{
friend ostream& operator << (ostream&, const Team& );
friend istream& operator >> (istream&, Team& );
public:
string TeamName;
int win;
int lose;
int draw;
int score;

Team ();
};

// Это - НЕ метод класса, не нужно инициализировать лишний объект,
// чтобы через него вызывать эту функцию.

void file_read(vector<Team>&);

#endif /*TEAM_H_*/




main.cpp
...

ostream& operator << (ostream& os, const Team& ob)
{
os << ob.TeamName << " " << ob.win << " " << ob.lose <<
" " << ob.draw << " " << ob.score;
return os;
}

istream& operator >> (istream& is, Team& ob)
{
int ch; // <--- Добавлено

getline(is, ob.TeamName, ' ');
is >> ob.win >> ob.lose >> ob.draw >> ob.score;

while(is && (ch = is.get()) != '\n'); // <--- Добавлено
return is;
}

void file_read(vector<Team>& vt) {

// Хотя вот это я бы сделал ДО вызова file_read(), и передавал
// бы сюда уже именно открытый поток ввода, как и показал выше

string filename;
cout <<"Enter a file name(without extension) : ";
cin >> filename;
filename = filename + ".txt";

ifstream infile(filename.c_str(), ios::in);
Team t;
while(infile >> t) {
vt.push_back(t);
}
infile.close();
}

vector<Team> vt;
int main() {

file_read(vt); // Читаем

// Проверяем
for(vector<Team>::iterator it = vt.begin(); it != vt.end(); it++) {
cout << *it << endl;
}
return 0;
}

Вот так...

Сообщение отредактировано: volvo -
 К началу страницы 
+ Ответить 
сообщение
Сообщение #13


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


Спасибо за помощь!Но всеравно не много не понимаю пока..ну разберусь.У меня теперь новый вопросsmile.gif
Допустим,имеется какой-то класс с полями int и string.И есть вектор этих объектов v.
Я хочу отсортировать вектор с помощью алгоритма sort() по заданным параметрам,т.е сортировка по i (в порядке возрастания,или убывания), сортировка по str (так же,в порядке возрастания и убывания).Понятно,что для этих типов определен оператор < и оператор >. Но,если я просто вызову функция sort(v.begin(),v.end()); ,то будет ошибка.Так вот, надо ли мне,определять предикат сортировки для каждого из параметров?

Допустим вот так :

#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;

class c{
public :
int c;
string str;
};



bool sortbystr(const c& first,const c& second)
{
return (first.str==second.str);
}

int main() {
vector<c> v;
sort(v.begin(),v.end(),sortbystr);
return 0;
}


Будет ли это правильно?

2ой вопрос : допустим,имеется клас Team

class Team
{
public :

string TeamName;

};


и класс Player :

class Player
{
public :
long int salary;
string Lname;
string team;

};



Необходимо,что бы при вводе поля team, происходила проверка : имеется ли данная команда в векторе класса Team.Т.е.,вводим ли мы реально существующую команду,к которой принадлежит игрок или нет.
С помощью какого алгоритма stl можно сделать данную проверку?find,search или же проще и лучше написать самому(это то я понимаю как написать,но хочется освоить stl алгоритмы)?Если можно,приведите,пожалуйста,пример.

Сообщение отредактировано: Andrewshkovskii -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #14


Гость






Цитата
надо ли мне,определять предикат сортировки для каждого из параметров?
Да, если ты хочешь иметь возможность сортировать вектор по нескольким разным полям...

Цитата
С помощью какого алгоритма stl можно сделать данную проверку?find,search или же проще и лучше написать самому
Гораздо проще будет написать самому...

Update
Хотя... Я тут посмотрел на то, что сделал вчера - есть небольшое добавление, я внес исправления в пост №12, в реализацию operator >> для класса Team. С учетом этого, можно сделать и с помощью алгоритма find_if:

1. Описываем в классе Team константный метод
class Team {
...
string get_team_name() const {
return TeamName;
}
}

2. Описываем также еще одну структуру:
struct check
{
string st;
bool operator() (const Team& t) const {
return (t.get_team_name() == st);
}

check(string s): st(s) {
}
};


3. И теперь проверка делается так:

    ...
vector<Team> vt;

string team; // наличие этой строки в vt будем проверять
cin >> team;

vector<Team>::iterator found;
found = find_if(vt.begin(), vt.end(), check(team)); // Собственно, поиск

// Проверяем, нашлось что-то или нет:
if(found != vt.end()) {
cout << "найдено: " << *found << endl;
}
else {
cout << "не найдено" << endl;
}
...


Сообщение отредактировано: volvo -
 К началу страницы 
+ Ответить 
сообщение
Сообщение #15


Бывалый
***

Группа: Пользователи
Сообщений: 222
Пол: Мужской
Реальное имя: Andrew

Репутация: -  0  +


Ну я отсутствовал в инете пару дней..когда ты сказал проще самому написать,я написал..Только почему-то циклиться,а почему - не пойму.Возможно гдето-то с параметрами напутал..вот такая картина :

void input_p (vector<Player>& v,const vector<Team>& vt)
{
cout <<"Input number of Player's to add : ";
int j;
cin >> j;
Player ob;
for (int k=0;k<j;k++)
AddOne_p(v,ob,vt);
}

void AddOne_p (vector <Player>& v,Player ob, const vector<Team>& vt)
{
cout <<"Input Player last name : ";
cin >> ob.Lname;
cout <<"\nInput team name, in which Player play : ";

while(exsist_c(ob.club,vt))
cin >> ob.club;
cout << "\nInput Player salary : ";
cin >> ob.salary;
v.push_back(ob);
}

bool exsist_c (string& club ,const vector<Team>& vt ) {
bool ye=0;
for (unsigned int i=0;i<vt.size();i++)
{
if(club==vt[i].TeamName)
ye=1;
else
{
cout <<"Entered team does not exsist";
ye=0;
}
}
return ye;
}


вроде подправил,надо было поток очистить..
пипеец..и функция вызывал ДО ввода команды..идиот..проститеsmile.gif

Сообщение отредактировано: Andrewshkovskii -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #16


Гость






Насколько я вижу - вот так будет лучше:

bool exsist_c (string& club, const vector<Team>& vt ) {

for(unsigned int i = 0; i < vt.size(); i++) {
if(club == vt[i].TeamName) return 1;
}
cout <<"Entered team does not exsist"; // Это можно делать только после просмотра всего вектора
return 0;

}
Это первое... Второе - вопрос на засыпку: зачем ты передаешь ob в AddOne_p()? Можно же не тянуть его извне, а описывать прямо внутри этой функции, ты ж все равно не пользуешься (да и не сможешь, передается-то объект не по ссылке, а по значению) введенными данными в самой функции input_p()...
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 18.01.2021 9:07
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name