Odczytywanie danych z pliku .csv do struktury [C]

0

Witam, potrzebuję pomocy z funkcją wczytującą dane z pliku csv do struktury. Nie rozumiem dlaczego program wczytuje mi zawartość całej auta.csvlinii, tylko do 1 zmiennej (temp->marka) a do reszty nic nie przesyła więc finalnie przykładowo mam że wartość temp->marka jest Ford;Mustang;2021;Czarny;32312;32131. Rozumiem, że funkcja tak jakby nie rozumie że średnik ma oddzielać dane, ale nie mam pojęcia jak to mógłbym naprawić.

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

struct REKORD
{
	int id;
	char* marka;
	char* model;
	int rokProdukcji;
	char* kolor;
	int przebieg;
	int cena;
	struct REKORD* next;
	struct REKORD* prev;
};

struct REKORD* first = NULL;
struct REKORD* last = NULL;

void WriteList(char*);
void ReadList(char*);
void ShowList(Void);
int GetIdMax(Void);

void main() {

	int menu = 0;
	while (1)
	{
		switch (menu)
		{
			case 0:
				printf("1. Zapisz plik\n");
				printf("2. Wczytaj plik\n");
				printf("3. Wyswitl liste\n");
				scanf("%d", &menu);

				system("cls");
				break;

			case 1:

				WriteList("auta.csv");

				menu = 0;
				break;
			case 2:

				ReadList("auta.csv");

				menu = 0;
				break;

			case 3:

				ShowList();

				menu = 0;
				break;
			default:
				break;
		}
	}
	
}

void WriteList(char* nazwa) {

	struct REKORD* temp;
	FILE* zapis;

	temp = first;
	zapis = fopen(nazwa, "w");

	while (temp != NULL)
	{
		fprintf(zapis, "%s;%s;%d;%s;%d;%d\n", temp->marka, temp->model, temp->rokProdukcji, temp->kolor, temp->przebieg, temp->cena);
		temp = temp->next;
	}

	fclose(zapis);

	printf("Plik zapisano pod nazwa %s.\n\n", nazwa);
}

void ReadList(char* nazwa) {

	int i;
	int linie = 0;
	struct REKORD* temp = NULL;
	FILE* odczyt;

	odczyt = fopen(nazwa, "r");

	if (odczyt == NULL) {

		printf("Plik nie istnieje\n\n");
		return 0;
	}

	while (!feof(odczyt))
		if (fgetc(odczyt) == '\n')
			linie++;

	rewind(odczyt);

	if (first == NULL) {

		temp = (struct REKORD*)malloc(sizeof(struct REKORD));
		temp->marka = (char*)malloc(sizeof(char) * 100);
		temp->model = (char*)malloc(sizeof(char) * 100);
		temp->kolor = (char*)malloc(sizeof(char) * 100);

		temp->next = NULL;
		temp->id = 1;
		fscanf(odczyt, "%s;%s;%d;%s;%d;%d\n", temp->marka, &temp->model, &temp->rokProdukcji, temp->kolor, &temp->przebieg, &temp->cena);
		temp->prev = NULL;

		first = temp;
		last = temp;
		linie--;
	}

	for (i = 0; i < linie; i++) {

		temp = (struct REKORD*)malloc(sizeof(struct REKORD));
		temp->marka = (char*)malloc(sizeof(char) * 100);
		temp->model = (char*)malloc(sizeof(char) * 100);
		temp->kolor = (char*)malloc(sizeof(char) * 100);

		temp->next = NULL;
		fscanf(odczyt, "%s;%s;%d;%s;%d;%d\n", temp->marka, temp->model, &temp->rokProdukcji, temp->kolor, &temp->przebieg, &temp->cena);
		temp->prev = last;
		temp->id = GetIdMax() + 1;

		last->next = temp;
		last = temp;
	}

	fclose(odczyt);

	printf("Wczytano plik %s\n\n", nazwa);
}

void ShowList(void) {

	struct REKORD* temp;

	temp = first;

	printf("Marka\tModel\tRokProdukcji\tKolor\tPrzebieg\tCena\n\n");
	while (temp != NULL)
	{
		printf("%d\t%s\t%s\t%d\t\t%s\t%d\t\t%d\n", temp->id, temp->marka, temp->model, temp->rokProdukcji, temp->kolor, temp->przebieg, temp->cena);
		temp = temp->next;
	}
	printf("\n");
}

int GetIdMax(Void) {

	int idMax = 0;
	struct REKORD* temp = first;

	while (temp != NULL) {

		if (idMax < temp->id)
			idMax = temp->id;
		temp = temp->next;
	}

	return idMax;
}
0

Ponieważ "%s" czyta do białego znaku.
Użyj: fscanf(odczyt, "%99[^;];%99[^;];%d;%99[^;];%d;%d\n", temp->marka, temp->model, &temp->rokProdukcji, temp->kolor, &temp->przebieg, &temp->cena);

0

A ja w poszukiwaniu rozwiązania natrafiłem na rozdzielanie tego z tablicy dopiero (http://www.cplusplus.com/reference/cstring/strtok/) a okazało się że jest takie proste rozwiązanie :P, a jeżeli mogę to chciałbym przy okazji dowiedzieć się czy te %99 coś konkretnego oznacza, czy to tak jakby bufor 99 znaków aż do napotkania średnika [^;]?

0

Wg mnie nie tędy droga. Jeżeli na tekstowe przydzielasz zawsze 100 znaków to może warto to zrobić od razu w strukturze?
Jak nie, to wczytaj cały wiersz i podziel go na fragmenty, po czym przydzielaj odpowiednią ilość pamięci dla każdego napisu.
Tak a propos strtok jest całkiem bezsensownym rozwiązaniem;

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct _Car
{
    char *producent,*model,*color;
    int year,mileage,price;
} Car;

typedef struct _Node
{
	Car car;
	struct _Node *next,*prev;
}Node;

typedef struct _List
{
	Node *head,*tail;
}List;


// If no strdup() in library
/*
char *strdup(const char *str)
{
	size_t size=strlen(str)+1;
	char *dst=(char*)malloc(size);
	return memcpy(dst,str,size);
}
*/

char *scan(char **scope,char separator)
{
	char *result=*scope;
	if(result)
	{
		*scope=strchr(*scope,separator);
		if(*scope) *((*scope)++)='\0';
	}
	return result;
}

Car read_from_file(FILE *file)
{
	Car car;
	char buff[1024+1],*scanptr;
	fscanf(file,"%1024[^\n]",buff);
	car.producent=strdup(scan(&scanptr,';'));
	car.model=strdup(scan(&scanptr,';'));
	car.year=atoi(scan(&scanptr,';'));
	car.color=strdup(scan(&scanptr,';'));
	car.mileage=atoi(scan(&scanptr,';'));
	car.price=atoi(scan(&scanptr,';'));	
	return car;
}

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