1 Востаннє редагувалося mamkin haker (11.08.2021 08:14:02)

Тема: Цикл while() пропускає std::cin

Зіткнувся з дивним явищем.
Коли зчитую та записую в int num не число типу int то цикл чомусь пропускає cin >> num;
В перемінну num при цьому записуєтся нуль, та виконуєтся "покупка" товар 1 із знижкою 50% до тих пір поки на балансі не залишится грошей
Якщо в кінці циклу добавити num = -1; то всеодно буде ігноруватись cin >> num; та буде писати "Введіть коректний номер товару"
Мова С++

головний файл
#include <iostream>
#include "User.h"
#include "Product.h"
using std::cin;

int main ()
{
    int num;
    int size_product = 2;
    User admin;

    //(ціна товару, назва товару)
    Product* product[size_product]; //знайти як зробити масив динамічним
    product[0] = new Product1(213, "товар 1");
    product[1] = new Product2(6.25, "товар 2");

    while (true)
    {
        printf("Ваш баланс %f грн\n\n", admin.get_money());

        for (int i = 0; i < size_product; i++)
        {
            float price = product[i] -> get_price();
            const char* product_name = product[i] -> get_name();
            printf("Номер: %d\nЦіна: %f грн\nІм'я товару: %s\n\n", i, price, product_name);
        }

        cin >> num;
        printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");

        if ((num >= 0) && (num < size_product))
        {
            float price = product[num] -> get_price();
            printf("%s\n", admin.buying(price));
        }
        else
        {
            printf("Введіть коректний номер товару!\n");
        }
        //виходу з циклу намає :D
    }
}
User.h
class User
{
public:
    float get_money(){return money;}
    char* buying(float price)
    {
        if (price < money)
        {
            money -= price;
            return "Покупка виконана.";
        }
        else
        {
            return "Недостатньо коштів.";
        }
    }

private:
    float money = 1000;   
};
Product.h
class Product
{
protected:
    float price;
    const char* product_name;
    Product(float price, const char* product_name): price(price), product_name(product_name){}

public:
    virtual const float get_price() {return 0;};
    virtual const char* get_name() {return "abstract";};
};

class Product1 : public Product
{
public:
    Product1(float price, const char* product_name) : Product(price, product_name){}
    virtual const float get_price() {return price/2;}; //скидка 50%
    virtual const char* get_name() {return product_name;};
};

class Product2 : public Product
{
public:
    Product2(float price, const char* product_name) : Product(price, product_name){}
    virtual const float get_price() {return price+1;}; //підняття ціни на 1 грн
    virtual const char* get_name() {return product_name;};
};

2 Востаннє редагувалося koala (10.08.2021 23:34:29)

Re: Цикл while() пропускає std::cin

Де саме в коді ви записуєте в int num об'єкт типу char*? Я бачу лише, що ви намагаєтеся туди прочитати int зі стандартного потоку введення.

Подякували: mamkin haker1

3

Re: Цикл while() пропускає std::cin

koala написав:

Де саме в коді ви записуєте в int num об'єкт типу char*? Я бачу лише, що ви намагаєтеся туди прочитати int зі стандартного потоку введення.

Так, коли я зчитую з термінала :3
Трішки неправильно висловився хехе

4

Re: Цикл while() пропускає std::cin

Потік введення при некоректній спробі читати наступний токен "ламається" (ставить прапорець bad). Перевірити стан можна простим if:

if(cin)...

... виконається лише якщо cin готовий читати.
Почистити прапорець можна методом cin.clean(), але ще доведеться викинути некоректні дані з буфера - скажімо, за допомогою cin.ignore.

Подякували: mamkin haker1

5 Востаннє редагувалося mamkin haker (11.08.2021 10:11:32)

Re: Цикл while() пропускає std::cin

Все працює :D дякую

#include <iostream>
int main()
{
    int num;
    while(true)
    {
        printf("while\n");
        if (std::cin)
        {
            std::cin >> num;
        }
        else
        {
            std::cin.clear();
            std::cin.ignore();
        }
    }
}

6

Re: Цикл while() пропускає std::cin

Оскільки istream::operator>> повертає istream&, це можна навіть скоротити до

if(std::cin>>num)
{
}
else...

або ж

if(!std::cin>>num)
{
    ...//код з else
}

і гляньте на аргументи ignore - зараз ви його викликаєте в циклі багато разів, а там можна багато символів за раз викинути.

Подякували: mamkin haker1

7 Востаннє редагувалося Droid 77 (11.08.2021 21:20:40)

Re: Цикл while() пропускає std::cin

Замість отого cin >> num, з першого повідомлення.
Можна втулити

ось таку
        std::cin >> num;
        if(std::cin.fail() || num < 0 || num > size_product) {
        std::cin.clear();
        std::cin.ignore();
        std::cout << "Invalid input.\n" << std::endl;
        } else

конструкцію.

P. S.
А отой using std::cin; краще закоментувати.

Подякували: mamkin haker1

8 Востаннє редагувалося mamkin haker (12.08.2021 12:39:13)

Re: Цикл while() пропускає std::cin

koala написав:

гляньте на аргументи ignore - зараз ви його викликаєте в циклі багато разів, а там можна багато символів за раз викинути.

подивився на стековер флов, там якісь цифри та "\n" , я це в свій код добавляю і нічого не працює, при компіляції return -1 :D

std::cin.ignore(1000,'\n')

https://stackoverflow.com/questions/254 … c#25476169

Droid 77 написав:

P. S.
А отой using std::cin; краще закоментувати.

?_?
це ж я його написав і єдине його місце десь в архівчику\корзині лежати
using namespace std; писати нехотілось тому написав просто using std::cin;

таке теж згодится :D?

        if ((cin) && (num >= 0) && (num < size_product))
        {
            float price = product[num] -> get_price();
            printf("%s\n", admin.buying(price));
        }
        else
        {
            while (!cin)
            {
                cin.clear();
                cin.ignore();
            }
            printf("Введіть коректний номер товару!\n");
        }