Funkcja zwracająca trzy wartości

Odpowiedz Nowy wątek
2019-07-30 10:08
0

Czesc napisalem oto taki program ktory liczy ile czytano duzych i malych liter oraz cyfr. Konczy sie po wprowadzeniu dwoch po sobie kropek.
Oto kod:

#include <iostream>

using namespace std;

int main()
{
    char znak_pierwszy, znak_drugi, znak_poprzedni, znak_aktualny;
    int licznik_duzych = 0;
    int licznik_malych = 0;
    int licznik_cyfr = 0;

    cout << "Prosze podac pierwszy znak ";
    cin >> znak_pierwszy;
    if ((znak_pierwszy >= 'a') && (znak_pierwszy <= 'z'))
    {
        licznik_malych++;
    }
    else if ((znak_pierwszy >= 'A') && (znak_pierwszy <= 'Z'))
    {
        licznik_duzych++;
    }
    else if ((znak_pierwszy >= '0') && (znak_pierwszy <= '9'))
    {
        licznik_cyfr++;
    }
    cout << "Prosze podac drugi znak ";
    cin >> znak_drugi;
    if ((znak_drugi >= 'a') && (znak_drugi <= 'z'))
    {
        licznik_malych++;
    }
    else if ((znak_drugi >= 'A') && (znak_drugi <= 'Z'))
    {
        licznik_duzych++;
    }
    else if ((znak_drugi >= '0') && (znak_drugi <= '9'))
    {
        licznik_cyfr++;
    }

    znak_poprzedni = znak_pierwszy;
    znak_aktualny = znak_drugi;
    while (znak_poprzedni != '.' || znak_aktualny != '.')
    {
        znak_poprzedni = znak_aktualny;
        cout << "Prosze podac kolejny znak ";
        cin >> znak_aktualny;
        if ((znak_aktualny >= 'a') && (znak_aktualny <= 'z'))
        {
            licznik_malych++;
        }
        else if ((znak_aktualny >= 'A') && (znak_aktualny <= 'Z'))
        {
            licznik_duzych++;
        }
        else if ((znak_aktualny >= '0') && (znak_aktualny <= '9'))
        {
            licznik_cyfr++;
        }

    }
    cout << "Wczytano " << licznik_duzych << " duzych liter." << endl;
    cout << "Wczytano " << licznik_malych << " malych liter." << endl;
    cout << "Wczytano " << licznik_cyfr << " cyfr. " << endl;
    system("pause");
    return 0;
}

Zastanawiam sie nad napisaniem funkcji dla

        if ((znak_aktualny >= 'a') && (znak_aktualny <= 'z'))
        {
            licznik_malych++;
        }
        else if ((znak_aktualny >= 'A') && (znak_aktualny <= 'Z'))
        {
            licznik_duzych++;
        }
        else if ((znak_aktualny >= '0') && (znak_aktualny <= '9'))
        {
            licznik_cyfr++;
        }

Jednak nie wiem jak zapisac funkcje ktora by mogla zwracac 3 wartosci do main() dla licznikow.

edytowany 2x, ostatnio: cerrato, 2019-07-30 10:17

Pozostało 580 znaków

2019-07-30 10:18
1

Możesz przekazać te liczniki do funkcji przez referencję.

void foo(int &licznik_duzych, int &licznik_malych, int &licznik_cyfr)
{
    // ...
}

int main()
{
    int licznik_duzych = 0;
    int licznik_malych = 0;
    int licznik_cyfr = 0;

    // ...

    foo(licznik_duzych, licznik_malych, licznik_cyfr);

    // ...
}

Pozostało 580 znaków

2019-07-30 10:19
0

Dzięki za odpowiedź, w takim razie przeczytam o referencji w C++

edytowany 1x, ostatnio: cerrato, 2019-07-30 10:21

Pozostało 580 znaków

2019-07-30 11:01

Możesz też użyć struktury:

#include <iostream>

using namespace std;

struct Liczniki {
    int licznik_duzych;
    int licznik_malych;
    int licznik_cyfr;
};

Liczniki policz(char znak, Liczniki poprzednio) {
        Liczniki wynik(poprzednio);
        if ((znak >= 'a') && (znak <= 'z'))
        {
            wynik.licznik_malych++;
        }
        else if ((znak >= 'A') && (znak <= 'Z'))
        {
            wynik.licznik_duzych++;
        }
        else if ((znak >= '0') && (znak <= '9'))
        {
            wynik.licznik_cyfr++;
        }
        return wynik;
}

int main()
{
    char znak_pierwszy, znak_drugi, znak_poprzedni, znak_aktualny;
    Liczniki liczniki;

    liczniki.licznik_duzych = 0;
    liczniki.licznik_malych = 0;
    liczniki.licznik_cyfr = 0;

    cout << "Prosze podac pierwszy znak ";
    cin >> znak_pierwszy;

    liczniki = policz(znak_pierwszy, liczniki);

    cout << "Prosze podac drugi znak ";
    cin >> znak_drugi;
    liczniki = policz(znak_drugi, liczniki);

    znak_poprzedni = znak_pierwszy;
    znak_aktualny = znak_drugi;
    while (znak_poprzedni != '.' || znak_aktualny != '.')
    {
        znak_poprzedni = znak_aktualny;
        cout << "Prosze podac kolejny znak ";
        cin >> znak_aktualny;
        liczniki = policz(znak_aktualny, liczniki);
    }
    cout << "Wczytano " << liczniki.licznik_duzych << " duzych liter." << endl;
    cout << "Wczytano " << liczniki.licznik_malych << " malych liter." << endl;
    cout << "Wczytano " << liczniki.licznik_cyfr << " cyfr. " << endl;
    system("pause");
    return 0;
}

Szacuje się, że w Polsce brakuje 50 tys. programistów

Pozostało 580 znaków

2019-07-30 11:03
0

to bardziej do mnie przemawia !
Dziekuje!

Pozostało 580 znaków

2019-07-30 11:11
1

Możesz też użyć std::tuple'a jako agregat zwracanych wartości.


"Sugeruję wyobrazić sobie Słońce widziane z orbity Merkurego, a następnie dupę tej wielkości. W takiej właśnie dupie specjalista ma teksty o wspaniałej atmosferze, pracy pełnej wyzwań i tworzeniu innowacyjnych rozwiązań. Pracuje się po to, żeby zarabiać, a z resztą specjalista sobie poradzi we własnym zakresie, nawet jeśli firma mieści się w okopie na granicy obu Korei."
-somekind,
konkretny człowiek-konkretny przekaz :]
edytowany 1x, ostatnio: MasterBLB, 2019-07-30 11:11

Pozostało 580 znaków

2019-07-30 11:37
3
MasterBLB napisał(a):

Możesz też użyć std::tuple'a jako agregat zwracanych wartości.

Każdy fajny feature jest nadużywany. Moda na nadużywanie tuple strasznie mnie irytuje.
std::tuple został zaprojektowany do generic programing. Np piszesz szablon, który przyjmuje nieznaną liczbę argumentów, które trzeba przechować na potem, by potem użyć z std::apply.
Wady tuple w normalnym programowaniu: pola nie mają czytelnych nazw - ważniejsze są pozycje pól niż ich nazwy. Utrzymywanie w kodzie pozycji gdzie co jest jest trudne, nieporęczne, błędogenne, nieczytelne.
Przewaga tuple nad zwykła strukturą: definicja jest krótka, za darom dostaje się operatory porównania. Te "zalety" są dla mnie niewystarczające, by używać tuple poza szablonami, wolę kod który jest czytelny, który nie wymaga skakania miedzy plikami źródłowymi.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 1x, ostatnio: MarekR22, 2019-07-30 11:38
Bracie Marku, wszytko to prawda, ale ja nie rekomenduję tuple'a do użycia ponad strukturę, tylko uświadamiam autora o innej metodzie na rozwiązanie jego dylematu. A co autorowi bardziej podpasuje to już niech on sam decyduje. - MasterBLB 2019-07-30 12:55
IMHO, w momencie wprowadzenia structured binding (C++17) , użycie tuple jako sposobu na zwracania wielu wartości staje się powoli akceptowalnym standardem. https://github.com/isocpp/Cpp[...]oreGuidelines.md#Rf-out-multi https://stackoverflow.com/que[...]iple-values-from-a-c-function - TomaszLiMoon 2019-07-30 12:56

Pozostało 580 znaków

2019-07-30 11:59
3
MisiakPisiak napisał(a):

Zastanawiam sie nad napisaniem funkcji dla

      if ((znak_aktualny >= 'a') && (znak_aktualny <= 'z'))
      {
          licznik_malych++;
      }
      else if ((znak_aktualny >= 'A') && (znak_aktualny <= 'Z'))
      {
          licznik_duzych++;
      }
      else if ((znak_aktualny >= '0') && (znak_aktualny <= '9'))
      {
          licznik_cyfr++;
      }

Jednak nie wiem jak zapisac funkcje ktora by mogla zwracac 3 wartosci do main() dla licznikow.

Im szybciej nauczysz się pisać mniejszymi funkcjami tym lepiej.
W tym wypadku użyłbym szablonów, ale żeby było bardziej zrozumiałe dla początkującego popatrz na to:

class CharCounter
{
public:
     explicit CharCounter(bool (*predicate)(char)) : predicate{predicate} {}

     void add(char ch) {
          mCount += predicate(ch));
     }
     size_t count() const {
         return mCount;
     }
private:
     bool (*predicate)(char);
     size_t mCount = 0;
};

struct NamedCharCounter {
     std::string name;
     CharCounter count;
};

struct CharStatistics {
     void add(char ch) {
          for(auto& counter : counters) {
               counter.add(ch);
          }
     }

    NamedCharCounter counters[] = {
         "duże litery", upperCount{ &std::isupper },
         "małe litery", lowerCount{ &std::islower },
         "cyfry", digitCount{ &std::isdigit },
    }
};

int main()
{
    CharStatistics stats;
    char a, b;
    if (std::cin >> b) {
          stats.add(b);
          while(std::cin >> b && (a !='.'  || b !='.')) {
                stats.add(a);
                b = a;
          }
    }
    ....
}

Dużo rzeczy wylądowało poz a main nawet nie tyle w funkcjach, ale w klasach, przez co wszystko jest czytelniejsze i łatwiejsze w rozszerzaniu, modyfikowaniu itp.
To można (powinno) popchnąć jeszcze dalej tak, że w main zostanie maks 5 linijek


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 1x, ostatnio: MarekR22, 2019-07-30 12:01
co myślisz o tworzeniu tylko jednej instancji głównej klasy w mainie, zabezpieczenie jej, a sterowanie przekazać konstruktorowi tej klasy i metodom (pomijając, że to może być blob czy god class)? - Sunnydev 2019-07-30 12:26
god class to określenie negatywne oznaczające ekstremalne naruszanie "Single Responsibility principle". Kontroler łączący ze sobą wszystkie zależności jest jak najbardziej ok. - MarekR22 2019-07-30 15:47

Pozostało 580 znaków

2019-07-30 21:48
0

Można też skorzystać z mapy <typ_licznika, aktualna wartość>

enum counters { licznik_malych, licznik_duzych, licznik_cyfr };
std::map <counters, int > counters_state;

Pozostało 580 znaków

2019-07-31 08:32
0
MarekR22 napisał(a):

Im szybciej nauczysz się pisać mniejszymi funkcjami tym lepiej.
W tym wypadku użyłbym szablonów, ale żeby było bardziej zrozumiałe dla początkującego popatrz na to:

Dużo rzeczy wylądowało poz a main nawet nie tyle w funkcjach, ale w klasach, przez co wszystko jest czytelniejsze i łatwiejsze w rozszerzaniu, modyfikowaniu itp.
To można (powinno) popchnąć jeszcze dalej tak, że w main zostanie maks 5 linijek

Dzieki za odpowiedz !
Wlasnie w sumie w o to chodzilo w moim pytaniu, jak zrobic funkcje aby nie potrzebnie nie pisac wszystkiego w funkcji main ()
Niestety szablony jak i klasy to jeszcze ciut za daleko idacy material. Dlatego przemawia do mnie bardziej struktura i funkcja ktora lepiej rozumiem.
Dziekuje jednak za wszystkie odpowiedzi, mam zapisane watek i zbiegiem czasu wroce do przerobienia tego zadania dzieki szablona i klasa.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0