Lista dynamiczna jednokierunkowa

0

Siemka. Mam zadanko żeby wczytać z pliku 3 dane do listy dynamicznej 1 kierunkowej. I Następnym krokiem zadania jest : "Po odczytaniu odwróć porządek elementów w liście dynamicznej, tak aby zaczynała się od ostatniego wczytanego elementu, a kończyła na pierwszym." Nie mam zielonego pomysłu jak to odwrócić. Byłbym wdzięczny za jakiekolwiek wskazówki.

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<malloc.h>
#include<ctype.h>
#define N 5


struct student 
{
	int indeks;
	char nazwisko[30];
	float ocena;
	struct student *nast;
};

int main()
{
	char f[20];								 //nazwy pllikow
	//char wynik[20];
	printf("Prosze podac nazwe pliku z danyymi(nazwa+rozszerzenie) :");
	scanf("%s", f);
	/*printf("Prosze podac nazwe pliku wynikowego(nazwa+rozszerzenie) :");
	scanf("%s", wynik);*/

	struct student *wsk, *glowa = NULL;
	int indeks;
	char nazwisko[30];
	float ocena;

	//plik z danymi otwieranie
	FILE* stream;
	if ((stream = fopen(f, "r")) == NULL)
	{
		printf("Pliku z danymi nie udalo sie otworzyc.\n");
		return 0;
	}
	else
		printf("Plik z danymi udalo sie otworzyc.\n");



	//plik wynikowy otwieranie
	//FILE* stream1;
	//if ((stream1 = fopen(wynik, "w")) == NULL)
	//{
	//	printf("Pliku z wynikami nie udalo sie otworzyc.\n");
	//	return 0;
	//}
	//else
	//	printf("Plik z wynikami udalo sie otworzyc.\n");
	////////////////////////////////////////////////////////////////////////////////
	putchar('\n\n');

	fscanf(stream, "%d %s %f", &indeks, nazwisko, &ocena);
	while (!feof(stream)) {
		if (glowa == NULL)
			glowa = wsk = malloc(sizeof(struct student));
		else {
			wsk->nast = malloc(sizeof(struct student));
			wsk = wsk->nast;
		}
		wsk->indeks = indeks;
		strcpy(wsk->nazwisko, nazwisko);
		wsk->ocena = ocena;
		wsk->nast = NULL;
		fscanf(stream, "%d %s %f", &indeks, nazwisko, &ocena);
	}



	putchar('\n\n');
	/////////////////////////////////////////////////////////////////////////////////
		if (fclose(stream))			//zamykanie pliku z danymi
			printf("Plik z danymi nie zostal zamkniety.\n");
		else
			printf("Plik z danymi zostal zamkniety.\n");

		//if (fclose(stream1))			//zamykanie pliku z wynikami
		//	printf("Plik z wynikami nie zostal zamkniety.\n");
		//else
		//	printf("Plik z wynikami zostal zamkniety.\n");


	printf("\nAutor: Bartosz Rozanski.\n");
	return 0;
}


0

Bierzesz kartkę, rysujesz sobie kółeczka i strzałki reprezentujące listę.
Sprawdź co się stanie jak weźmiesz głowę listy i potraktuje jako głowę drugiej listy, a głowa pierwszej listy uczynisz drugi element, ten za głową, która właśnie wziąłeś. Co się stanie jak powtórzysz to kilka raz? Co zrobić z nową głową?

0

Ja bym spróbował zamknąć dodawanie elementu do listy w funkcji(to spowoduje, że będzie czytelniej) i zrobić jakąś iteracje po liście; wtedy nie powinno być problemów z odwróceniem.

1

Tak na prawdę kolejność listy opiera się na tym polu: struct student *nast;

    wsk->nast = glowa->nast;
    wsk->nast->nast = glowa;
    glowa->nast = 0;

Tylko teraz masz listę odwróconą, tzn głowa jest ogonem.
Wystarczy teraz sobie zamienbić wsk z glowa i po sprawie:

    struct student *temp = wsk;
    wsk = glowa;
    glowa = temp;
0

Nie wiem czy dobrze zrozumiałem bl4ster, ale ty mi podałeś kod na 3 wiersze w pliku? Jeżeli tak jak zmienić ten porządek kiedy nie wiemy ile jest wierszy w pliku?

1
karwan33 napisał(a):

Nie wiem czy dobrze zrozumiałem bl4ster, ale ty mi podałeś kod na 3 wiersze w pliku? Jeżeli tak jak zmienić ten porządek kiedy nie wiemy ile jest wierszy w pliku?

Nie, źle go zrozmumiałeś. Masz odwrócić listę, którą stworzyłeś. Kod do odwracana listy może wyglądać np. tak:

void reverse(struct node **head_link) {
    struct node *reversed = NULL;

    if (head_link == NULL) {
        return;
    }

    for (struct node *curr = *head_link; curr != NULL; curr = *head_link) {
        *head_link = curr->next;    // pop element from original list

        curr->next = reversed;      // push element to front of reversed list
        reversed = curr;            //
    }

    *head_link = reversed;          // add reversed list to original
}
0

Uzupełniłem kod w to co mi pomogliście ale nie mogę poradzić sobie z tym, że zapisuje mi do pliku wiersze -1 ( np mam w pliku z danymi 4 wiersze to zapisze 3 itd). Myślę że odwrócenie jest w porządku, tylko z tym zapisaniem jest problem.Tutaj kod :

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<malloc.h>
#include<ctype.h>
#define N 5


struct student 
{
	int indeks;
	char nazwisko[30];
	float ocena;
	struct student *nast;
};

int main()
{
	char f[20];								 //nazwy pllikow
	char wynik[20];

	struct student *wsk=NULL, *glowa = NULL;
	int indeks;
	char nazwisko[30];
	float ocena;

	printf("Prosze podac nazwe pliku z danymi(nazwa+rozszerzenie) :");
	scanf("%s", f);
	//plik z danymi otwieranie
	FILE* stream;
	if ((stream = fopen(f, "r")) == NULL)
	{
		printf("Pliku z danymi nie udalo sie otworzyc.\n");
		return 0;
	}
	else
		printf("Plik z danymi udalo sie otworzyc.\n");


	////////////////////////////////////////////////////////////////////////////////
	putchar('\n');
	//wczytywanie do listy dynamicznej
	fscanf(stream, "%d %s %f", &indeks, nazwisko, &ocena);
	printf("\nIndeks: %d Nazwisko: %s Ocena: %.1f", indeks, nazwisko, ocena);
	while (!feof(stream)) {
		if (glowa == NULL)
			glowa = wsk = malloc(sizeof(struct student));
		else {
			wsk->nast = malloc(sizeof(struct student));
			wsk = wsk->nast;
		}
		wsk->indeks = indeks;
		strcpy(wsk->nazwisko, nazwisko);
		wsk->ocena = ocena;
		wsk->nast = NULL;
		fscanf(stream, "%d %s %f", &indeks, nazwisko, &ocena);
		printf("\nIndeks: %d Nazwisko: %s Ocena: %.1f", indeks, nazwisko, ocena);
	}


	putchar('\n');
	putchar('\n');
	//odwrocenie listy

	wsk->nast = glowa->nast;
	wsk->nast->nast = glowa;
	glowa->nast = NULL;
	struct student *temp = wsk;
	wsk = glowa;
	glowa = temp;
	//////////////////////////////////////////////////////////////

	printf("Prosze podac nazwe pliku wynikowego(nazwa+rozszerzenie) :");
	scanf("%s", wynik);

	//plik wynikowy otwieranie
	FILE* stream1;
	if ((stream1 = fopen(wynik, "w")) == NULL)
	{
		printf("Pliku z wynikami nie udalo sie otworzyc.\n");
		return 0;
	}
	else
		printf("Plik z wynikami udalo sie otworzyc.\n");


	//zapisywanie listy do pliku 
	if (glowa == NULL)
		printf("Nie ma elementow do zapisania");
	else
	{
			while (temp != NULL)
			{
				fprintf(stream1, "%d ", temp->indeks);
				fprintf(stream1, "%s ", temp->nazwisko);
				fprintf(stream1, "%.0f\n", temp->ocena);
				temp = temp->nast;
			}
			printf("\nLista zostala zapisana\n\n");
	}


	////////////////////////////////////////////////////////////////////////////////
		if (fclose(stream))			//zamykanie pliku z danymi
			printf("Plik z danymi nie zostal zamkniety.\n");
		else
			printf("Plik z danymi zostal zamkniety.\n");

		if (fclose(stream1))			//zamykanie pliku z wynikami
			printf("Plik z wynikami nie zostal zamkniety.\n");
		else
			printf("Plik z wynikami zostal zamkniety.\n");


	printf("\nAutor: Bartosz Rozanski.\n");
	return 0;
}

0

Narysuj sobie taką listę na kartce papieru (z uwzględnieniem wskaźników), to zrozumiesz, dlaczego taka prosta podmiana elementów nie działa w tym przypadku.

0

Dla 4 wierszy ta zamiana listy nie zadziała(ona jest dla 3 elementów), musiałbyś skorzystać z funkcji, którą podał @nalik
Zauważyłem, że przypisanie wartości do temp niby jest poprawne, ale jest niejako pozostałością po odwróceniu listy (przez to kod jest nieczytelny). Po linijce //zapisywanie listy do pliku dopisz sobie:

temp = glowa;

i teraz zamiast if (glowa == NULL) zamień na if (temp== NULL)
Podziel sobie kod na funkcje będzie łatwiej się czytało.

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