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

Dynamiczna struktura danych - odczytywanie konkretnej pozycji

Object Storage Arubacloud
0 głosów
618 wizyt
pytanie zadane 25 czerwca 2015 w C i C++ przez bather Nowicjusz (160 p.)
edycja 25 czerwca 2015 przez bather

Cześć, 

próbuję stworzyć swój pierwszy program, w którym mam dynamicznie zaalokowaną pamięć na strukturę - użytkownik podaje dane pracowników firmy (Imie, Nazwisko, Pesel, Stawka), które następnie są zapisywane do pliku (i ewentualnie z tego pliku odczytywane). 

Problem pojawił się, gdy chciałem zrobić funkcję wyszukiwania w tej strukturze (wczytanej z pliku). Mianowicie chciałbym, aby po wpisaniu przez użytkownika jakiegoś nr Pesel program sprawdził czy w tej strukturze taki pesel wystąpił a następnie wyświetlił pozostałe dane, od osoby, do której taki pesel jest przypisany. O ile sprawdzenie czy pesel występuje jakoś udało mi się osiągnąć, to dalszej części już niestety nie jestem w stanie rozwiązać... 

Dodam, że struktura nie jest tablicą. Czy da się to osiągnąć bez tworzenia tablicy? (dla osoby stawiającej pierwsze kroki w c++). 

struct baza
{
    string imie, nazwisko, stanowisko, stawka;
    long long int pesel;
};
baza * wsk = new baza;

[.....]

Funkcja wyszukiwania

{
cout << "Podaj nr PESEL, aby wyszukac pracownika: " << endl;
    string pesel_tmp;
    cin >> pesel_tmp;
    cout << endl << endl;


    fstream plik;
    plik.open("pracownicy.txt", ios::in); //otwarcie pliku do odczytu

    if (plik.good()==false)
    {
        cout << "Blad! Plik nie istnieje!" << endl;
        exit(0);
    }

string linia;
int nr_linii=3; //na 3ciej linii znajduje sie pierwszy pesel
bool flaga=0;

while (getline(plik, linia))
    {
        switch(nr_linii)
        {
            case 3:
            if (linia == pesel_tmp)
            {
                flaga=1;

            }
            break;
        }
        nr_linii+6; //kolejny pesel jest 6 linii dalej
	}



	if (flaga==1)
        cout << "Znalazlem pracownika" << endl;
    if (flaga==0)
        cout << "Nie znalazlem pracownika "<< endl;

 plik.close();


}

 

 

EDIT: To wyszukiwanie niby działa, ale jest bez sensu napisane - nr_linii+6; jest w ogóle tutaj nie potrzebne... Ehhh... 

2 odpowiedzi

+2 głosów
odpowiedź 25 czerwca 2015 przez criss Mędrzec (172,590 p.)
edycja 26 czerwca 2015 przez criss

nr_linii+6 nie robi absolutnie nic :P Program po prstu doda do wartości zmiennej 6 i nigdzie tego nie zapisze. Powinieneś napisać nr_linii = nr_linii +6; . Ale i tak nie wiem jak to ma u ciebie działać jeżeli nr_linii ma od poczatku wartość 3. W taki sposób już na pierwszej linii program stwierdzi, że to jest to co chce mieć. A nie chce. Ja bym to zrobił w ten sposób:

nr_linii=0;
while (getline(plik, linia))
    {
     if(nr_linii%3 == 0 && nr_linii!=0){
                 if (linia == pesel_tmp)
                 {
                flaga=1;
                break;} //koniec while-a jesli znalezlismy
    }
        nr_linii++;
    }

Nie ma sensu używac switcha z jednym casem i to takim krótkim. Btw. jeśli w ifie jest jedna komenda, to nie musisz używać {} .

+1 głos
odpowiedź 25 czerwca 2015 przez draghan VIP (106,230 p.)

Słuchaj, jeśli chcesz wyszukiwać tylko po numerze PESEL, to najwygodniej Ci będzie zapisywać dane o osobie, zaczynając od PESELu. :)

Wtedy, o ile znajdziesz odpowiedni numer PESEL, pozostałe dane będą w odpowiednich kilku linijkach niżej. :)

Powiedzmy, taki przykład:

1234567890123
Jan
Kowalski
1234567890122
Janina
Kowalska
1111111111111
Krzysztof
Kamiński

I kiedy znajdziesz PESEL == 1111111111111 w linii 7, to imię i nazwisko masz w liniach numer 8 i 9. :)

komentarz 25 czerwca 2015 przez draghan VIP (106,230 p.)
I jeszcze coś: o ile to nie jest duuuża baza danych, to chyba lepiej wczytać sobie wszystkich pracowników do pamięci (tablicy, vectora, listy...) i wtedy wygodnie przeszukiwać. :)
komentarz 25 czerwca 2015 przez bather Nowicjusz (160 p.)
Chyba jednak wybiorę tę pierwszą opcję, czyli zmianę kolejności danych. Bo wczytanie wszystkich pracowników do tablicy chyba nie jest takie proste... przynajmniej dla mnie :P

Korzystając z podpowiedzi kolegi poniżej (dzięki!) i skoro to wyszukiwanie już działa, to teraz jest jeszcze jedna rzecz, której nie udało mi się rozwiązać... Jak wyłuskać dane, które siedzą w konkretnej linii? Tak jak w tym przypadku 8 i 9.
komentarz 25 czerwca 2015 przez criss Mędrzec (172,590 p.)
draghan - i tu jest pewien problem, bo jesli znalazłeś pesel w linii 7 to 8. i 9. już nie dostaniesz. Jasne, można to zrobić, ale znacznie łatwiej jest z taką kolejnością jak teraz.
komentarz 25 czerwca 2015 przez criss Mędrzec (172,590 p.)
bather - jeszcze dodaj break w wypadku znalezienia zeby nie szukał dalej bez potrzeby.
komentarz 25 czerwca 2015 przez draghan VIP (106,230 p.)

Znacznie łatwiej jest po prostu zrobić metody do tej struktury, które będą sobie same wczytywały dane. ;) Może to nie jest idealny kod, ale ilustruje co należy. ;)

#include <string>
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;

struct baza
{
    string imie, nazwisko, stanowisko, stawka;
    long long int pesel;
    bool zapisz(string sciezka);
    bool wczytaj(string sciezka, unsigned offset);
    void wypisz()
    {
        cout<<imie<<"\n"<<nazwisko<<"\n"<<stanowisko<<"\n"<<stawka<<"\n"<<pesel<<endl;
    }
};

bool baza::zapisz(string sciezka)
{
    bool zwracana = true;
    ofstream plik;
    plik.open(sciezka, ios::out | ios::app);
    if(plik.good())
    {
        plik<<imie<<endl<<nazwisko<<endl<<stanowisko<<endl<<stawka<<endl<<pesel<<endl;
    }
    else
    {
        zwracana = false;
        cout<<"Nie udalo sie otworzyc pliku"<<endl;
    }
    plik.close();
    return zwracana;
}

bool baza::wczytaj(string sciezka, unsigned offset)
{
    bool zwracana = true;
    ifstream plik;
    plik.open(sciezka);
    if(plik.good())
    {
        unsigned licznik_linii = 0, licznik_danych = 0;
        string linia;
        while(getline(plik, linia))
        {
            ++licznik_linii;
            if(licznik_linii > (offset-1)*5)
            {
                ++licznik_danych;
            }

            if(licznik_danych == 1) imie = linia;
            else if(licznik_danych == 2) nazwisko = linia;
            else if(licznik_danych == 3) stanowisko = linia;
            else if(licznik_danych == 4) stawka = linia;
            else if(licznik_danych == 5) pesel = stoull(linia);
            else if(licznik_danych == 6) break;
        }
        if(licznik_danych < 5)
        {
            zwracana = false;
            cout<<"Osiagnieto koniec pliku"<<endl;
        }
    }
    else
    {
        zwracana = false;
        cout<<"Nie udalo sie otworzyc pliku"<<endl;
    }
    plik.close();
    return zwracana;
}

int main()
{
    vector <baza> db;

    baza tymczasowy;
    int licznik = 1;
    while(tymczasowy.wczytaj("db.txt", licznik))
    {
        db.push_back(tymczasowy);
        ++licznik;
    }

    for(auto & i: db)
    {
        i.wypisz();
        cout<<endl;
    }
    db.clear();
    return 0;
}

Zawartość pliku db.txt:

Adam
Kowalski
Kasjer
Podstawowa
12345678901
Ewa
Kaminska
Manager
Managerska
12345678903
Paweł
Sosnowski
Kierowca
Podstawowa
12345678941

Przeanalizuj, pobaw się, a jak masz pytania, to pytaj. ;)

komentarz 26 czerwca 2015 przez bather Nowicjusz (160 p.)
Dzięki! To co napisałeś to co prawda dość wysokie progi dla mnie, bo nie doszedłem jeszcze do obiektówki, ale... dzięki temu, że zagłębiłem ten temat (żeby choć troche zrozumieć kod), to dotarłem do jednego z ocinków kursu obiektowego C++ (oczywiście nieocenionego pana Zelenta). A w tym ocinku był przerabiany quiz i pokzane zostało rozwiązanie problemu dostania się do konkretnych linii :)

Wszystko zatem działa, problem można uznać za rozwiązany. Dzięki za pomoc!
komentarz 26 czerwca 2015 przez draghan VIP (106,230 p.)
Eeeej, nie ma tu nic strasznego. :) Może ostatnia pętla for wygląda trochę dziwnie i ten vector, ale to jest niegroźne...  Wręcz przeciwnie, jest bardzo pożyteczne i warto się z tym zaznajomić jak najwcześniej. :)

Powodzenia w dalszej nauce! :)

Podobne pytania

0 głosów
1 odpowiedź 130 wizyt
0 głosów
1 odpowiedź 169 wizyt
0 głosów
1 odpowiedź 281 wizyt
pytanie zadane 7 kwietnia 2023 w C i C++ przez Zuzan Początkujący (390 p.)

92,576 zapytań

141,426 odpowiedzi

319,652 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!

...