-2
\main112.cpp    In function 'int main()':
63  36  \main112.cpp    [Error] 'counter' was not declared in this scope
28               \Makefile.win  recipe for target 'main112.o' failed
#include <string>
#include <iostream>
#include <windows.h>
#include <stdlib.h>

using namespace std;

struct Person
{
    string name;
    string race;
    int weight;

    void write();
    void show();
    void check();
};

void Person::show()
{
    cout<<"ÔÈÎ: "<<name<<endl;
    cout<<"Íîìåð ðåéñà: "<<race<<endl;
    cout<<"Âåñ áàãàæà: "<<weight<<endl;
}

void Person::write()
{
    cout<<"Ââåäèòå ÔÈÎ: ";
    getline(cin,name);
    cout<<"Ââåäèòå íîìåð ðåéñà: ";
    getline(cin,race);
    cout<<"Ââåäèòå âåñ áàãàæà: ";
    cin>>weight;
    cin.ignore();
}

void Person::check()
{
    int counter = 0;
    if(weight>10)
    {
        counter++;
    }
}

int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    setlocale(0, "Russian");


    Person* persons=new Person[4];
    for (int i = 0; i < 4; i++)
    {
        persons[i].write();
    }
    for (int i = 0; i < 4; i++)
    {
        persons[i].show();
        persons[i].check();
    }
    cout<<"Ñ áàãàæîì áîëüøå 10 êã: "<<counter<<" ÷åëîâåê"<<endl;

    delete[] persons;
    return 0;
}

Program that works the way its coded and should work, without this problem

Homework:

Write a program for processing passenger information. Information includes: 1) Full name of the passenger. 2) Flight number. 3) Luggage weight The program should allow the user to: 1) Read data from the keyboard and display it. 2) Calculate the number of passengers with the weight of baggage which is more than 10 kg

Favoras
  • 19
  • 3
  • 5
    The error message is correct. The variable `counter` only exists inside the function `Person::check()` It is not usable anywhere else. – drescherjm Mar 25 '19 at 17:52
  • How can i fix it considering what i want from future program? – Favoras Mar 25 '19 at 17:54
  • Your `counter` is created with the value zero each time you all `check()`, it's incremented if `weight>10` and then ceases to exist without ever being used at the end of the function call. – François Andrieux Mar 25 '19 at 17:54
  • Why would `counter` be a class member? `Person` doesn't care about the count, only `main` does. My pitch a free function that tests and returns `bool` and let `main` keep count. – user4581301 Mar 25 '19 at 18:29
  • @user4581301 what is the counter counting? How many people have wight over 10? – Aykhan Hagverdili Mar 25 '19 at 18:32
  • 1
    @Ayxan, yes, but the function is an abstraction. The counter would be implemented every time `check` returns `true`. `main` has no need to care what produces true. – user4581301 Mar 25 '19 at 18:35
  • 1
    This looks like a good place to use std::count_if. http://www.cplusplus.com/reference/algorithm/count_if/ – drescherjm Mar 25 '19 at 18:45

4 Answers4

1

The problem here is you're defining counter in the scope of the function Person::check(). Every time you run the check function a new variable called counter is created set to be the value 0. Then once it's through running that function it ceases to exist.

A quick and dirty way of fixing this would be declaring counter as a global variable.

#include <string>
#include <iostream>
#include <windows.h>
#include <stdlib.h>

using namespace std;

int counter = 0;

struct Person
{
    string name;
    string race;
    int weight;

    void write();
    void show();
    void check();
};

void Person::show()
{
    cout<<"ÔÈÎ: "<<name<<endl;
    cout<<"Íîìåð ðåéñà: "<<race<<endl;
    cout<<"Âåñ áàãàæà: "<<weight<<endl;
}

void Person::write()
{
    cout<<"Ââåäèòå ÔÈÎ: ";
    getline(cin,name);
    cout<<"Ââåäèòå íîìåð ðåéñà: ";
    getline(cin,race);
    cout<<"Ââåäèòå âåñ áàãàæà: ";
    cin>>weight;
    cin.ignore();
}

void Person::check()
{
    if(weight>10)
    {
        counter++;
    }
}

int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    setlocale(0, "Russian");


    Person* persons=new Person[4];
    for (int i = 0; i < 4; i++)
    {
        persons[i].write();
    }
    for (int i = 0; i < 4; i++)
    {
        persons[i].show();
        persons[i].check();
    }
    cout<<"Ñ áàãàæîì áîëüøå 10 êã: "<<counter<<" ÷åëîâåê"<<endl;

    delete[] persons;
    return 0;
}

A better way would be defining counter as a member variable of your struct then you can get the value of each of the person objects' counter variable at anytime after declaring the object.

nwfistere
  • 355
  • 4
  • 15
  • 2
    Usage of [global variables](https://stackoverflow.com/questions/484635/are-global-variables-bad) isn't really wise advice. – πάντα ῥεῖ Mar 25 '19 at 18:06
  • Can you explain why? – Favoras Mar 25 '19 at 18:07
  • See the linked Q&A. There are more to find. Basically it clutters your program and makes all of the parts harder to maintain. That's the whole point why c++ introduced encapsulation of data into classes. – πάντα ῥεῖ Mar 25 '19 at 18:09
  • @πάνταῥεῖ I agree that using global variables is bad advice, but it is the simplest way of getting what Favoras wants. – nwfistere Mar 25 '19 at 18:13
  • 2
    Which means the _simplest way_ isn't necessarily _the best_. I think we should always give _the best possible_ answers, to be as most useful for future research, and not just help the OP with their specific problem in short terms. – πάντα ῥεῖ Mar 25 '19 at 18:16
  • almost as simple would be to declare `counter` as `static` and make `check` return its value. Actually it is cheating, because then `counter` can still be considered as a global variable by purists – 463035818_is_not_an_ai Mar 25 '19 at 18:44
1

Familiarize yourself with the concept of scope.

Because its scope is the function Person::check, counter is only visible within the bounds of Person::check. No other parts of the program are allowed to interact with it.

Suggested solution:

Change Person::check (and its declaration) to return a boolean. Example:

bool Person::check() const 
{
    return weight>10;
}

The method is declared const to promise that this function will not change the object. This is done to prevent errors and allow a function that should not change the object to be used on a constant Person. This can prevent subtle errors from creeping into the code.

Now a user can check a Persons baggage weight and do with the result of check whatever they want. In the case of main, it wants to keep a count. There is no reason for anyone but main to know what it does, so counter should be scoped by main. eg:

int main()
{
   ...


    int counter = 0;
    for (int i = 0; i < 4; i++)
    {
        persons[i].show();
        if (persons[i].check()) 
        {
            counter++;
        }
    }
    cout<<"Ñ áàãàæîì áîëüøå 10 êã: "<<counter<<" ÷åëîâåê"<<endl;
    ...
}

Side note: There doesn't seem to be a need for persons to be dynamically allocated. Consider replacing

Person* persons=new Person[4];

with

Person persons[4];

and removing

delete[] persons;

If you are dynamically allocating in preparation for a variable number of Persons, prefer to use std::vector

std::vector<Person> persons;

and push_back or emplace_back Persons as they are introduced.

user4581301
  • 33,082
  • 7
  • 33
  • 54
  • I edited my code and now it give me this: [Warning] non-static data member initializers only available with -std=c++11 or -std=gnu++11 [Error] prototype for 'bool Person::check() const' does not match any in class [Error] candidate is: bool Person::check() void write(); void show(); bool check(); bool Person::check() const { return weight>10; } – Favoras Mar 25 '19 at 19:47
  • @Favoras in the class definition, `bool check();` would have to be `bool check() const`. I am unsure how you get the first error message. – user4581301 Mar 25 '19 at 19:57
0

Here's how you fix it. Declare counter in main, make check return bool, and count the number of times it returns false. This encapsulates counter and it makes more sense for check to actually return a Boolean value. Here's what the body of for loop should do:

if (!persons[i].check())
  ++counter
Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
0

The error message is correct, because there is no counter in main. You only declare counter here:

void Person::check()
{
    int counter = 0;
    if(weight>10)
    {
        counter++;
    }
}

and its scope is limited to that method. Actually each time the function is called you get a new counter which gets initialized to 0.

If instead you make counter a member you can keep its value across multiple calls to the method:

class Person() {
    public:
    int counter = 0;
    int check() {
        if (weight > 10) ++counter;
    }
    // ...other stuff left out
};

I also changed the method to return the value of the counter (otherwise you would have to write a getter or some means to get its value).

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185