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

Wyszukiwanie po nazwiskach w listach jednokierunkowych i usuwanie po nim osób

Object Storage Arubacloud
0 głosów
601 wizyt
pytanie zadane 25 maja 2020 w C i C++ przez kamylmeister Nowicjusz (190 p.)
#include <iostream>
#include <string>
#include <cstdlib>
#include <windows.h>

using namespace std;

struct osoba {
	string imie;
	string nazwisko;
	int wiek;
	osoba* nastepna; // wskaźnik na następny element
	osoba(); // konstruktor
};

osoba::osoba() {
	nastepna = 0; // konstruktor
}

struct lista {
	osoba* pierwsza; // wskaźnik na początek listy
	void dodaj_osobe(string imie, string nazwisko, int wiek);
	void usun_osobe(int nr);
	void wyswietl_liste();
	void usun_osobe_nazwisko(string nazwisko);
	void znajdz_osobe_nazwisko(string nazwisko);
	lista();
};

lista::lista() {
	pierwsza = 0; // konstruktor
}

void lista::wyswietl_liste()
{
	// wskaznik na pierszy element listy
	osoba* temp = pierwsza;

	// przewijamy wskazniki na nastepne elementy
	while (temp)
	{
		cout << "imie: " << temp->imie << ", nazwisko: " << temp->nazwisko << ", wiek: " << temp->wiek << endl;
		temp = temp->nastepna;
	}
}

void lista::usun_osobe(int nr)
{
	// jezeli to pierwszy element listy
	if (nr == 1)
	{
		osoba* temp = pierwsza;
		pierwsza = temp->nastepna; //ustawiamy poczatek na drugi element
		delete temp; // usuwamy stary pierwszy element z pamieci
	}

	// jeżeli nie jest to pierwszy element
	else if (nr >= 2)
	{
		int j = 1;

		// do usuniecia srodkowego elemetnu potrzebujemy wskaznika na osobe n-1
		// wskaznik *temp bedzie wskaznikiem na osobe poprzedzajaca osobe usuwana
		osoba* temp = pierwsza;

		while (temp)
		{
			// sprawdzamy czy wskaznik jest na osobie n-1 niz usuwana
			if ((j + 1) == nr) break;

			// jezeli nie to przewijamy petle do przodu
			temp = temp->nastepna;
			j++;
		}

		// wskaznik *temp wskazuje teraz na osobe n-1
		// nadpisujemy wkaznik n-1 z osoby n na osobe n+1
		// bezpowrotnie tracimy osobe n-ta

		// jezeli usuwamy ostatni element listy
		if (temp->nastepna->nastepna == 0) {
			delete temp->nastepna;
			temp->nastepna = 0;
		}
		// jezeli usuwamy srodkowy element
		else {
			osoba* usuwana = temp->nastepna;
			temp->nastepna = temp->nastepna->nastepna;
			delete usuwana;
		}
	}
}

void lista::dodaj_osobe(string imie, string nazwisko, int wiek)
{
	osoba* nowa = new osoba; // tworzy nowy element listy

	// wypełniamy naszymi danymi
	nowa->imie = imie;
	nowa->nazwisko = nazwisko;
	nowa->wiek = wiek;

	if (pierwsza == 0) // sprawdzamy czy to pierwszy element listy
	{
		// jeżeli tak to nowy element jest teraz początkiem listy
		pierwsza = nowa;
	}
	else
	{
		// w przeciwnym wypadku wędrujemy na koniec listy
		osoba* temp = pierwsza;

		while (temp->nastepna)
		{
			// znajdujemy wskaźnik na ostatni element
			temp = temp->nastepna;
		}

		temp->nastepna = nowa; // ostatni element wskazuje na nasz nowy
	}
}

void lista::znajdz_osobe_nazwisko(string nazwisko)
{
	
}

void lista::usun_osobe_nazwisko(string nazwisko)
{
	
}

int main()
{
	lista* baza = new lista; // tworzymy liste

	int wybor;

	string n_imie, n_nazwisko;
	int n_wiek;

	int do_usuniecia;

	string nazwisko_usuwane;

	string nazwisko_szukane;

	do
	{
		cout << "Co chcesz zrobic?" << endl;
		cout << "1. Dodac osobe" << endl;
		cout << "2. Usunac osobe po numerze" << endl;
		cout << "3. Usunac osobe po nazwisku" << endl;
		cout << "4. Wypisac wszystkich" << endl;
		cout << "5. Wyszukac osobe po nazwisku" << endl;
		cout << "6. Zakonczyc program" << endl;

		cin >> wybor;

		switch (wybor)
		{
		case 1:
			cout << "Podaj imie osoby: ";
			cin >> n_imie;
			cout << "Podaj nazwisko osoby: ";
			cin >> n_nazwisko;
			cout << "Podaj wiek osoby: ";
			cin >> n_wiek;
			baza->dodaj_osobe(n_imie, n_nazwisko, n_wiek);
			break;
		case 2:
			cout << "Podaj numer osoby: ";
			cin >> do_usuniecia;
			baza->usun_osobe(do_usuniecia);
			break;
		case 3:
			cout << "Podaj nazwisko: ";
			cin >> nazwisko_usuwane;
			baza->usun_osobe_nazwisko(nazwisko_usuwane);
			break;
		case 4:
			baza->wyswietl_liste();
			Sleep(5000);
			break;
		case 5:
			cout << "Podaj nazwisko do odszukania: ";
			cin >> nazwisko_szukane;
			baza->znajdz_osobe_nazwisko(nazwisko_szukane);
			break;
		case 6:
			exit;
		}

		system("CLS");

	} while (wybor != 6);

	return 0;
}

Umiałby ktos wytłumaczyc mi jak zrobic w liscie jednokierunkowej w c++ wyszukiwanie i usuwanie uzytkownikow po nazwisku? W wyszukiwaniu myslalem nad zwyklą pętlą for, gdzie iterator operowałby na strukturach w liscie i sprawdzał, czy nazwisko osoby jest takie, jak podane przez użytkownika, tylko nie wiem, jak to napisać.

komentarz 25 maja 2020 przez Piotr Batko Stary wyjadacz (13,190 p.)
Pomysł masz bardzo dobry. Czego nie wiesz jak napisać? Zwykłą pętlę for? Czy może sprawdzenie czy nazwisko jest takie samo? Najlepiej jakbyś wrzucił jakiś kodzik, jak zacząłeś pisać i nie wiesz co dalej, albo coś się nie kompiluje.
komentarz 25 maja 2020 przez kamylmeister Nowicjusz (190 p.)
Szczerze mówiąc nie jestem pewny, ponieważ gdy zaczynam pisać kod to chcę pobrać wielkosc listy lista.size(), ale wyskakuje mi error, więc nawet nie wiem jak zacząć.
komentarz 25 maja 2020 przez Piotr Batko Stary wyjadacz (13,190 p.)
Nie potrzebujesz rozmiaru listy, żeby po niej iterować. Przecież jak pisałeś wyświetlanie listy, to iterowałeś po wszystkich elementach i nie korzystałeś z jej rozmiaru. Już zapomniałeś? :)
komentarz 26 maja 2020 przez kamylmeister Nowicjusz (190 p.)
Myslalem, ze to bedzie cos trudniejszego, a praktycznie wystarczylo dodac jednego ifa :) Tylko teraz mam problem z usuwaniem przez nazwisko, myslalem nad "połączeniem" wyszukiwania przez nazwisko z usuwaniem przez numer, tylko nie wiem za bardzo od której strony się za to zabrać :/ Jakas porada?
komentarz 26 maja 2020 przez Piotr Batko Stary wyjadacz (13,190 p.)

Najprostsza metoda jak już masz funkcje znajdz_goscia i usun_goscia_o_numerze to:

int numer_goscia_do_usuniecia = znajdz_goscia("Nowak");
usun_goscia_o_numerze(numer_goscia_do_usuniecia);

Ale nieoptymalna, bo wymaga dwukrotnego przebiegania po liście (osobnego dla każdej z tych funkcji). Może to nie jest dla Ciebie problemem, dlatego to zaproponowałem.

Najlepszym sposobem jest jednak ponownie ten, który zaproponowałeś. Masz dobrą intuicję :) Zamiast szukać gościa po numerze:
if (i == numer_goscia_do_usuniecia),
szukaj po nazwisku:
if (wskazywany_gosciu->nazwisko == nazwisko_goscia_do_usuniecia).

komentarz 27 maja 2020 przez kamylmeister Nowicjusz (190 p.)

chciałbym to dobrze nazpisac, ale po prostu mi nie wychodzi, nawet nie wiem, co mam źle :/

void lista::usun_osobe_nazwisko(string nazwisko)
{
	osoba* temp = pierwsza;

	while (temp)
	{
		if (temp->nastepna->nazwisko == nazwisko)
		{
			osoba* usuwana = temp->nastepna;
			temp->nastepna = temp->nastepna->nastepna;
			delete usuwana;
		}
		temp = temp->nastepna;
	}
}

 

komentarz 27 maja 2020 przez kamylmeister Nowicjusz (190 p.)
void lista::usun_osobe(int nr)
{
	// jezeli to pierwszy element listy
	if (nr == 1)
	{
		osoba* temp = pierwsza;
		pierwsza = temp->nastepna; //ustawiamy poczatek na drugi element
		delete temp; // usuwamy stary pierwszy element z pamieci
	}

	// jeżeli nie jest to pierwszy element
	else if (nr >= 2)
	{
		int j = 1;

		// do usuniecia srodkowego elemetnu potrzebujemy wskaznika na osobe n-1
		// wskaznik *temp bedzie wskaznikiem na osobe poprzedzajaca osobe usuwana
		osoba* temp = pierwsza;

		while (temp)
		{
			// sprawdzamy czy wskaznik jest na osobie n-1 niz usuwana
			if ((j + 1) == nr) break;

			// jezeli nie to przewijamy petle do przodu
			temp = temp->nastepna;
			j++;
		}

		// wskaznik *temp wskazuje teraz na osobe n-1
		// nadpisujemy wkaznik n-1 z osoby n na osobe n+1
		// bezpowrotnie tracimy osobe n-ta

		// jezeli usuwamy ostatni element listy
		if (temp->nastepna->nastepna == 0) {
			delete temp->nastepna;
			temp->nastepna = 0;
		}
		// jezeli usuwamy srodkowy element
		else {
			osoba* usuwana = temp->nastepna;
			temp->nastepna = temp->nastepna->nastepna;
			delete usuwana;
		}
	}
}

void lista::znajdz_osobe_nazwisko(string nazwisko)
{
	// wskaznik na pierszy element listy
	osoba* temp = pierwsza;

	// przewijamy wskazniki na nastepne elementy, wyswietlajac tylko osoby z danym nazwiskiem
	while (temp)
	{
		if (nazwisko == temp->nazwisko)
		{
			cout << "imie: " << temp->imie << ", nazwisko: " << temp->nazwisko << ", wiek: " << temp->wiek << endl;			
		}
		temp = temp->nastepna;
	}
	Sleep(5000);

Ogólnie tak wygląda mój kod do usuwania przez numer i wyszukiwania przez nazwisko, ale totalnie nie wiem jak użyć tego, co napisałes. Mógłbys bardziej wyjasnić? Jest ewentualnie jakas inna opcja?

komentarz 27 maja 2020 przez Piotr Batko Stary wyjadacz (13,190 p.)

Ten kodzik który napisałeś jest całkiem niezły. On poprawnie kasuje osoby: pierwszą, drugą itd. ale nie potrafi usunąć zerowej. Zwróć uwagę, że w linii 7. sprawdzasz, czy nazwisko następnej osoby jest takie jak szukasz. A zerową osobę pomijasz. Dodaj osobnego ifa na ten szczególny przypadek, gdzie trzeba skasować zerową osobę i będzie hulać ;) (Możesz się wzorować na kodzie z:
void lista::usun_osobe(int nr).
Tam też przecież inaczej obsługujesz ten zerowy element, a inaczej pozostałe.

Tak w ogóle, może powinienem od tego w ogóle zacząć, polecam zadania z listami sobie rozrysowywać. Ja sobie nie wyobrażam pisania list bez rysunków. Przyznam się, że żeby sprawdzić czy dobrze napisał to usuwanie przesłane wyżej, narysowałem sobie listę i wykonywałem na niej napisany przez Ciebie kod. No i się poprawnie skasowało :)

Zaloguj lub zarejestruj się, aby odpowiedzieć na to pytanie.

Podobne pytania

0 głosów
1 odpowiedź 115 wizyt
pytanie zadane 29 lutego 2020 w Python przez Marak123 Stary wyjadacz (11,190 p.)
0 głosów
1 odpowiedź 415 wizyt
pytanie zadane 24 kwietnia 2019 w C# przez Vorczu Początkujący (390 p.)
0 głosów
1 odpowiedź 267 wizyt
pytanie zadane 31 października 2021 w C i C++ przez letmestay Użytkownik (520 p.)

92,576 zapytań

141,426 odpowiedzi

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

...