Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
5 / 5 / 1
Регистрация: 10.07.2017
Сообщений: 56

Не получается справиться с cin cout

15.06.2022, 12:14. Показов 1206. Ответов 18
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Подскажите, что я делаю не так?
Закомментированное работает нормально, но как только использую Input, внутри которой cin
вылетает ошибка: Code::Blocks: Process terminated with status -1073741819 (0 minute(s), 6 second(s))
VS: Необработанное исключение по адресу 0x00007FFD8A442A03 (msvcp140d.dll) в LAB1.exe: 0xC0000005: нарушение прав доступа при чтении по адресу 0x0000000000000000. (ошибка при чтении строки NameBook)




main.cpp
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
using namespace std;
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include "Main.h"
 
 
 
Person::Person(int NumBook, char *NameBook, char *AuthorBook, float Price)
{
   Person::NumBook = NumBook;
   strcpy(Person::NameBook, NameBook);
    strcpy(Person::AuthorBook, AuthorBook);
   Person::Price = Price;
}
 
void Person::Print(void)
{
    cout << NumBook << " | " << NameBook << " | " << AuthorBook << " | " << Price << endl;
}
 
void Person::Input(void)
{
    cin >> NumBook >> NameBook >> AuthorBook >> Price;
}
 
int main(void)
{
  //  Person firstbook (1, "War and Peace", "Tolstoy L.N.", 25);
  //  firstbook.Print();
 
  //  Person *per ;
  //  per = new Person(2,"Eugeniy Onegin","Pushkin A. S.",19);
  //  per->Print();
  //  delete per;
 
 Person *per2;
 per2->Input();
 per2->Print();
system("pause");
  return 0;
}
;
main.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
class Person
{
public:
    Person(int, char *, char *, float); //конструктор объекта по умолчанию (без аргументов)
    void Print(void);
    void Input(void);
private:
    int NumBook; // Номер книги в каталоге (целый тип)
    char NameBook[500]; // Название книги (символьный массив)
    char AuthorBook[500]; // ФИО автора (символьный массив)
    float Price;// Стоимость (вещественный тип)
};
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
15.06.2022, 12:14
Ответы с готовыми решениями:

cin cout
Как выводить через cin cout а не через printf. А то получается ерунда #include &lt;stdio.h&gt; #include &lt;locale.h&gt; #include...

Cout cin
Ребят, мы пишем cout &lt;&lt; .... и cin &gt;&gt; .... Как называются эти операторы &lt;&lt; и &gt;&gt;? И что они делают?

cin and cout
cout &lt;&lt; &quot;vvedite interval postupleniya detaley: &quot;; cin &gt;&gt; minDet&gt;&gt; maxDet; Нужно сделать чтобы интервал вводился не через...

18
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
15.06.2022, 12:37
Цитата Сообщение от Tanatholog Посмотреть сообщение
Person *per2;
Указатель не инициализирован. Он указывает в никуда.
Цитата Сообщение от Tanatholog Посмотреть сообщение
per2->Input();
Тут вы используете неинициализированный указатель.

Добавлено через 2 минуты
Кроме этой есть еще много ошибок в этом коде. )
0
5 / 5 / 1
Регистрация: 10.07.2017
Сообщений: 56
15.06.2022, 12:37  [ТС]
А почему вот тут
C++
1
Person *per
все работает?
Понимаю, что туплю, но и глаз замылился, и мозги расплавились.
0
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
15.06.2022, 12:39
Цитата Сообщение от Tanatholog Посмотреть сообщение
А почему вот тут все работает?
А чему тут не работать?
В этой строке вы объявили переменную-указатель на свой тип.
Тут, собственно, ничего не происходит. Чему тут не работать?!

Добавлено через 1 минуту
Вам "можно" использовать std::string вместо char*, или по заданию надо как следует задолбаться?
0
5 / 5 / 1
Регистрация: 10.07.2017
Сообщений: 56
15.06.2022, 12:42  [ТС]
Цитата Сообщение от lemegeton Посмотреть сообщение
Кроме этой есть еще много ошибок в этом коде. )
Натыкайте носом, пожалуйста. Если не трудно. Буду благодарен!

Добавлено через 2 минуты
Цитата Сообщение от lemegeton Посмотреть сообщение
Вам "можно" использовать std::string вместо char*, или по заданию надо как следует задолбаться?
Вот так звучит часть задания:
. В файле main.h определите с помощью ключевого слова class объект Person.
Данные объекта:
БИБЛИОТЕКА
имя — char*
автор — char*
стоимость — float
0
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
15.06.2022, 12:44
Цитата Сообщение от Tanatholog Посмотреть сообщение
Вот так звучит часть задания:
У. Мои соболезнования. Вариант с "задолбаться".
Давайте я вам лучше этот класс напишу, а вы посмотрите, что вы понимаете из этого.
0
5 / 5 / 1
Регистрация: 10.07.2017
Сообщений: 56
15.06.2022, 12:47  [ТС]
Цитата Сообщение от lemegeton Посмотреть сообщение
Давайте я вам лучше этот класс напишу, а вы посмотрите, что вы понимаете из этого.
Я за! Если вам не трудно.
0
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
15.06.2022, 12:51
Лучший ответ Сообщение было отмечено Tanatholog как решение

Решение

Цитата Сообщение от Tanatholog Посмотреть сообщение
Натыкайте носом, пожалуйста. Если не трудно. Буду благодарен!
Знаете, а я тут подумал, сойдёт ваш код.

Он, конечно, избыточен, но в целом функцию свою выполняет. Если я его щас перепишу -- будет вообще не разобрать.

Внесём буквально пару поправок.

В конструктор к переменным добавим const.
C++
1
    Person(int, const char *, const char *, float); //конструктор объекта по умолчанию (без аргументов)
Уберём ото всюду лишний void
Добавим конструктор по-умолчанию,
создадим и удалим объект per.

Цитата Сообщение от Tanatholog Посмотреть сообщение
per = new Person(2,"Eugeniy Onegin","Pushkin A. S.",19);
У вас прям в закомментированном коде есть валидный вариант. )

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
#include <iostream>
#include <utility>
#include <cstring>
 
using namespace std;
 
class Person
{
public:
    Person(); //конструктор объекта по умолчанию (без аргументов)
    Person(int, const char *, const char *, float); //конструктор объекта по умолчанию (без аргументов)
    void Print();
    void Input();
 
private:
    int NumBook; // Номер книги в каталоге (целый тип)
    char NameBook[500]; // Название книги (символьный массив)
    char AuthorBook[500]; // ФИО автора (символьный массив)
    float Price;// Стоимость (вещественный тип)
};
 
Person::Person() {
    Person::NumBook = 0;
    Person::NameBook[0] = 0;
    Person::AuthorBook[0] = 0;
    Person::Price = 0;
}
 
Person::Person(int NumBook, const char *NameBook, const char *AuthorBook, float Price) {
    Person::NumBook = NumBook;
    strcpy(Person::NameBook, NameBook);
    strcpy(Person::AuthorBook, AuthorBook);
    Person::Price = Price;
}
 
void Person::Print()
{
    cout << NumBook << " | " << NameBook << " | " << AuthorBook << " | " << Price << endl;
}
 
void Person::Input()
{
    cin >> NumBook >> NameBook >> AuthorBook >> Price;
}
 
int main()
{
    //  Person firstbook (1, "War and Peace", "Tolstoy L.N.", 25);
    //  firstbook.Print();
 
    //  Person *per ;
    //  per = new Person(2,"Eugeniy Onegin","Pushkin A. S.",19);
    //  per->Print();
    //  delete per;
 
    // раз потом всё равно введем, то ничего и не надо в инстанс пихать
    Person *per2 = new Person();
    per2->Input();
    per2->Print();
 
    delete per2; // удаление
    return 0;
}
1
5 / 5 / 1
Регистрация: 10.07.2017
Сообщений: 56
15.06.2022, 12:58  [ТС]
Цитата Сообщение от lemegeton Посмотреть сообщение
Person(int, const char *, const char *, float)
Этот вариант я использовал, но напугало задание. Там ни слова об использовании const нет.
Цитата Сообщение от lemegeton Посмотреть сообщение
У вас прям в закомментированном коде комментарии есть валидный вариант. )
Закомментировано еще одно задание. Оно выполняется без труда. Но потом надо:
Напишите функцию ввода данных в объект с клавиатуры void Person::Input(). В теле функции для ввода данных используйте стандартный поток ввода cin >> значение1 >> значение2 >> ...;
Затем в теле функции main создайте объект Person с помощью конструктора по умолчанию и введите данные в объект с клавиатуры, вызвав функцию Input.

И вот тут я поплыл...
0
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
15.06.2022, 14:36
Цитата Сообщение от Tanatholog Посмотреть сообщение
Напишите функцию ввода данных в объект с клавиатуры void Person::Input(). В теле функции для ввода данных используйте стандартный поток ввода cin >> значение1 >> значение2 >> ...;
Затем в теле функции main создайте объект Person с помощью конструктора по умолчанию и введите данные в объект с клавиатуры, вызвав функцию Input.
И вот тут я поплыл...
Это код выше и делает.
0
5 / 5 / 1
Регистрация: 10.07.2017
Сообщений: 56
16.06.2022, 05:15  [ТС]
Цитата Сообщение от lemegeton Посмотреть сообщение
Это код выше и делает.
Огромное спасибо за помощь!
Со свежей головой действительно все становится понятнее ))
0
5 / 5 / 1
Регистрация: 10.07.2017
Сообщений: 56
23.06.2022, 07:52  [ТС]
И снова вопрос.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#pragma once
#include <iostream>
#include <stdlib.h>
 
class Library
{
public:
    Library();//конструктор объекта по умолчанию (без аргументов)
    Library(int, const char*, const char*, float); //Описываем конструктор объекта, аргументы инициализируют все данные объекта
    void Print();
    void Input();
    ~Library(); //Деструктор объекта
    
private:
    int NumBook; // Номер книги в каталоге (целый тип)
    char NameBook[500]; // Название книги (символьный массив)
    char AuthorBook[500]; // ФИО автора (символьный массив)
    float Price;// Стоимость (вещественный тип)
            
};

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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// LAB1.cpp : Этот файл содержит функцию "main". Здесь начинается и заканчивается выполнение программы.
//
using namespace std;
#include <iostream>
#include <utility>
#include <cstring>
#include "Main.h"
 
 
Library::Library()
{
   Library::NumBook = 0;
   Library::NameBook[0] = 0;
   Library::AuthorBook[0] = 0;
   Library::Price = 0;
}
 
Library::Library(int NumBook, const char* NameBook, const char* AuthorBook, float Price) {
    Library::NumBook = NumBook;
    strcpy_s(Library::NameBook, NameBook);
    strcpy_s(Library::AuthorBook, AuthorBook);
    Library::Price = Price;
}
 
void Library::Print()
{
    cout << NumBook << "|" << NameBook << "|" << AuthorBook << "|" << Price << endl;
}
 
void Library::Input()
{
    //cin >> NumBook >> NameBook >> AuthorBook >> Price;
                                  //Используем стандартный поток ввода cin
    char str[50];
    bool test = false;
    while (test == false)        //Проверяем ввод номера
    {
        test = true;
        cout << "\nInput NumBook: ";
        cin.ignore();       //Пропускаем символ конца строки, оставшийся от последнего ввода
        cin >> str;
        for (int i = 0; i < strlen(str); i++)
            if ((str[i] < '0') || (str[i] > '9')) test = false;
        if (test) NumBook = atoi(str);
        
        else cout << "Invalid NumBook!" << endl;
        
    }
    test = false;
    while (test == false)        //Проверяем ввод названия книги
    {
        test = true;
        cout << "\nInput NameBook: ";
        cin.ignore();       //Пропускаем символ конца строки, оставшийся от последнего ввода
        cin.getline(str, sizeof(str));        //Позволяет написать полностью название
        for (int i = 0; i < strlen(str); i++)
            if ((str[i] < 'a') || (str[i] > 'z'))
                if ((str[i] < 'A') || (str[i] > 'Z'))
                    if (str[i] != '.')
                        if (str[i] != ' ') test = false;
        if (test) strcpy_s(NameBook, str);
        else cout << "\nInvalid NameBook!" << endl;
       
    }
    test = false;
    while (test == false)        //Проверяем ввод ФИО автора
    {
        test = true;
        cout << "\nInput AuthorBook: ";
        cin.ignore();       //Пропускаем символ конца строки, оставшийся от последнего ввода
        cin.getline(str, sizeof(str));        //Позволяет написать полностью ФИО автора
        for (int i = 0; i < strlen(str); i++)
            if ((str[i] < 'a') || (str[i] > 'z'))
                if ((str[i] < 'A') || (str[i] > 'Z'))
                    if (str[i] != '.')
                        if (str[i] != ' ') test = false;
        if (test) strcpy_s(AuthorBook, str);
        else cout << "\nInvalid AuthorBook!" << endl;
    }
    test = false;
    while (test == false)        //Проверяем ввод цены
    {
        test = true;
        cout << "\nInput Price: ";
        cin >> str;
        for (int i = 0; i < strlen(str); i++)
            if ((str[i] < '0') || (str[i] > '9'))
                if (str[i] != '.') test = false;
        if (test) Price = atof(str);
        else cout << "\nInvalid Price!" << endl;
    }
 
}
 
Library::~Library()
{ 
    cout << "Call Destructor" << endl; //Сообщаем о вызове деструктора
}
 
 
 
int main()
{
    Library firstbook(1, "War and Peace", "Tolstoy L.N.", 25); //Создаем объект с указанием значений (задание 10)
    firstbook.Print(); 
    
    Library* book;
    book = new Library(2, "Eugeniy Onegin", "Pushkin A. S.", 19);//Создаем динамический объект с обычным конструктором и оператором new (задание 11)
    book->Print();
    delete book; // Удаляем объект из памяти
 
 
    Library*book2 = new Library(); //Создаем объект с помощью конструктора по умолчанию и ввода данных (задание 12)
    book2->Input();
    book2->Print();
 
    delete book2; // Удаляем объект из памяти
 
    cin.ignore(); //Игнорируем символ конца строки и Задаем паузу (замечание №12)
    cout << "Press any key." << "\n";
    cin.get();
    return 0;
}
Почему в названии книги и имени автора отрезается первый символ при целенаправленном вводе с ошибкой и перепроверке ввода?
0
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
23.06.2022, 08:02
Цитата Сообщение от Tanatholog Посмотреть сообщение
void Library::Input()
{
    //cin >> NumBook >> NameBook >> AuthorBook >> Price;
                                  //Используем стандартный поток ввода cin
    char str[50];
    bool test = false;
    while (test == false)        //Проверяем ввод номера
    {
        test = true;
        cout << "\nInput NumBook: ";
        cin.ignore();       //Пропускаем символ конца строки, оставшийся от последнего ввода
        cin >> str;
        for (int i = 0; i < strlen(str); i++)
            if ((str[i] < '0') || (str[i] > '9')) test = false;
        if (test) NumBook = atoi(str);
else cout << "Invalid NumBook!" << endl;
}
    test = false;
    while (test == false)        //Проверяем ввод названия книги
    {
        test = true;
        cout << "\nInput NameBook: ";
        cin.ignore();       //Пропускаем символ конца строки, оставшийся от последнего ввода
        cin.getline(str, sizeof(str));        //Позволяет написать полностью название
        for (int i = 0; i < strlen(str); i++)
            if ((str[i] < 'a') || (str[i] > 'z'))
                if ((str[i] < 'A') || (str[i] > 'Z'))
                    if (str[i] != '.')
                        if (str[i] != ' ') test = false;
        if (test) strcpy_s(NameBook, str);
        else cout << "\nInvalid NameBook!" << endl;
}
    test = false;
    while (test == false)        //Проверяем ввод ФИО автора
    {
        test = true;
        cout << "\nInput AuthorBook: ";
        cin.ignore();       //Пропускаем символ конца строки, оставшийся от последнего ввода
        cin.getline(str, sizeof(str));        //Позволяет написать полностью ФИО автора
        for (int i = 0; i < strlen(str); i++)
            if ((str[i] < 'a') || (str[i] > 'z'))
                if ((str[i] < 'A') || (str[i] > 'Z'))
                    if (str[i] != '.')
                        if (str[i] != ' ') test = false;
        if (test) strcpy_s(AuthorBook, str);
        else cout << "\nInvalid AuthorBook!" << endl;
    }
    test = false;
    while (test == false)        //Проверяем ввод цены
    {
        test = true;
        cout << "\nInput Price: ";
        cin >> str;
        for (int i = 0; i < strlen(str); i++)
            if ((str[i] < '0') || (str[i] > '9'))
                if (str[i] != '.') test = false;
        if (test) Price = atof(str);
        else cout << "\nInvalid Price!" << endl;
    }
}
Простите, это нечитаемо.

Попробуйте переделать следующим образом: сначала введите все данные, потом проверьте валидность полей с помощью отдельных функций.

Иначе у вас получается странное чтение данных недоконца и спагетти из кода.
0
5 / 5 / 1
Регистрация: 10.07.2017
Сообщений: 56
23.06.2022, 08:15  [ТС]
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  while (test == false)        //Проверяем ввод ФИО автора
    {
        test = true;
        cout << "\nInput AuthorBook: ";
        cin.ignore();       //Пропускаем символ конца строки, оставшийся от последнего ввода
        cin.getline(str, sizeof(str));        //Позволяет написать полностью ФИО автора
        for (int i = 0; i < strlen(str); i++)
            if ((str[i] < 'a') || (str[i] > 'z'))
                if ((str[i] < 'A') || (str[i] > 'Z'))
                    if (str[i] != '.')
                        if (str[i] != ' ') test = false;
        if (test) strcpy_s(AuthorBook, str);
        else cout << "\nInvalid AuthorBook!" << endl;
        cout << AuthorBook;
Вот тут при вводе: Dostoevskiy
cout выдает: ostoevskiy
0
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
23.06.2022, 08:35
Цитата Сообщение от Tanatholog Посмотреть сообщение
cin.ignore();       //Пропускаем символ конца строки, оставшийся от последнего ввода
Вот тут, например, пропускается не "символ конца строки", а какой-то символ, следующий за предыдущим вводом.
Подебажьте, посмотрите.
Ещё раз предлагаю сделать так: сначала ввести, потом проверять.

Добавлено через 3 минуты
Цитата Сообщение от lemegeton Посмотреть сообщение
while (test == false)        //Проверяем ввод названия книги
    {
        test = true;
        cout << "\nInput NameBook: ";
        cin.ignore();       //Пропускаем символ конца строки, оставшийся от последнего ввода
        cin.getline(str, sizeof(str));        //Позволяет написать полностью название
        for (int i = 0; i < strlen(str); i++)
            if ((str[i] < 'a') || (str[i] > 'z'))
                if ((str[i] < 'A') || (str[i] > 'Z'))
                    if (str[i] != '.')
                        if (str[i] != ' ') test = false;
        if (test) strcpy_s(NameBook, str);
        else cout << "\nInvalid NameBook!" << endl;
}
Вынесите вот это в отдельную функцию, тогда пропадёт необходимость в ужасном while и вознёй с булевой переменной.
Вы просто cможете сделать return false;
0
5 / 5 / 1
Регистрация: 10.07.2017
Сообщений: 56
24.06.2022, 15:27  [ТС]
Ура! Я запутался ))
Написал функцию:
C++
1
2
char str[50];
char txt[50];
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
char* TestTXT()
{
   
    bool test = false;
    while (test == false)
    {
        test = true;
                        
        cin.getline(str, sizeof(str));        //Позволяет написать полностью название               
        for (int i = 0; i < strlen(str); i++)
            if ((str[i] < 'a') || (str[i] > 'z'))
                if ((str[i] < 'A') || (str[i] > 'Z'))
                    if (str[i] != '.')
                        if (str[i] != ' ') test = false;
        if (test) strcpy_s(txt, str);
        else cout << "Invalid Text. Repeat: ";
 
    }
    return txt;
}
Дальше собираюсь вызывать ее таким способом:

C++
1
2
cout << "Input NameBook: ";
    NameBook = TestTXT();
Сделал так, чтобы одной функцией проверять, что NameBook, что AuthorBook.

Напоминаю, что:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Library
{
public:
    Library();//конструктор объекта по умолчанию (без аргументов)
    Library(int, const char*, const char*, float); //Описываем конструктор объекта, аргументы инициализируют все данные объекта
    void Print();
    void Input();
    ~Library(); //Деструктор объекта
    
private:
    int NumBook; // Номер книги в каталоге (целый тип)
    char NameBook[500]; // Название книги (символьный массив)
    char AuthorBook[500]; // ФИО автора (символьный массив)
    float Price;// Стоимость (вещественный тип)
И получаю ошибку о том, что выражение должно быть допустимым для изменения левосторонним значением.
0
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
24.06.2022, 17:13
Цитата Сообщение от Tanatholog Посмотреть сообщение
Ура! Я запутался ))


Да. Вас занесло в какие-то далёкие края.
Вы полезли валидировать ввод непонятно чего. Непонятно зачем.
Бросьте это. Позвольте пока вашей программе быть несовершенной.

Посмотрите пример, как можно реализовать класс и сделать ввод/вывод в ваших условиях:
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <iostream>
#include <cstring>
#include <utility>
 
class Book {
public:
    Book() : id(), caption(new char[1]{0}), author(new char[1]{0}), price() {}
 
    Book(int id, const char *caption, const char *author, float price)
            : id(id),
              caption(std::strcpy(new char[std::strlen(caption) + 1], caption)),
              author(std::strcpy(new char[std::strlen(author) + 1], author)),
              price(price) {}
 
    ~Book() {
        delete[] author;
        delete[] caption;
    }
 
    // поскольку есть деструктор, нам нужно
    // соблюдаем правило трёх
    Book(const Book &other)
            : id(other.id),
              caption(std::strcpy(new char[std::strlen(other.caption) + 1], other.caption)),
              author(std::strcpy(new char[std::strlen(other.author) + 1], other.author)),
              price(other.price) {}
 
    Book &operator=(const Book &other) {
        if (this != &other) {
            delete[] caption;
            delete[] author;
            id = other.id;
            caption = std::strcpy(new char[std::strlen(other.caption) + 1], other.caption);
            author = std::strcpy(new char[std::strlen(other.author) + 1], other.author);
            price = other.price;
        }
        return *this;
    }
 
    // поскольку у нас плюсы после одиннадцатых,
    // соблюдаем правило пяти
    Book(Book &&other) noexcept
            : id(other.id),
              caption(std::exchange(other.caption, nullptr)),
              author(std::exchange(other.author, nullptr)),
              price(other.price) {}
 
    Book &operator=(Book &&other) noexcept {
        if (this != &other) {
            id = other.id;
            caption = std::exchange(other.caption, caption);
            author = std::exchange(other.author, author);
            price = other.price;
        }
        return *this;
    }
 
    int getId() const {
        return id;
    }
 
    const char *getCaption() const {
        return caption;
    }
 
    const char *getAuthor() const {
        return author;
    }
 
    float getPrice() const {
        return price;
    }
 
private:
    int id;
    char *caption;
    char *author;
    float price;
};
 
std::ostream &operator<<(std::ostream &out, const Book &book) {
    return out << "Book{"
               << "id=" << book.getId() << ","
               << "caption=\"" << book.getCaption() << "\","
               << "author=\"" << book.getAuthor() << "\","
               << "price=" << book.getPrice() << "}";
}
 
// самый мрачный метод
std::istream &operator>>(std::istream &in, Book &book) {
    // буфферы для копирования данных.
    int id; // для ввода id
    static char captionBuffer[4096]; // буффер для ввода названия
    static char authorBuffer[4096]; // буффер для ввода автора
    float price;
    *captionBuffer = *authorBuffer = 0; // это обнуляет строки
    std::cin >> id;
    std::cin.ignore(); // тот самый пропуск символа, поскольку getline читает от текущей позиции до конца строки
    std::cin.getline(captionBuffer, 4096);
    std::cin.getline(authorBuffer, 4096);
    std::cin >> price;
    // сначла конструктор с параметрами, затем move-присваивание
    book = {id, captionBuffer, authorBuffer, price};
    return in;
}
 
bool isValidCaption(const char *caption) {
    std::size_t length = std::strlen(caption);
    for (int i = 0; i < length; i++) {
        if ((caption[i] < 'a' || caption[i] > 'z') &&
            (caption[i] < 'A' || caption[i] > 'Z') &&
            (caption[i] != '.') &&
            (caption[i] != ' ')) {
            return false;
        }
    }
    return true;
}
 
bool isValidAuthor(const char *author) {
    std::size_t length = std::strlen(author);
    for (int i = 0; i < length; i++) {
        if ((author[i] < 'a' || author[i] > 'z') &&
            (author[i] < 'A' || author[i] > 'Z') &&
            (author[i] != '.') &&
            (author[i] != ' ')) {
            return false;
        }
    }
    return true;
}
 
bool isValid(const Book &book) {
    return isValidCaption(book.getCaption()) && isValidAuthor(book.getAuthor());
}
 
int main() {
 
    Book book;
    // сначала ввести
    std::cin >> book;
    // можно и вывести
    std::cout << book << std::endl;
    // потом валидировать
    std::cout << std::boolalpha << isValid(book) << std::endl;
    return 0;
}
In:
Code
1
2
3
4
1
Война и мир
Лев Толстой
1024.50
Out:
Code
1
2
Book{id=1,caption="Война и мир",author="Лев Толстой",price=1024.5}
false
Добавлено через 8 минут
Цитата Сообщение от Tanatholog Посмотреть сообщение
else cout << "Invalid Text. Repeat: ";
После этой строки выполнение продолжится.
Цитата Сообщение от Tanatholog Посмотреть сообщение
И получаю ошибку о том, что выражение должно быть допустимым для изменения левосторонним значением.
Не понимаю, где вы её могли получить в этом куске кода.
В любом случае, такой подход бы не сработал.
Функция вернёт указатель на глобальную переменную txt, которая будет присвоена полю,
а при следующем чтении эта же функция в эту же область памяти запишет другое.
В результате у вас поле каждого объекта будут указывать в одну и ту же область памяти, в которой будет последнее чтение.
0
5 / 5 / 1
Регистрация: 10.07.2017
Сообщений: 56
24.06.2022, 17:23  [ТС]
Цитата Сообщение от lemegeton Посмотреть сообщение
Вы полезли валидировать ввод непонятно чего. Непонятно зачем.
Бросьте это.
Да дело не в совершенстве.
Выполнил лабораторную, а препод доколупалась, что у меня нет проверки ввода данных. Вот тут и началось...

Добавлено через 5 минут
Цитата Сообщение от lemegeton Посмотреть сообщение
После этой строки выполнение продолжится.
К сожалению, программа вообще не собирается. NameBook подсвечивается с сообщением: "выражение должно быть допустимым для изменения левосторонним значением"

Цитата Сообщение от lemegeton Посмотреть сообщение
Функция вернёт указатель на глобальную переменную txt, которая будет присвоена полю
А как мне написать, чтобы функция вернула мне то, что я внутри нее ввел и проверил?

Добавлено через 1 минуту
Цитата Сообщение от lemegeton Посмотреть сообщение
Посмотрите пример, как можно реализовать класс и сделать ввод/вывод в ваших условиях:
С удовольствием, но так как замечания по уже увиденному коду, то преподаватель не поймет полностью переписанной програмы ))
0
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
24.06.2022, 17:49
Цитата Сообщение от Tanatholog Посмотреть сообщение
С удовольствием, но так как замечания по уже увиденному коду, то преподаватель не поймет полностью переписанной програмы ))
Если вы поймете, то и препод поймет.

Добавлено через 30 секунд
Цитата Сообщение от Tanatholog Посмотреть сообщение
К сожалению, программа вообще не собирается. NameBook подсвечивается с сообщением: "выражение должно быть допустимым для изменения левосторонним значением"
Я имел в виду, что нет кода, который бы что-то делал для того, чтоб ввести заново.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
24.06.2022, 17:49
Помогаю со студенческими работами здесь

Cin cout
записать через сin cout printf (&quot;a=&quot;, i); scanf (&quot;%f&quot;, &amp;a);

cout и cin
есть хандл трубы handle. можно настроить cout и cin так , чтобы вводить и принимать данные с помощью этих команд?

Перегрузка cin/cout
Надо перегрузить операторы для некого класса. У меня есть два базовых класса, в одном 2 поля, в другом 3 поля. В производном классе(от етих...

Не работают cin и cout
Компилю на С++. Впервые. Использую Borland C++ Builder 6.0 Прочитал много разных самоучителей, энциклопедий по С++ Создаю приложение...

Добавить cin и cout
#include &lt;iostream&gt; using namespace std; struct Node { int numer; //информационный элемент int pos; //информационный...


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

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Новые блоги и статьи
Сумматор с применением элементов трёх состояний.
Hrethgir 26.03.2026
Тут. https:/ / fips. ru/ EGD/ ab3c85c8-836d-4866-871b-c2f0c5d77fbc Первый документ красиво выглядит, но без схемы. Это конечно не даёт никаких плюсов автору, но тем не менее. . . всё может быть. . .
Автозаполнение реквизитов при создании документа
Maks 26.03.2026
Программный код из решения ниже размещается в модуле объекта документа, в процедуре "ПриСозданииНаСервере". Алгоритм проверки заполнения реализован для исключения перезаписи значения реквизита,. . .
Команды "Заполнить" и "Очистить" на форме документа
Maks 26.03.2026
1. Команда формы "ЗаполнитьЗапчасти". На примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. В качестве источника данных выбран регистр накопления, в. . .
Кому нужен AOT?
DevAlt 26.03.2026
Решил сделать простой ланчер Написал заготовку: dotnet new console --aot -o UrlHandler var items = args. Split(":"); var tag = items; var id = items; var executable = args;. . .
Отправка уведомления на почту при изменении наименования справочника
Maks 24.03.2026
Программная отправка письма электронной почты на примере изменения наименования типового справочника "Склады" в конфигурации БП3. Перед реализацией необходимо выполнить настройку системной учетной. . .
модель ЗдравоСохранения 5. Меньше увольнений- больше дохода!
anaschu 24.03.2026
Теперь система здравосохранения уменьшает количество увольнений. 9TO2GP2bpX4 a42b81fb172ffc12ca589c7898261ccb/ https:/ / rutube. ru/ video/ a42b81fb172ffc12ca589c7898261ccb/ Слева синяя линия -. . .
Midnight Chicago Blues
kumehtar 24.03.2026
Такой Midnight Chicago Blues, знаешь?. . Когда вечерние улицы становятся ночными, а ты не можешь уснуть. Ты идёшь в любимый старый бар, и бармен наливает тебе виски. Ты смотришь на пролетающие. . .
SDL3 для Desktop (MinGW): Вывод текста со шрифтом TTF с помощью библиотеки SDL3_ttf на Си и C++
8Observer8 24.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-text-sdl3-c. zip finish-text-sdl3-cpp. zip
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru