Błąd w odczycie pliku książki telefonicznej

0

Jestem świeżakiem który ma do zrobienia program wczytujący dane z pliku i później dodawać kontakty usuwać wyświetlać etc. Problem w tym że jak wczytuje plik to bez pierwszego kontaktu, ostatni wczytuje i w kolejnej linii

obraz_2023-01-21_122836791.png

Plik prosta_lista.csv wypluwa jakieś dziwne znaki

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>

struct kontakt
{
	char* imie;
	char* nazwisko;
	char* numer;
	char* grupa;
};

struct element
{
	struct kontakt* dane;
	struct element* nastepny;
	struct element* poprzedni;
};

struct kontakt* stworzKontakt(char* imie, char* nazwisko, char* numer, char* grupa)
{
	struct kontakt* k = malloc(sizeof(struct kontakt));
	k->imie = imie; //microsoft learn kazal uzyc malloc.h ale nei dziala
	k->nazwisko = nazwisko;
	k->numer = numer;
	k->grupa = grupa;
	return k;
}

struct kontakt* odczyt(struct element* gora)
{
	FILE* plik = fopen("prosta_lista.csv", "r");
	if (plik != NULL)
	{
		char tab[100];
		while (fgets(tab, 100, plik) != NULL)
		{
			char* imie = malloc(sizeof(char) * 20);
			char* nazwisko = malloc(sizeof(char) * 20);
			char* numer = malloc(sizeof(char) * 20);
			char* grupa = malloc(sizeof(char) * 20);
			fscanf(plik, " %[^;] ; %[^;] ; %[^;] ; %s", imie, nazwisko, numer, grupa);
			struct kontakt* k = stworzKontakt(imie, nazwisko, numer, grupa);

			printf("%s ", imie);
			printf("%s ", nazwisko);
			printf("%s ", numer);
			printf("%s\n\n", grupa);

		}
		fclose(plik);
	}
	else
	{
		printf("Blad");
	};
}

void menu(int* m)
{
	printf("\nMenu:\n");
	printf("\n1. Dodawanie\n");
	printf("\n2. Odczytywanie od konca\n");
	printf("\n3. Czyszczenie danych\n");
	printf("\n4. Koniec\n");
	printf("\nWybierz od 1 do 4\n");
	while (1)
	{
		if (!scanf("%d", m))
		{
			while ('\n' != getchar());
			printf("\nNie ma takiego punktu: \n");
			printf("\nPrzenies sie do: \n");
		}
		else return;
	}
}

void dodaj(struct element** gora, int liczba)
{
	struct element* nowy = malloc(sizeof(struct element));
	nowy->dane = liczba;
	nowy->poprzedni = *gora;
	nowy->nastepny = NULL;
	if (*gora != NULL)

		(*gora)->nastepny = nowy;
	*gora = nowy;
};

void wyswietlListe(struct element* gora)
{
	
	
	int wybor = 0;
	struct element* nowy = gora;
	while (nowy != NULL)
	{
		printf("%d\n", nowy->dane);
		nowy = nowy->poprzedni;
	}
}

void wyszczyscStos(struct element** gora)
{
	while (*gora != NULL)
	{
		struct element* nowy = (*gora)->poprzedni;
		free(*gora);
		*gora = nowy;
	}
}
struct element* dodajPusty(struct kontakt* Kontakt)
{
	struct element* temp = malloc(sizeof(struct element));
	temp->poprzedni = NULL;
	temp->dane = stworzKontakt(Kontakt->imie, Kontakt->nazwisko, Kontakt->numer, Kontakt->grupa);
	temp->nastepny = NULL;
	return temp;
}

void main()
{
	struct kontakt* k = stworzKontakt("Imie", "Nazwisko", "Numer", "Grupa");

	//ODCZYT DANYCH Z PLIKU
	struct element* Gora = dodajPusty(k);
	Gora = odczyt(Gora);

	//struct element* gora = NULL;
	int m = 0, dane = 0;
	do
	{
		menu(&m);
		switch (m)
		{
    		case 1:
    			printf("\n \n");
    			break;
    		case 2:
    			printf("\nODCZYT DANYCH OD KONCA\n");
    			//wyswietlStos(gora);
    			break;
    		case 3:
    			//wyszczyscStos(&gora);
    			break;
    		case 4:
    			//wyszczyscStos(&gora);
    			return 0;
    		default:
    			break;
    		}
    	} while (m != 4);
    	return 0;
    }
}
1
vitt3 napisał(a):

struct kontakt* odczyt(struct element* gora)>
{
FILE* plik = fopen("prosta_lista.csv", "r");
if (plik != NULL)
{
char tab[100];
while (fgets(tab, 100, plik) != NULL)
{
char* imie = malloc(sizeof(char) * 20);
char* nazwisko = malloc(sizeof(char) * 20);
char* numer = malloc(sizeof(char) * 20);
char* grupa = malloc(sizeof(char) * 20);
fscanf(plik, " %[^;] ; %[^;] ; %[^;] ; %s", imie, nazwisko, numer, grupa);
struct kontakt* k = stworzKontakt(imie, nazwisko, numer, grupa);

  	printf("%s ", imie);
  	printf("%s ", nazwisko);
  	printf("%s ", numer);
  	printf("%s\n\n", grupa);

  }
  fclose(plik);

}
else
{
printf("Blad");
};
}

Z marginalnych, to nie musisz mnożyć przez siezef(char), miarą sizeofa jest właśnie rozmiar literki jako "jeden"

Funkcja ma jakiś parametr góra, z którym nic się nie dzieje, ale co gorsza ma cos zwracać, a nie zwraca.

Ten kod musi wyć od ostrzeżeń kompilatora. Na takim etapie, każde ostrzeżenie to ma byc jak bład.
Prawdę mówiąc zmęczyłem się przy próbie czytania. Pełen jest jakiś podjętych a niedokończonych zamiarów

1
  1. Na każde pole struktury przydzielasz 20 znaków, to czemu nie zrobić od razu w strukturze: char imie[20],nazwisko[20];
  2. W pliku masz pola oddzielone spacjami zaś fscanf chce średników, więc wczytuje cały plik w pole imie pierwszego kontaktu mające 20 znaków rozmiaru
  3. Dodaj sobie struct list { struct element *pierwszy,*ostatni; }; będzie wygodniej przekazywać do funkcji.
  4. http://forum.4programmers.net/1208091
  5. Napisz sobie do odczytu i zapisu specjalną funkcję:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <locale.h>

char *strdup(const char *str)
{
	int size=strlen(str)+1;
	char *ret=(char*)malloc(size);
	memcpy(ret,str,size);
	return ret;
}

char *readstr(FILE *source,const char *prompt)
{
	char buff[33];
	if((source==stdin)&&(prompt!=NULL)) printf("Podaj %s: ",prompt);
	fscanf(source,"%32[^;\n]",buff);
	fgetc(source);
	return strdup(buff);
}

int main()
{
	system("CHCP 65001>nul");
	setlocale(LC_ALL,"pl_PL.UTF-8");
    char *name=readstr(stdin,"imię");
    char *surname=readstr(stdin,"nazwisko");
    printf("podano: %s %s\n",name,surname);
    FILE *fout=fopen("test.cpp","w+");
    fprintf(fout,"%s;%s\n",name,surname);
    fclose(fout);
    free(surname);
    free(name);
    FILE *fin=fopen("test.cpp","r+");
    name=readstr(fin,"imię");
    surname=readstr(fin,"nazwisko");    
    fclose(fin);
    printf("wczytano: %s %s\n",name,surname);
    free(surname);
    free(name);
    return 0;
}
1

O co chodzi z tym komentarzem?

//microsoft learn kazal uzyc malloc.h ale nie dziala

Windows ma malloc.h? Myślałem, że to gnuism????

1

Po co ci w ogóle plik tekstowy? Tutaj znacznie lepiej sprawdzi się surowy plik binarny, i nawet łatwiejsza będzie implementacja skoro dane to lista struktur (tylko nie zapisuj wskaźników w pliku). Do tego zamiast:

struct kontakt
{
	char* imie;
	char* nazwisko;
	char* numer;
	char* grupa;
};

Użyj takiego zapisu, bez powtarzania nazwy typu:

struct kontakt
{
    char *imie,
	     *nazwisko,
	     *numer,
	     *grupa;
};

Z tablicą wbudowaną w strukturę też możesz zrobić podobnie:

typedef char pole[20];
struct kontakt
{ pole imie,
       nazwisko,
       numer,
       grupa;
};

No i dodatkowo rezerwować pamięć przez szybkie malloc (sizeof (pole)). Uwaga: typ wskaźnika to wciąż char*.

1

@vitt3:

Ustaw maksimum warningów, bo jest niemożliwe, aby było ich tak mało jak zgłaszasz - umknęło mi jakie środowiska C używasz

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