Wątek przeniesiony 2017-07-03 08:21 z C/C++ przez ŁF.

cannot be used as function; czemu?

0

Witam, zacząłem dzisiaj moją (mam nadzieję) długą przygodę z programowaniem. Na start postanowiłem zrobić program losujący (jak się później dowiedziałem, że możliwie tylko pseudo)losowe liczby w zakresie 1-29, a następnie umożliwiający użytkownikowi wpisanie 6 liczb i porównanie ich kolejno do tych wylosowanych. Zatrzymałem się na tworzeniu 6 różnych zmiennych dla każdej oddzielnej liczby, ponieważ nie wierzyłem, że nie wymyślono sposobu aby skrócić i ułatwić ten zapis. W internecie znalazłem poradnik o tym jak wykorzystywać tablice. Teraz mam problem - w sumie to nie rozumiem, czemu nie mogę skompilować tego kodu:

#include <iostream>
#include <cstdlib>
#include <time.h>
#include <windows.h>

using namespace std;
int liczba_losowan=5;
int liczby[5];
int losowanie[5];
int porownanie[5];
int main()
{
        cout << "losuje 6 liczb" << endl;
        for (int i=0; i<=liczba_losowan; i++)
        {
            srand(time(NULL));
            losowanie[i] = rand()%30+1;
            cout << losowanie[i] << endl;
            Sleep(1000);
        }
        cout << "wpisz 6 liczb: " << endl;
        for (int z=1; z<=liczba_losowan; z++)
        {
            cin >> liczby[z];
        }
        cout << "nastepuje porownanie liczb" << endl;
        Sleep(3000);
        for (int x=0; x<=liczba_losowan; x++)
        {
            cout << "porownuje "<< x << " wpisana liczbe z " << x << " wylosowana" << endl;
            if (liczby(x)==losowanie(x))
            {
                cout << "dobrze" << endl;
            }
            else
            {
                cout << "zle" << endl;
            }
        }
        return 0;
}

Wyskakuje komunikat, że "liczby" i "losowanie" nie mogą zostać użyte jako funkcje w if-ie. Dlaczego tak się dzieje? Można to jakoś obejść na poziomie totalnego początkującego?

PS: Jeżeli ktoś jest w stanie polecić dobrą książkę uczącą od podstaw tego języka to byłbym bardzo wdzięczny. Może być w języku angielskim(nawet preferuję).

2
(liczby(x) == losowanie(x))

nawiasów kwadratowych używa się z tablicami. liczby[x].
Nawiasy okrągłe używane są do wywoływania funkcji.

PS: jakakolwiek opisująca przynajmniej standard C++11. Zerknij w spis treści przy szukaniu.

0

Okej, poprawiłem na nawiasy tabel i trochę kod i działa. Ale jest następny problem, źle porównuje pierwszą wpisaną liczbę
konsola:

losuje 6 liczb
16
19
22
26
29
2
wpisz 6 liczb:
16
19
22
26
9
4
nastepuje porownanie liczb
porownuje 1 wpisana liczbe z 1 wylosowana
zle
porownuje 2 wpisana liczbe z 2 wylosowana
dobrze
porownuje 3 wpisana liczbe z 3 wylosowana
dobrze
porownuje 4 wpisana liczbe z 4 wylosowana
dobrze
porownuje 5 wpisana liczbe z 5 wylosowana
zle
porownuje 6 wpisana liczbe z 6 wylosowana
zle

Process returned 0 (0x0)   execution time : 16.846 s
Press any key to continue.

kod:

#include <iostream>
#include <cstdlib>
#include <time.h>
#include <windows.h>

using namespace std;
int liczba_losowan=5;
int liczby[5];
int losowanie[5];
int porownanie[5];
int main()
{
        cout << "losuje 6 liczb" << endl;
        for (int i=0; i<=liczba_losowan; i++)
        {
            srand(time(NULL));
            losowanie[i] = rand()%30+1;
            cout << losowanie[i] << endl;
            Sleep(1000);
        }
        cout << "wpisz 6 liczb: " << endl;
        for (int z=0; z<=liczba_losowan; z++)
        {
            cin >> liczby[z];
        }
        cout << "nastepuje porownanie liczb" << endl;
        Sleep(3000);
        for (int x=0; x<=liczba_losowan; x++)
        {
            cout << "porownuje "<< x+1 << " wpisana liczbe z " << x+1 << " wylosowana" << endl;
            if (liczby[x]==losowanie[x])
            {
                cout << "dobrze" << endl;
            }
            else
            {
                cout << "zle" << endl;
            }
        }
        return 0;
}

Nie wiem czemu wyszło "zle" w pierwszym.
Zarówno liczby[0] jak i losowanie[0] powinno mieć według napisanego kodu te same wartości, zgadza się?

A i jeszcze jedno pytanie, jakbym zamiast zmiennych "x" i "z" dał "i" ( tak, żeby w każdej pętli for zmienna była i ) to powodowałoby to jakieś komplikacje, czy śmiało mogę używać cały czas tej samej litery w przypadku różnych pętli?

0

Do losowania liczb można użyć nowszego narzędzia: uniform_int_distribution
Zamiast gołych tablic użyj: array
Zamiast Sleep() użyj: this_thread sleep_for
To

int liczba_losowan=5;
int liczby[5];
int losowanie[5];
int porownanie[5];

można zastąpić tym

constexpr int liczba_losowan=5;
int liczby[liczba_losowan];
int losowanie[liczba_losowan];
int porownanie[liczba_losowan];

Nie używasz wtedy magic number.

Skoro angielski nie jest problemem, pisz kod w języku angielskim.

0
czy constexpr jest tutaj konieczne? w jakim celu?
Konieczna, bo rozmiar tablicy musi być stały i znany w czasie kompilacji. `constexpr` można zastąpić `const`.
0

Nie do końca rozumiem. Jeżeli zrobiłem sobie zmienną liczba_losowan tylko po to, abym mógł wykorzystywać ją jako funkcję która będzie mi wygodnie zmieniała rozmiar kilku tablic na raz, które zawierają 6 znaków i mam zamiar tylko operować na tych 6 znakach (zmieniac, zapisywac i odczytywac je) a nie bezpośrednio ruszać tą zmienną liczba_losowan (dodawać, odejmować itp.) to ona z początkowego założenia - kiedy ją w ogóle tworzyłem jest i będzie stała ( nie mam zamiaru jej w ogóle użyć w kodzie, jest tylko po to, aby zmieniać rozmiar kilku tablic na raz ). Mój tok rozumowania jest zły? Jak coś proszę wybaczyć, jestem totalnie nowy :).

0

Teraz to zobaczyłem. Masz tam wyjście poza zakres tablicy. Undefined behavior.
Program może zachować się w niekontrolowany sposób, stąd pewnie problem z pierwszym porównaniem.
To akurat pikuś, a mógł się na tym wyłożyć.

2

Każda tablica o rozmiarze 5 ma indeksy 0 - 4.
Odczytanie danych z tablicy o indeksie 5 jest UB.

Jeszcze pozbyłem się zmiennych globalnych.
Nie korzystaj z nich jeśli nie zmusi cię do tego sytuacja, a twoim kodzie nie ma takiej potrzeby.

#include <iostream>
#include <array>
#include <random>
#include <thread>
using namespace std;

int main()
{
    mt19937_64 generator(random_device{}());
    uniform_int_distribution<int> distance(1, 30);

    constexpr size_t size = 6;
    array<int, size> randomedNums;
    array<int, size> myNums;

    cout << "losuje 6 liczb" << endl;
    for (size_t i = 0; i < size; ++i)
    {        
        randomedNums[i] = distance(generator);
        cout << randomedNums[i] << endl;
        this_thread::sleep_for(1s);
    }

    cout << "wpisz 6 liczb: " << endl;
    for (size_t z = 0; z < size; ++z)
    {
        cin >> myNums[z];
    }

    cout << "nastepuje porownanie liczb" << endl;
    this_thread::sleep_for(3s);
    for (size_t x = 0; x < size; x++)
    {
        cout << "porownuje " << x + 1 << " wpisana liczbe z " << x + 1 << " wylosowana" << endl;
        if (randomedNums[x] == myNums[x])
        {
            cout << "dobrze" << endl;
        }
        else
        {
            cout << "zle" << endl;
        }
    }
    return 0;
} ```
0

Ok

  1. Przeczytałem, że size_t to kolejna zmienna, z tą różnicą, że bez znaku i może pomieścić teoretycznie maksymalną liczbę dowolnego typu obiektu. Nie do końca rozumiem różnicy pomiędzy np. zwykłym int, poza tym, że int ma jakiś zakres. Czemu np. constexpr size_t size = 6; albo for (size_t x = 0; x < size; x++) a nie po prostu for (int x = 0; x < size; x++) . Jakie to ma praktycznie różnice? x i tak nie osiąga w tym przypadku niemożliwych dla int odczytania wartości.
  2. uniform_int_distribution<int> distance(1, 30); Jak dobrze rozumiem to <int> wpisujemy jako zmienną, która będzie "zawierała" rozmiar losowania (1-30). Czyli, jakbym chciał losować z o wiele większego przedziału to musiałbym zmienić np. na long tak?
  3. mt19937_64 generator(random_device{}()); Tego nie czaje, chyba zbyt dużo informacji do przyswojenia dla kogoś z dniem doświadczenia. Rozumiem, że to generuje nam losową liczbę - generator(random_device{}()); to integer który losowo generuje liczbę i zapisuje ją w funkcji generator. Nie mam pojęcia skąd i po co są {}() na koniec. Nie mam pojęcia po co jest mt19937_64. Nawet po poczytaniu opisów.
  4. this_thread::sleep_for(1s); jak patrze na przykłady na internecie to wszędzie jest std::. Rozumiem, że nie muszę tego pisać bo mam using namespace std; w kodzie( było razem z helloworld ). Mogę analogicznie dać using namespace this_thread; i nie musieć już pisać this_thread:: za każdym razem?

Jak chcę uruchomić Twój kod to wyskakuje mi coś takiego error This file requires compiler and library support for the \ ISO C++ 2011 standard. This support is currently experimental, and must be \ enabled with the -std=c++11 or -std=gnu++11 compiler options. gdzie mam te komendy wpisać?

1

size_t zależy od implementacji kompilatora. To jest typ zmiennej bez znaku i może być odpowiednikiem unsigned int, unsigned long itd.
Zastosowałem ją, ponieważ kontenery używają wartości typu size_t do określenia swojego rozmiaru, więc nie ma sensu zmuszać kompilator do
niejawnych konwersji typów (możliwa utrata danych). W tym przypadku nie miałoby to znaczenia, ale czepialski kompilator może dać ostrzeżenie o niezgodności typów.

edit: błąd związany jest z niewłączonym standardem C++11. Dodaj flagę -std=c++11 do kompilatora i powinno działać. Zobacz w dokumentacji jak to się robi w twoim kompilatorze.

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