LISTA - Sortowanie tekstu i liczb

0

Witam. Mam problem z tym w jaki sposób mam posortować dane z pliku.
W pliku tekstowym znajdują się takie dane:

08:30-10:00 pt gr1 Kowalski Programowanie
10:15-11:45 wt gr2 Nowak Elektrotechnika
14:34-15:43 sr gr2 Kowalski Java
08:30-11:00 sr gr3 Kowalski PHP
08:30-10:00 cz gr1 Polak Filozofia
11:15-12:50 wt gr1 Polak WF
07:23-19:34 cz gr1 Nowak Astronomia
15:00-16:15 wt gr1 Kowalski BHP
09:00-10:30 wt gr2 Polak WF
08:30-11:00 sr gr3 Kowalski PHP
09:18-12:00 pt gr3 Nowak Fizyka

Muszę pobrać dane z pliku i stworzyć 3 pliki tekstowe o nazwach zgodnych z nazwiskami(czyli pliki: Polak, Kowalski, Nowak)​. W tych plikach mają znajdować się plany dla każdej osoby posortowany względem dni i godzin(np.
10:15-11:45 wt gr2 Nowak Fizyka
07:23-19:34 cz gr1 Nowak Astronomia
09:18-12:00 pt gr3 Nowak Fizyka
)
Pomyślałem, że dobrym pomysłem będzie posortować nazwiska i podzielić je na grupy w których będę sortować dni i godziny. Nie mam niestety pomysłu jak to zrobić. Próbowałem sortować te nazwiska ale nigdy mi się to nie udało.
PS: Nie wiem czemu ale lista wyświetla się na odwrót i powielony jest pierwszy wyświetlany wers.

#include <iostream>
#include <string>
#include <cstdlib>
#include <fstream>
#include <sstream>
using namespace std;
 
struct dane                  //struktura z danymi i wskaznikiem na nastepny element
{
    string godzina;
    string dzien;
    string grupa;
    string nazwisko;
    string przedmiot;
    dane *nast;
};
 
typedef dane* lista;
lista glowa = NULL;
lista wsk = NULL;
 
void prosta(lista &glowa, string godzina,string dzien, string grupa, string nazwisko, string przedmiot) // dodawanie nowego elementu do listy
{
    glowa = new dane;
    glowa->godzina = godzina;
    glowa->dzien = dzien;
    glowa->grupa = grupa;
    glowa->nazwisko = nazwisko;
    glowa->przedmiot = przedmiot;
 
    glowa->nast = wsk;
    wsk = glowa;
 
}
 
void drukuj(lista glowa)     //wyswietlenie listy
{
 
    lista kolejny;
    kolejny = glowa;
    while (kolejny != NULL)
    {
        cout << kolejny->godzina << " " << kolejny->dzien << " " << kolejny->grupa << " "
             << kolejny->nazwisko << " " << kolejny->przedmiot << endl;
        kolejny = kolejny->nast;
    }
    cout << "\n";
}
 
 
 
int main(int argc, char *argv[])
{
    fstream plik;
    plik.open("sciezka do pliku");
    if (plik.is_open())
    {
        string wers;
        string godzina, dzien, grupa, nazwisko, przedmiot;
        cout << "DOBRZE" << endl;
        int liczby;
        string a, b;
        while (!plik.eof())
        {
 
            getline(plik, wers);
            istringstream is(wers);   //dzielenie wersu  na czesci
            is >> godzina >> dzien >> grupa >> nazwisko >> przedmiot;
 
            prosta(glowa, godzina, dzien, grupa, nazwisko, przedmiot);  //dodanie pobranych danych z pliku do listy
 
 
            //---------------------------------------------------   ten fragment kodu nie jest na razie uzywany
            a = godzina[0]; //
            b = godzina[1]; //
            godzina = a + b; //   sparowanie dwoch pierwszych cyfr typu string w 
            liczby = atoi(godzina.c_str());  //  zamiana pierwszych dwoch cyfr typu string na int   
            //-----------------------------------------------------------
 
        }
    }
    else
    {
        cout << "ZLE" << endl;
    }
 
    drukuj(glowa);
} 
1
  1. Zacznij od pozbycia się zmiennych globalnych.
  2. Listę przerób na listę z dowiązaniami
  3. Zlicz ilość rekordów.
  4. Stwórz tablicę odpowiedniego rozmiaru i przypisz do niej dowiązania.
  5. Posortuj za pomocą sort (składany klucz nazwisko+data)
  6. Fragmentami z tablicy.
0

1.Zacznij od pozbycia się zmiennych globalnych.

Czy o to chodziło?

#include <iostream>
#include <string>
#include <cstdlib>
#include <fstream>
#include <sstream>
using namespace std;

struct dane                  //struktura z danymi i wskaznikiem na nastepny element
{
	string godzina;
	string dzien;
	string grupa;
	string nazwisko;
	string przedmiot;
	dane *nast;
};

typedef dane* lista;



void prosta(lista &glowa, string godzina, string dzien, string grupa, string nazwisko, string przedmiot) // dodawanie nowego elementu do listy
{
	lista glowa = NULL;
	lista wsk = NULL;
	glowa = new dane;
	glowa->godzina = godzina;
	glowa->dzien = dzien;
	glowa->grupa = grupa;
	glowa->nazwisko = nazwisko;
	glowa->przedmiot = przedmiot;

	glowa->nast = wsk;
	wsk = glowa;

}

void drukuj(lista glowa)     //wyswietlenie listy
{

	lista kolejny;
	kolejny = glowa;
	while (kolejny != NULL)
	{
		cout << kolejny->godzina << " " << kolejny->dzien << " " << kolejny->grupa << " "
			<< kolejny->nazwisko << " " << kolejny->przedmiot << endl;
		kolejny = kolejny->nast;
	}
	cout << "\n";
}



int main(int argc, char *argv[])
{
	fstream plik;
	plik.open("sciezka do pliku");
	if (plik.is_open())
	{
		string wers;
		string godzina, dzien, grupa, nazwisko, przedmiot;
		cout << "DOBRZE" << endl;
		int liczby;
		string a, b;
		while (!plik.eof())
		{

			getline(plik, wers);
			istringstream is(wers);   //dzielenie wersu  na czesci
			is >> godzina >> dzien >> grupa >> nazwisko >> przedmiot;

			prosta(glowa, godzina, dzien, grupa, nazwisko, przedmiot);  //dodanie pobranych danych z pliku do listy


																		//---------------------------------------------------   ten fragment kodu nie jest na razie uzywany
			a = godzina[0]; //
			b = godzina[1]; //
			godzina = a + b; //   sparowanie dwoch pierwszych cyfr typu string w 
			liczby = atoi(godzina.c_str());  //  zamiana pierwszych dwoch cyfr typu string na int   
											 //-----------------------------------------------------------

		}
	}
	else
	{
		cout << "ZLE" << endl;
	}

	drukuj(glowa);
} 
  1. Listę przerób na listę z dowiązaniami
    Jak wygląda taka lista? Czy to jest może lista z wartownikiem?

3.Zlicz ilość rekordów.
Czyli?

PS: Chciałbym dodać, że ilość danych w pliku jest przykładowa(czyli zamiast 10 wersów z danymi może być 20)

0
  1. Zmiennych globalnych niepoprawnie się pozbyłeś
struct data { time_t dt; string grupa,nazwisko,przedmiot; };
struct node { data *rec; node *next; };
struct list { node *head; };
  1. Dodałeś zwiększ licznik. Lub po dodaniu całości przeiteruj jak przy wyświetleniu tylko zliczaj zamiast wyświetlać.
0
_13th_Dragon napisał(a):
  1. Zmiennych globalnych niepoprawnie się pozbyłeś
struct data { time_t dt; string grupa,nazwisko,przedmiot; };
struct node { data *rec; node *next; };
struct list { node *head; };
  1. Dodałeś zwiększ licznik. Lub po dodaniu całości przeiteruj jak przy wyświetleniu tylko zliczaj zamiast wyświetlać.

1.W jaki sposób dobrze to zrobić?
2.Czy zamiast data nie powinno być dane?

struct dane { time_t dt; string grupa, nazwisko, przedmiot; };
struct node { dane *rec; node *next; };
struct list { node *head; };


void dodaj(node &glowa, time_t dt, string grupa, string nazwisko,string przedmiot) // dodawanie nowego elementu do listy
{
	node glowa = NULL;
	node wsk = NULL;

	glowa = new dane;
	glowa->godzina = godzina;
	glowa->dzien = dzien;
	glowa->grupa = grupa;
	glowa->nazwisko = nazwisko;
	glowa->przedmiot = przedmiot;

	glowa->nast = wsk;
	wsk = glowa;

} 

Część kodu zmieniłem gdyż nie wiem jak mam zmienić void dodaj(dawniej void prosta). Mógłbyś wyjaśnić mi wstawione przez ciebie struktury?
PS: Rozumiem że void dodaj będzie mieć teraz cztery pola(time_t dt; string grupa, nazwisko, przedmiot) i time_t dt to jest godzina+dzień i właśnie to pole będzie potem sortowane?

1

Ad 1. Nie rozumiem pytania.
Ad 2. Odradzam polskiego nazewnictwa, bo twój kod wygląda tak: http://4programmers.net/Forum/1208091

Zacznij może od dobrych praktyk, dziel wszystko na małe funkcje:

struct data { time_t dt; string group,name,subject; };
struct node { data *rec; node *next; };
struct list { node *head; };
 
data *makeData(time_t dt,string group,string name,string subject) // zamiast tego musi być konstruktor, bo to co robisz to nie C++ tylko C z cin/cout i new/delete
  {
   data *tmp=new data;
   tmp->dt=dt;
   tmp->group=group;
   tmp->name=name;
   tmp->subject=subject;
   return tmp;
  }

node *makeNode(data *rec,node *next) // zamiast tego musi być konstruktor, bo to co robisz to nie C++ tylko C z cin/cout i new/delete
  {
   node *tmp;
   tmp->rec=rec;
   tmp->next=next;
   return tmp;
  }

void append(list *lst,data *rec) // zamiast tego musi być metoda, bo to co robisz to nie C++ tylko C z cin/cout i new/delete
  {
   lst->head=makeNode(rec,lst->head);
  }

Tak to powinno (mniej-więcej) wyglądać w C++:

struct data 
  {
   time_t dt; 
   string group,name,subject; 
   data(time_t dt,string group,string name,string subject):dt(dt),group(group),name(name),subject(subject) {}
  };
class list
  {
   public:
   struct node
     {
      data *rec; 
      node *next; 
      node(data *rec,node *next):rec(rec),next(next) {}
     };
   private:
   node *head;
   public:
   list():head(0) {}
   void append(data *rec) { head=new node(rec,head); }
  };
0

Gdy wpisałem ten kod

struct data { time_t dt; string group,name,subject; };
struct node { data *rec; node *next; };
struct list { node *head; };
 
data *makeData(time_t dt,string group,string name,string subject) // zamiast tego musi być konstruktor, bo to co robisz to nie C++ tylko C z cin/cout i new/delete
  {
   data *tmp=new data;
   data->dt=dt;
   data->group=group;
   data->name=name;
   data->subject=subject;
   return tmp;
  }
 
node *makeNode(data *rec,node *next) // zamiast tego musi być konstruktor, bo to co robisz to nie C++ tylko C z cin/cout i new/delete
  {
   node *tmp;
   tmp->rec=rec;
   tmp->next=next;
   return tmp;
  }
 
void append(list *lst,data *rec) // zamiast tego musi być metoda, bo to co robisz to nie C++ tylko C z cin/cout i new/delete
  {
   lst->head=makeNode(rec,lst->head);
  } 

To w linijce
struct node { data *rec; node *next; };
pojawił się komunikat: "data" is ambiguous
Zmieniłem więc data na base i wtedy pojawił się taki komunikat: expected an identifier

struct base { time_t dt; string group, name, subject; };
struct node { base *rec; node *next; };
struct list { node *head; };

base *makeBase(time_t dt, string group, string name, string subject) // zamiast tego musi być konstruktor, bo to co robisz to nie C++ tylko C z cin/cout i new/delete
{
	base *tmp = new base;
	base->dt = dt;
	base->group = group;
	base->name = name;
	base->subject = subject;
	return tmp;
}

node *makeNode(base *rec, node *next) // zamiast tego musi być konstruktor, bo to co robisz to nie C++ tylko C z cin/cout i new/delete
{
	node *tmp;
	tmp->rec = rec;
	tmp->next = next;
	return tmp;
}

void append(list *lst, base *rec) // zamiast tego musi być metoda, bo to co robisz to nie C++ tylko C z cin/cout i new/delete
{
	lst->head = makeNode(rec, lst->head);
} 

Mam prośbę. Czy mógłbyś wyjaśnić mi linijki kodu który zamieściłeś a który ja przytoczyłem. Chciałbym to zrozumieć a nauka list cienko mi idzie.

PS: Na razie zostanę przy tym C z cin/cout i new/delete, ale dzięki za uwagę. Nie wiedziałem, że to nie c++.

0

Z datą poprawione.
tmp->rec = rec; przypisuje wskaźnik, z parametru do struktury.

0
_13th_Dragon napisał(a):

Z datą poprawione.
tmp->rec = rec; przypisuje wskaźnik, z parametru do struktury.

Gdzie umieściłeś ten poprawiony kod?
Czy byłoby przesadą poproszenie cię o wyjaśnienie całego wstawionego kodu w możliwie jak najprostszy sposób?
Jak już wspomniałem nauka list idzie mi słabo a bardzo chciałbym je zrozumieć.

0
xpack napisał(a):

Czy byłoby przesadą poproszenie cię o wyjaśnienie całego wstawionego kodu w możliwie jak najprostszy sposób?
Weź przeczytaj byle kurs będziesz już 99% wiedział, zaś ten jeden procent to zadasz konkretne pytanie.

0
_13th_Dragon napisał(a):

Weź przeczytaj byle kurs będziesz już 99% wiedział, zaś ten jeden procent to zadasz konkretne pytanie.

Trochę tych kursów przeczytałem o listach..ale wezmę się za nie jeszcze raz.
A ten poprawiony kod gdzie znajdę?

0
xpack napisał(a):

Trochę tych kursów przeczytałem o listach..ale wezmę się za nie jeszcze raz.
Nie czytaj o listach, czytaj o języku.

xpack napisał(a):

A ten poprawiony kod gdzie znajdę?
Już raz odpowiedziałem na to pytanie, jeżeli własnie tak czytasz kursy to się nie dziwię.

0

Napisałeś "Z datą poprawione". Pomyślałem więc, że zmodyfikowałeś swój poprzedni post, lecz gdy go umieszczam w visualu błąd jest ciągle ten sam.
Mam nie czytać o listach w c++ tylko o języku c++. Nigdy tak nie robiłem. Wybierałem zagadnienie, które mnie interesowało i o nim czytałem(np. o plikach z tej strony http://cpp0x.pl/kursy/Kurs-C++/Obsluga-plikow/305). Jak już pisałem jestem zielony w te klocki i dziękuję za każdą radę, lecz zdanie " Nie czytaj o listach, czytaj o języku " nic mi nie mówi.

0
xpack napisał(a):

... lecz gdy go umieszczam w visualu błąd jest ciągle ten sam.
Więc albo nie umiesz umieścić albo gdzieś masz inną deklaracje data: http://ideone.com/k8off5

xpack napisał(a):

... Wybierałem zagadnienie, które mnie interesowało i o nim czytałem ...
Właśnie dla tego wciąż masz problemy bardzo początkującego. Weź przeczytaj pierwsze kilka rozdziałów po kolei.

0

Chyba masz racje. Zacznę od funkcji, potem struktury,wskaźniki i listy. Chyba tak będzie dobrze. Jeśli się mylę to mnie popraw.

0

OK. A możesz mi polecić jakieś strony czy książki. Tego jest masa a myślę, że twoje doświadczenia z różnego rodzaju materiałami pozwoliły ci na wybranie źródeł lepszych niż inne. Byłbym wdzięczny za radę.

0

Na początek wystarczy byle jaki - wybierz najkrótszy.
Po czym ta twoja stara strategia stanie się lepsza.

0

Czyli zrobić krótki kurs, potem wybrać jakiś większy i tak dalej, by stopniowo dowiadywać się nowych rzeczy. OK. Myślałem też o przerobieniu symfonii c++ . Myślisz, że to dobry pomysł?

0

Nie, po krótkim, jak już łykniesz podstawy podstaw, to możesz czytasz tylko konkretne tematy które akurat potrzebne do kolejnego kroku aktualnego projektu.

0

Ok. Wielkie dzięki za rady.

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