• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Jaki typ tablicy, aby na początku mogło być 0

Object Storage Arubacloud
0 głosów
369 wizyt
pytanie zadane 17 sierpnia 2015 w C i C++ przez Jonki Dyskutant (8,180 p.)
zmienione kategorie 17 sierpnia 2015 przez Jonki

Witam! Piszę proste logowanie i rejestrację do bankomatu, ale mam problem z rejestracją PINu. Nie wiem co mam zrobić, aby w PINach czytało mi 0 na początku. Tablice string nie da rady zrobić, a int nie czyta 0 na początku i mam wielki problem.

EDIT: Jesze jedno pytanko. Jak mam napisać, aby funkcja zaloguj miała dostęp do tablicy utworzonej w funkcji zarejestruj? Tablice globalne nie wchodzą chyba w grę.

main.cpp

 

#include <iostream>
#include "naglowki.h"

using namespace std;

int main()
{

    Uzytkownik u1;
    u1.pokaz();

    return 0;
}

 

naglowki.h

#include <iostream>
#include <fstream>

using namespace std;

class Uzytkownik
{
    string PPIN;
    int StanKontaPoczatkowy;
    fstream plik;

public:

    void pokaz();
    void zaloguj();
    void zarejestruj();
};

funkcje.cpp

#include <iostream>
#include <windows.h>
#include <conio.h>
#include <fstream>
#include "naglowki.h"
#include <string>

using namespace std;

void zaloguj();
void zarejestruj();

void Uzytkownik::pokaz()
{
    char wybor;

    system("cls");
    cout << "\t" << "Witaj w banku!" << endl;

    cout << "1. Zaloguj" << endl;
    cout << "2. Zarejestruj" << endl << endl;

    cout << "Wybor: ";
    wybor = getch();

    switch(wybor)
    {
    case '1':
        {

        break;
        }
    case '2':
        {
        zarejestruj();
        break;
        }
    }
}

void Uzytkownik::zarejestruj()
{
    static int licznik = 0;
    licznik++;

    system("cls");
    cout << "\t" << "REJESTRACJA" << endl << endl;

    cout << "Podaj PIN: ";
    cin >> PPIN;
    cout << endl;

    int *PIN;
    PIN = new int;

    PIN[licznik] = atoi(PPIN.c_str());

    int *StanKonta;
    StanKonta = new int;

    StanKonta[licznik] = StanKontaPoczatkowy;

    plik.open("uzytkownicy.txt", ios::out | ios::app);
    if (plik.good() == false)
    {
        system("cls");
        cout << "\t" << "Blad polaczenia z baza danych!";
        Sleep(2000);
    }
    else
    {
        plik << PIN[licznik];
        plik << endl << StanKonta[licznik] << endl;

        plik.close();
    }
}

 

3 odpowiedzi

+1 głos
odpowiedź 17 sierpnia 2015 przez Krawiec91 Pasjonat (19,600 p.)
Witam.
1. W jakim celu chcesz PIN do int'a zapisać? Bo jakoś większego sensu nie widzę, przy typie int liczbę zero na początku przy wyświetlaniu będzie Ci ignorowało, zresztą logiczne, po co zera z przodu dopisywać. Wiadome, że milej jak się z tyłu zera dopisuje, szczególnie na koncie.;)
Ale jest wyjście w wypadku jakbyś się uparł z tym, żeby to do int zapisać. Musisz stworzyć tablicę int i każdy element ze stringa po konwersji na int zapisywać do kolejnych pól tablicy int.
komentarz 17 sierpnia 2015 przez Jonki Dyskutant (8,180 p.)
edycja 17 sierpnia 2015 przez Jonki

A to nie powinno przesuwać po elemtach tablicy, tylko po adresach w pamięci?

To jak mam zalokować tą pamięć dynamicznie, aby było wszystko OK.

 

W ogóle nie rozumiem działanie tej tablicy. Czyli wychodzi, że daję tylko znać, że będzie tu tablica. Za każdym wywołaniem rejestracji tworzę jeden elemnt np. o adresie 150500 i funkcja kończy pracę. Potem, gdy znowu wywołam rejestrację, tworzę nowy element o adresie jakimkolwiek wyższym, ale nie o 4 bajty wyższym, czyli 150504, tylko tam gdzie adres jest wolny.

Wydawało mi się, że jaki adres maja elementy w tablicy nie ma znaczenia, bo program wie, że jesli odwołuję się do PIN[0] to odczytuje wartość z komórki o adresie 150500, a gdy odczytuje wartość z PIN[1] to szuka tego adresu w pamięci i z niego odczytuje wartość.

Czyli chcesz mi powiedzieć, że funkcja rejestracji wcale nie zapisuje pinów do tej tablicy, ale do notatnika to już tak. Odczytanie z * też pokazuje nie wiadomo jak wielką cyfrę.

int *PIN;                  //tworzenie zmiennej wskaźnik
PIN = new int;       // tworzenie jednego elementu
cin >> PIN[licznik-1];     //podanie wartości do zerowego elemetu


Ponowne uruchomienie programu 


PIN = new int;       // tworzenie jednego elementu
cin >> PIN[licznik-1];     //podanie wartości do pierwszego  elemetu

I jak to jest z tym tworzeniem tablicy. Napisze new int i tworzy jeden element, potem znowu napiszę new int i znowu tworzy jeden element, to tablica jest już dwu elementowa czy jak?

komentarz 17 sierpnia 2015 przez Krawiec91 Pasjonat (19,600 p.)

Po kolei bo i ja się zaczynam trochę gubić.
1. Operatorem new zgłaszasz żądanie przydzielenia pewnego obszaru pamięci na dane. Do przykładów zakładam, że int ma 4 - bajty. Na przykład instrukcją:
 

int* wsk_dane=new int;

zgłaszasz żądanie przydzielenia 4 bajtów pamięci na zmienną int. Jeśli system posiada tyle wolnej pamięci to przydziela ją i do wsk_dane zostaje przypisany adres początku bloku pamięci, która została przydzielona - wskaźnik na typ int. Jeżeli nie ma dostatecznej ilości pamięci to przypisywany jest do zmiennej NULL pointer. Kolejny przykład:
 

int* wsk_array=new int[10];

W tym wypadku zgłaszasz żądanie przydzielenia 40 (10*4 bajty) bajtów pamięci na tablicę typu int. Jeśli tyle system może przydzielić, to do wsk_array przypisany jest adres początku bloku przydzielonej pamięci, innymi słowym adres pierwszego elementu tablicy. Kolejne elementy masz przesunięte o 4 bajty, bo taki rozmiar ma zmienna int.

Przechodząc do sedna sprawy operacje:
 

int* wsk=new int[2];

oraz dwukrotne użycie

int* wsk=new int;

Nie będzie sobie równoważne, jakieś tam prawdopodobieństwo istniej, że obok siebie zostałyby zaalokowane zmienne, ale lepiej nie ryzykować.. W pierwszym przypadku tworzysz tablice 2 - elementową int, czyli 2 int-y będą w pamięci obok siebie, przesunięte o 4 bajty.
W drugim przypadku tworzysz 2 wskaźniki na int, powiedzmy 2 zmienne int, które mogą nie być obok siebie ułożone jak w tablicy, bo system przydziela akurat w danej chwili obszar pamięci (adres) i niekoniecznie będą to komórki pamięci obok siebie, żeby móc odwoływać się jak do tablicy.

2. Wracając do Twojego kodu.

    PIN = new int;
 
    cout << "Podaj PIN: ";
    cin >> PIN[licznik-1];
    cout << endl;

Za każdym wywołaniem funkcji zarejestruj() tworzysz nowy wskaźnik na int (1 sztuka). Zakładam, że PIN to wcześniej utworzony wskaźnik na int. Następnie próbujesz zapisujesz tam co wprowadziłeś i to będzie działać. Tak samo poprawnie działa ze stanem początkowym konta. Wrzuciłeś to co w notatniku, jest git.

3. Clue sprawy to to, że funkcja zarejestruj() nie tworzy tablicy typu int, w sensie myślenia, że tablica zawiera więcej niż jeden element. Tylko za każdym razem tworzy jeden wskaźnik na int (jedną zmienną, nie tablicę), więc te zmienne nie muszą i raczej nie będą znajdować się obok siebie jak w tablicy (Punkt 1). Cześć z zapisywaniem danych do pliku będzie działać, tworzysz jedną zmienną, zapisujesz tam coś i zrzucasz to do pliku.

4. Jeszcze a propo wskaźników. Jeśli tworzysz dynamicznie wskaźniki, w przypadku gdy nie są one już wykorzystywane w programie należy jest usuwać za pomocą operatora delete.  Zaalokowanej dynamicznie a nie zwolnionej pamięci, nie można ponownie zaalokować. Nie ma do niej dostępu. Nie zwalniając niepotrzebnej pamięci zawężasz sobie dostępną pulę.

Pokaż ta funkcje pokaz() to zobaczę co tam może nie grać. Możliwe, że próbowałeś odwoływać się tam jakbyś miał utworzoną tablicę i wyświetla nie to co trzeba. Ale to tylko przypuszczenie, kod bym zobaczył to by się problem rozwiązał.

komentarz 17 sierpnia 2015 przez Jonki Dyskutant (8,180 p.)
Jestem taki głupi, że sobie nie wyobrażasz. Mój kod może nie jest jakoś super poukładany, ale działa i to dobrze. Po prostu zrąbało mi się myślenie. Podczas rejestracji przypisywałem do PIN[0] podany PIN i program sie kończył. Po ponownym jego uruchomieniu znowu dodawałem nowy PIN w zerowy element i znowu sie kończył. I tak ciągle włączałem i wyłączałem. No i potem za którymś razem dodałem w funkcji pokaz cout << PIN[2], no i w tym momencie pokazywało mi jakies śmieci. No ale jak mogło być inaczej jeśli tam nic przecież nie było. Dopiero kiedy dałem to wszystko w pętle w pliku main, mogłem bez restartu programu dodawać do kolejnych elementów tablicy PINy i po wyświetleniu np. PIN[2] pokazywało mi podany PIN. I nad tym siedziałem cały dzień .Masakra jakaś.
komentarz 17 sierpnia 2015 przez Krawiec91 Pasjonat (19,600 p.)
Czyli moje podejrzenia okazały się słuszne. Każdemu zdarza się zamulić na mniejszych czy większych pierdołach. Do dziś pamiętam sytuację prawie sprzed roku jak zacząłem C++ się na powaznie uczyć, żeby programowanie na studiach zaliczyć. Wykładowca kazał mi program z użyciem struktur zrobić (wektory w trójwymiarze) i funkcję, która załatwiłaby zarówno dodawanie, odejmowanie. Ogólnym zamysłem było wykorzystanie reference i wskaźników w funkcjach.
Usłyszałem zadanie, banan na twarzy, na szybkości się program napisze i będzie gites. No i lece z tematem, wszystko porobione jak należy, program się kompiluje bez errorów, bez warningów. Sprawdzam program dodawanie działa jak należy, ale z odejmowaniem lipa wyrzuca mi jakieś śmieci. Kombinuje, zamieniam referencję na wskaźniki i odwrotnie no dalej nic. W końcu wykładowca mi znalazł błąd - dałem instrukcję return w środku funkcji. Suma wektorów miała byś "klasycznie zwracana" returnem, a różnica wektorów miała być zrobiona przez referencję. A tak to funkcja wykonała się w połowie.
Program pisałem 15 minut, szukałem błędu jakieś 1.5 godziny.

Czułość na takie błędy wzrosła lawinowo po tam incydencie. Dzień straciłeś, ale na przyszłość to pewnie lampka się będzie w głowie zapalała przy tablicach i pointerach.;)
komentarz 17 sierpnia 2015 przez Jonki Dyskutant (8,180 p.)
Tak przyglądając się programowi, doszedłem do wniosku, że używanie w rejestracji tablicy jest bez sensu, w ogóle nie potrzebne. Wystarczy zmienna i tyle. Potrzeba tylko wpisać do notatnika, a nie do jakiejś tam tablicy, co nie?
0 głosów
odpowiedź 17 sierpnia 2015 przez niezalogowany
  1. Przenieś temat do innego wątku, bo ,,Nasze projekty" jest w dyskusjach, czyli że pokazujesz swój projekt i chcesz się nim pochwalić, zapytać, co poprawić, co by tam dodać, ale wszystko działa. Przenieś do ,,C i C++" ;)
  2. Niezbyt cię rozumiem: chodzi ci o to, że PIN typu string w klasie Uzytkownik nie chce się zarejestrować? Czy co? W ogóle cię nie rozumiem. Niezbyt wiem o co ci chodzi O_o Wytłumacz trochę dokładniej ;)
komentarz 17 sierpnia 2015 przez Krawiec91 Pasjonat (19,600 p.)
Wydaje mi się, że chodzi o to że przy wyświetlaniu na ekran początkowego zer(a) nie wyświetla.;) Jak wpisze PIN np. 0001 to wyświetli mu potem tylko 1.
komentarz 17 sierpnia 2015 przez niezalogowany
:O No to prosta sprawa, jeśli rzeczywiście tak jest ;)
komentarz 17 sierpnia 2015 przez Jonki Dyskutant (8,180 p.)
Dla mnie nie prosta.
komentarz 17 sierpnia 2015 przez niezalogowany
Chodzi ci o to, żeby wyświetlało się ileś tam zer przed hasłem, tak? Powiedzmy, że hasło ma 10 znaków, a użytkownik wpisał tylko 8 i żeby przed tym były jeszcze 2 zera? Według mnie to trochę dziwne, bo użytkownik wybiera sobie hasło i tyle, te zera mogą trochę mylić :| Jak o to ci chodzi, to powiedz w której linijce ma się to tak wyświetlać ;)
komentarz 17 sierpnia 2015 przez Jonki Dyskutant (8,180 p.)
Nie. Chodzi o to, ze dajmy przykład chcę się zarejestrować i podaję PIN: 0794. A w notatniku zostaje zapisane tylko 794.
komentarz 17 sierpnia 2015 przez niezalogowany

Aha... No to ciekawa sprawa... A potem żeby się "zalogować" to trzeba też wpisać 0794, czy już wystarczy tylko 794? Dobra, tutaj masz taki kod (PIN jest stringiem, czyli tak jak chyba chcesz):

for(unsigned int i=0;i<PIN.length();i++)
{
    if(PIN[i]!='0')
    {
        PIN.erase(0,i);
        break;
    }
}

Spróbuj ten kod, tylko go przerób tak, żeby pasowało do programu ;)

0 głosów
odpowiedź 17 sierpnia 2015 przez Dorion300 Szeryf (90,250 p.)
int *PIN;
PIN = new int;
PIN[licznik] = atoi(PPIN.c_str());

A wiesz że tak się nie robi dynamicznej tablicy?

Zmień na:

int *PIN;
PIN = new int[licznik];
 
PIN[licznik-1] = atoi(PPIN.c_str());

Tak samo ze "stanem konta"

Podobne pytania

0 głosów
2 odpowiedzi 134 wizyt
pytanie zadane 7 stycznia 2021 w PHP przez vingilot85 Obywatel (1,150 p.)
0 głosów
1 odpowiedź 215 wizyt
pytanie zadane 15 lutego 2021 w C i C++ przez Rainbow99 Początkujący (430 p.)
0 głosów
1 odpowiedź 738 wizyt
pytanie zadane 5 maja 2020 w C i C++ przez pseudoinformatyczka Nowicjusz (140 p.)

92,576 zapytań

141,426 odpowiedzi

319,650 komentarzy

61,961 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...