Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 15, средняя оценка - 4.93
Korhall
7 / 7 / 1
Регистрация: 02.03.2013
Сообщений: 69
#1

Как реализовать метод ToString? - C++

27.06.2013, 09:56. Просмотров 2175. Ответов 22
Метки нет (Все метки)

Здравствуйте, коллеги.
Выручайте, кто может.
Я написал программу по слудеющему заданию.
Создать класс задающий данные для визитной карточки, внесенные данные потом записать в файл.
Все сделано с раздельной компиляцией: card.h - класс; met.h - описание функций; main.cpp - понятно.
Писалось в Visual stiduo 2008
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// main.cpp
#include <iostream>
#include "card.h"
#include <vector>
#include <fstream>
 
using namespace std;
 
// вывод на печать
        void viv(std::string cname, std::string clast_name, std::string ctel, std::string cemail)
        {
            std::cout << cname << "\t "
        << clast_name << " \t "
        << ctel << "\t" << cemail << "\t" << std::endl;
        }
 
// запись в файл
        void save(std::string cname, std::string clast_name, std::string ctel, std::string cemail)
        {
            
    ofstream fout;
        fout.open("base.txt", std::ios::app);
    fout << cname << " " << clast_name << " " 
        << ctel << " " << cemail; 
    fout<< std::endl;
    fout.close();
            
        }
 
int main()
{
    // Создание объекта класса visit
    
 
    std::string name;
    std::string last_name;
    std::string tel;
    std::string email;
    
    // Ввод имени с клавиатуры
    std::cout << "Name: ";
    getline(std::cin, name);
 
    // Ввод фамилии
    std::cout << "Last name: ";
    getline(std::cin, last_name);
 
    // Ввод номера телефона
    std::cout << "Telephone number: ";
    getline(std::cin, tel);
 
    // Ввод адреса электронной почты
    std::cout << "E-mail: ";
    getline(std::cin, email);
 
    //передача параметров конструктору
    
    visit card(name, last_name, tel, email);
 
    viv(name, last_name, tel, email);
    save(name, last_name, tel, email);
        // Считываем построчно записи...
    /*    vector<visit> v;
 
        v.push_back(name);
        v.push_back(last_name);
            v.push_back(tel);
            v.push_back(email);
 
        for (int i=0; i < v.size(); i++)
            cout << v[i] << " " ;
        cout << endl;
        cout << v.capacity();
        cout << endl;  */
 
 
    return 0;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// card.h
#pragma once /* Защита от двойного подключения заголовочного файла */
#include <string>
#include <vector>
 
 
using namespace std;
class visit {
    public:
        // Установка имени
        void set_name(std::string);
        // Получение имени
        std::string get_name();
        // Установка фамилии
        void set_last_name(std::string);
        // Получение фамилии
        std::string get_last_name();
        // Установка номера телефона
        void set_tel(std::string);
        // Получение номера телефона
        std::string get_tel();
        // Установка адреса электронной почты
        void set_email(std::string);
        // Получение адреса электронной почты
        std::string get_email();
        //деструктор класса visit
        //visit::~visit();
        //конструктор класса visit
        visit(std::string cname, std::string clast_name, std::string ctel, std::string cemail);
        
 
    private:
        // номер телефона
        string tel;
        // адрес электронной почты
        string email;
        // Имя
        std::string name;
        // Фамилия
        std::string last_name;
 
 
 
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// met.h
#include <string>
#include "card.h"
#include <iostream>
#include <vector>
 
using namespace std;
 
// конструктор visit
    visit::visit(std::string cname, std::string clast_name, std::string ctel, std::string cemail)
    {
        visit::set_name(name);
        visit::set_last_name(last_name);
        visit::set_tel(tel);
        visit::set_email(email); 
 
    }
 
//деструктор visit
//  visit::~visit();
 
 
 
 
// Установка имени 
void visit::set_name(std::string cname)
{
    visit::name = cname;
}
 
// Получение имени 
std::string visit::get_name()
{
    return visit::name;
}
 
// Установка фамилии 
void visit::set_last_name(std::string clast_name)
{
    visit::last_name = clast_name;
}
 
// Получение фамилии
std::string visit::get_last_name()
{
    return visit::last_name;
}
 
// Установка номера телефона
void visit::set_tel(std::string ctel)
{
    visit::tel = ctel;
}
// Получение номера телефона
std::string visit::get_tel()
{
    return visit::tel;
}
// Установка адреса электронной почты
void visit::set_email(std::string cemail)
{
    visit::email = cemail;
}
// Получение номера телефона
std::string visit::get_email()
{
    return visit::email;
}
Проблема в том, что в процессе написания семестровой задание изменилось:
1)
надо реализовать вектор. Я его сделал и он работает (в main.cpp). Но пришлось его закоментить, т.к. оказалось, что я реализовал не тот вектор, который хочет видеть препод. У меня просто vector<string> а ему надо vector<visit>, т.е. вектор класса (если я правильно это называю. Если я исправляю на vector<visit> то компилятор ругается. До меня пока никак не дойдет в чем проблема. Где-то в интернете видел решение, но пповторно найти этот сайт не могу.
Подскажите, как реализовать вектор?

2) Необходимо реализовать 2 метода вывода в строку и проверки вывода. У меня просто реализован потоковый метод cout. И все замечательно работает. Но преподавателю такой подход не нравится почему-то. Должно быть что-то вроде:
C++
1
2
3
4
std::string ... tostring()
{
...
}
и
C++
1
2
3
4
bool fromstring(sring src)
{
...
}
Не удается найти какого-либо материала об этом. Подскажите, что это за операторы и как ими пользоваться.

3)
Прошу объяснить, что за проблема с деструктором. Пришлось его закоментить иначе компилятор ругается, что деструктор объявлен повторно.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
nxtech
77 / 59 / 2
Регистрация: 26.06.2013
Сообщений: 198
27.06.2013, 11:06     Как реализовать метод ToString? #2
1) Вы не правильно работаете с вектором. У вас элементы контейнера должны быть типа visit, а вы пытаетесь запихать туда значения типа std::string.
2) Ну и возвращайте из tostring что-то типа name + " " + last_name + " " + ...
3) У вас повтороно объявлен деструктор, а нужно реализацию написать типа visit::~visit(){//реализация}
Korhall
7 / 7 / 1
Регистрация: 02.03.2013
Сообщений: 69
27.06.2013, 11:57  [ТС]     Как реализовать метод ToString? #3
nxtech, с деструктором я разобрался. Спасибо.
А вот с остальным пока глухо:
давайте начнем с простого. Что такое будет Tosring? Это оператор или переменная?
По контейнеру: как синтаксически прописать элементы контейнера типа visit?
lowercase
212 / 201 / 34
Регистрация: 09.05.2012
Сообщений: 494
27.06.2013, 12:23     Как реализовать метод ToString? #4
В таких языках как C# и Java метод toString() широко используется и служит для представления данных обьекта в виде строки. В этого метода (в выше приведенных языках) есть определнная реализация по-умолчанию (например, в java возвращается строка с полным именем класса + '@' + хеш код обьекта), которую можно свободно перепределить при надобности.

например у вас есть класс:
C++
1
2
3
4
5
6
7
8
9
10
11
class Car {
   string brand;
   string model;
   int color;
   Engine engine; // для простоты предположим что этот класс уже описан
public:
   string toString() { 
      string str = brand + ": " + model;
      return str;
   }
}
это одна из возможных реализаций этого метода. как видете вы никому не обязаны возвращать в строковом представлении полностью всю информацию которую хранит обьект, но темнеме сделать это вам тоже никто не запрещает.
будь у Engine тоже метод toString() было бы очень весело:
C++
1
2
3
4
string toString() { 
   string str = brand + ": " + model + "; color: " + nameForColor(color) + "; engine: " + engine.toString();
   return str;
}
то есть как видите реализация может быть разной. все зависит от ваших нужд. если обьект имеет очень много полей то его строковое представление будет очень громоздким, особенно если вызывать toString() для всех обьектов которые используются в текущем классе в качестве полей.
Korhall
7 / 7 / 1
Регистрация: 02.03.2013
Сообщений: 69
27.06.2013, 14:17  [ТС]     Как реализовать метод ToString? #5
Спасибо за разъяснения. Вот что у меня получилось.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
//card.h
    string toString(); ..объявляю фнкцию в классе
 
//met.cpp
//передача в string
string toString(std::string cname, std::string clast_name, std::string ctel, std::string cemail) //реализация функции
{ 
    string str = cname + " \t " + clast_name + " \t " + ctel + " \t " + cemail ;
      return str;
   }
 
//main.cpp
    toString(name, last_name, tel, email);
кмопилятор пишет что идентификатор tostring не найден. Инклуды подключены везде.
Что у меня не так?

Добавлено через 1 час 33 минуты
А что если использовать такой вариант:
C++
1
2
3
4
5
6
7
8
9
string toString(std::string cname, std::string clast_name, std::string ctel, std::string cemail)
{ 
string str;
    std::ostream& operator << (std::ostream& str, const visit& );
 
      return str;
 
      
   }
nxtech
77 / 59 / 2
Регистрация: 26.06.2013
Сообщений: 198
27.06.2013, 15:04     Как реализовать метод ToString? #6
Я думаю вам нужно сделать tostring методом класса, тогда и параметры не потребуются:
C++
1
2
3
4
std::string visit::tostring()
{
    return (name + " \t " + last_name + " \t " + tel + " \t " + email);
}
Korhall
7 / 7 / 1
Регистрация: 02.03.2013
Сообщений: 69
27.06.2013, 15:10  [ТС]     Как реализовать метод ToString? #7
Это я делал. А в main писал:

C++
1
    toString(name, last_name, tel, email);
компилятор все равно пишет что tostring идентификатор не найден
nxtech
77 / 59 / 2
Регистрация: 26.06.2013
Сообщений: 198
27.06.2013, 15:14     Как реализовать метод ToString? #8
Так нужно использовать с экземпляром класса:
C++
1
2
3
4
5
visit card("vasya", "pupkin", "+71111111111", "vasya@mail.ru");
std:string str = card.tostring();
std::cout << str << std::endl;
// или
std::cout << card.tostring() << endl
Korhall
7 / 7 / 1
Регистрация: 02.03.2013
Сообщений: 69
27.06.2013, 15:37  [ТС]     Как реализовать метод ToString? #9
в card.h
C++
1
2
3
4
std::string visit::tostring()
{
    return (name + " \t " + last_name + " \t " + tel + " \t " + email);
}
в main
C++
1
2
3
    visit card(name, last_name, tel, email);
 
std::cout << card.tostring() << endl;
Да, все компилируется, только в консоли ничего не печатается.
Если закомментить в card.h фуекцию, тогда уже ошибка.
Я наверное туплю, но реально не доходит, что с этим делать и главное где почитать из разряда "для тупых".
nxtech
77 / 59 / 2
Регистрация: 26.06.2013
Сообщений: 198
27.06.2013, 15:56     Как реализовать метод ToString? #10
Это
Цитата Сообщение от Korhall Посмотреть сообщение
visit::visit(std::string cname, std::string clast_name, std::string ctel, std::string cemail)
* * {
* * * * visit::set_name(name);
* * * * visit::set_last_name(last_name);
* * * * visit::set_tel(tel);
* * * * visit::set_email(email);
}
Вы замените в теле конструктора имена полей на имена параметров, т.е. name на cname и т.д.

Добавлено через 2 минуты
А вообще лучше так написать конструктор:
C++
1
2
3
4
visit::visit(std::string cname, std::string clast_name, std::string ctel, std::string cemail) :
name(cname), last_name(clast_name), tel(ctel), email(cemail)
{
}
Korhall
7 / 7 / 1
Регистрация: 02.03.2013
Сообщений: 69
27.06.2013, 16:00  [ТС]     Как реализовать метод ToString? #11
nxtech, спасибо большое. Все заработало. Но, если честно не понятно почему. Был бы очень благодарен за разъяснения.
nxtech
77 / 59 / 2
Регистрация: 26.06.2013
Сообщений: 198
27.06.2013, 16:06     Как реализовать метод ToString? #12
Вообще в данном случае лучше передавать параметры во все методы и конструктор по константной ссылке:
C++
1
2
3
4
5
6
7
8
9
visit::visit(std::string const& cname, std::string const& clast_name, std::string const& ctel, std::string const& cemail) :
name(cname), last_name(clast_name), tel(ctel), email(cemail)
{
}
 
void visit::set_name(std::string const& cname)
{
    name = cname;
}
и т.п.
Только не забудьте в объявлениях методов соответствующие изменения внести.
В этом случае не будут создаваться временные объекты std::string
Korhall
7 / 7 / 1
Регистрация: 02.03.2013
Сообщений: 69
27.06.2013, 16:13  [ТС]     Как реализовать метод ToString? #13
Я так понимаю, что & указывает на адрес переменной. Правильно?
Правда препод жутко не любит, когда я такие вещи делаю. У меня конструктор был через указатель. Он мне его зарубил. Ну да ладно.
А вот как быть с вектором?
abit
260 / 259 / 33
Регистрация: 03.02.2013
Сообщений: 709
27.06.2013, 16:19     Как реализовать метод ToString? #14
Цитата Сообщение от Korhall Посмотреть сообщение
Я так понимаю, что & указывает на адрес переменной. Правильно?
нет, это ссылка, т.е. разыменованный указатель

Цитата Сообщение от Korhall Посмотреть сообщение
Правда препод жутко не любит, когда я такие вещи делаю.
применение ссылки и с const там как раз хороший код

Цитата Сообщение от Korhall Посмотреть сообщение
У меня конструктор был через указатель.
это как?
Korhall
7 / 7 / 1
Регистрация: 02.03.2013
Сообщений: 69
27.06.2013, 16:24  [ТС]     Как реализовать метод ToString? #15
Извиняюсь, не конструктор а создание объекта
C++
1
visit *card=new visit(name, last_name, tel, email);
а потом я его через delete сносил.
nxtech
77 / 59 / 2
Регистрация: 26.06.2013
Сообщений: 198
27.06.2013, 17:11     Как реализовать метод ToString? #16
С вектором все просто.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
std::vector<visit> v;
// Резервируем место в контейнере для трех элементов.
v.reserve(3);
// Обратите внимание размер == 0, а вместимость == 3.
std::cout << "size: " << v.size() << std::endl;
std::cout << "capacity : " << v.capacity() << std::endl << std::endl;
 
// Добавляем элементы в контейнер.
v.push_back(card);
v.push_back(visit("Vanya", "Ivanov", "+72222222222", "vanya@mail.ru"));
v.push_back(visit("Petya", "Petrov", "+73333333333", "petya@mail.ru"));
// Выводим содержимое контейнера.
for (unsigned int i = 0; i < v.size(); i++)
    std::cout << v[i].tostring() << std::endl;
// Размер контейнера изменился.
std::cout << "size: " << v.size() << std::endl << std::endl;
 
// Освобождаем контейнер.
v.pop_back();
for (unsigned int i = 0; i < v.size(); i++)
    std::cout << v[i].tostring() << std::endl;
// Размер контейнера изменился.
std::cout << "size: " << v.size() << std::endl << std::endl;
 
v.pop_back();
for (unsigned int i = 0; i < v.size(); i++)
    std::cout << v[i].tostring() << std::endl;
// Размер контейнера изменился.
std::cout << "size: " << v.size() << std::endl << std::endl;
 
v.pop_back();
// Размер контейнера изменился (должен быть пуст).
std::cout << "size: " << v.size() << std::endl << std::endl;
Что нужно учитывать:
Если не использовать std::vector::reserve, то может выполняться интенсивное перераспределение памяти.
При таком виде std::vector<visit> при добавлении в контейнер происходит копирование всего объекта.


Я не проверял код, может где-то опечатался
Korhall
7 / 7 / 1
Регистрация: 02.03.2013
Сообщений: 69
27.06.2013, 21:44  [ТС]     Как реализовать метод ToString? #17
Спасибо, nxtech.
Вечером попробую и отпишусь.

Добавлено через 4 часа 31 минуту
nxtech, спасибо тебе огромное. Все работает.
Теперь хотя бы понятно.rак стыковать векторы и класы в принципе.
Если я тебя еще совсем не задолбал, расскажи про оператор fromstring.
Вот я пишу:

C++
1
2
3
std::string str = card.tostring();
std::cout << str << std::endl;
bool fromstring(string str);
Все компилируется. Хотя это и не показатель, ессно. По идее результатом должно быть true или false. Т.е. показатель то, были ли переданы значения в строку. И за bool должна следовать функция в { } - это подсказка от препода.
Но что же тогда будет возвращать функция? Str смысла нет. Мы только что ее вывели на экран. Как вывести bool?
nxtech
77 / 59 / 2
Регистрация: 26.06.2013
Сообщений: 198
27.06.2013, 23:46     Как реализовать метод ToString? #18
Я так понял, что метод fromstring должен быть обратным по отношению к tostring. Т.е. мы извлекаем из входного параметра str поля. Разделителями полей служит символ табуляции.
Например, строка: "Vanya\tIvanov\t+72222222222\tvanya@mail.ru". Из нее нужно извлечь четыре поля. Если извлечение полей прошло успешно - возвращаем true, иначе - false (существующий объект при этом не меняем).
Примерно можно сделать так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <sstream> // нужно добавить заголовок.
bool visit::fromstring(std::string const& str)
{
    int const num_of_fields = 4; // Можно объявить в классе статической константой: static int const num_of_fields = 4;
 
    std::istringstream is(str);
    std::vector<std::string> v;
    v.reserve(num_of_fields);
    std::string s;
 
    while (is >> s)
    {
        if (v.size() == num_of_fields) return false;
        v.push_back(s);
    }
    if (v.size() < num_of_fields) return false;
 
    name = v[0];
    last_name = v[1];
    tel = v[2];
    email = v[3];
 
    return true;
}
Используем так:
C++
1
2
3
std::cout << card.fromstring("Vanya\tIvanov\t+72222222222\tvanya@mail.ru\???") << std::endl; // ошибка в формате данных - лишние.
std::cout << card.fromstring("Vanya\tIvanov\t+72222222222\tvanya@mail.ru") << std::endl;
std::cout << card.fromstring("\t+72222222222\tvanya@mail.ru") << std::endl; // ошибка в формате данных - не достаточно.
Все функции get_xxx и tostring следует сделать константными:
C++
1
2
3
std::string get_name() const;
...
std::string tostring() const;
Добавлено через 4 минуты
Еще функции viv и save стоит сделать также константными методами класса. В save использовать в качестве разделителей табуляцию, а не пробелы, чтоб всюду согласовано было.
Korhall
7 / 7 / 1
Регистрация: 02.03.2013
Сообщений: 69
28.06.2013, 09:08  [ТС]     Как реализовать метод ToString? #19
Цитата Сообщение от nxtech Посмотреть сообщение
Я так понял, что метод fromstring должен быть обратным по отношению к tostring. Т.е. мы извлекаем из входного параметра str поля. Разделителями полей служит символ табуляции.
Например, строка: "Vanya\tIvanov\t+72222222222\tvanya@mail.ru". Из нее нужно извлечь четыре поля. Если извлечение полей прошло успешно - возвращаем true, иначе - false (существующий объект при этом не меняем).
Я тоже так понял.

Я так понимаю, что это будет в met.cpp, так где все функции. Но мне не совсем понятен этот фрагмент:

Цитата Сообщение от nxtech Посмотреть сообщение
std::string s;

while (is >> s) // объявили переменную s но она пустая. А что делает условие цикла "is >> s"?
{
if (v.size() == num_of_fields) return false;
v.push_back(s);
}
if (v.size() < num_of_fields) return false; // а это не опечатка? Или подразумевается, что в строку могут //передаться не все поля?

name = v[0];
last_name = v[1];
tel = v[2];
email = v[3]; //а если, скажем v[3] пустой элемент массива, то присвоения не произойдет?

return true;
}[/CPP]
Это main:
Цитата Сообщение от nxtech Посмотреть сообщение
C++
1
2
3
std::cout << card.fromstring("Vanya\tIvanov\t+72222222222\tvanya@mail.ru\???") << std::endl; // ошибка в формате данных - лишние. - т.е. они просто не выведутся в печать или будет ошибка?
std::cout << card.fromstring("Vanya\tIvanov\t+72222222222\tvanya@mail.ru") << std::endl;
std::cout << card.fromstring("\t+72222222222\tvanya@mail.ru") << std::endl; // ошибка в формате данных - не достаточно.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.06.2013, 14:43     Как реализовать метод ToString?
Еще ссылки по теме:

C++ Как реализовать метод шаблона вне класса?
Стеганография: как реализовать метод избыточных пробелов сокрытия информации в текстовом файле? C++
C++ Как правильно реализовать метод добавления и удаления объектов в хранилище без перегрузки?
C++ Реализовать статический метод уничтожения объекта
C++ C++ и матан, как реализовать метод класса?

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Korhall
7 / 7 / 1
Регистрация: 02.03.2013
Сообщений: 69
29.06.2013, 14:43  [ТС]     Как реализовать метод ToString? #20
Спасибо. Все работает. Когда сдам преподу - выложу здесь полную отредактированную версию программы.
Yandex
Объявления
29.06.2013, 14:43     Как реализовать метод ToString?
Ответ Создать тему
Опции темы

Текущее время: 13:33. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru