Funkcja zwracająca trzy wartości

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.

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);

	// ...
}
0

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

3

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;
}
0

to bardziej do mnie przemawia !
Dziekuje!

1

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

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.

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

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;

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.

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