C: wczytywanie danych z pliku

0

Program wczytuje plik .csv, który jest w postaci:

#komentarz
wartosc x1, wartosc y1
wartosc x2, wartosc y2
...

Przy wczytywaniu ma pominąć komentarz (lub komentarze) i zapisać dane do struktury (samo w sobie łatwe). Jednak nie wiemy, ile jest punktów w tym pliku i program powinien zliczyć je sam na samym wstępie (by potem odpowiednio zadeklarować rozmiar tablicy) i na tym program mi się sypie (tzn. nic się nie dzieje - dosłownie). Cały program, który mam do napisania jest większy, jednak kombinuję teraz na jego malutkim, przerobionym fragmencie w postaci:

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

struct Punkt
{
	double x;
	double y;
};

void pominKomentarze(FILE *plik)
{
	int znak;
	znak = getc(plik);

    while (znak == '#')
    {
            while (znak != '\n')
            {
                  znak = getc(plik);
            }

        znak = getc(plik);
    }
}

int zliczIloscProbek(FILE *plik)
{
	int i = 0;
	int znak;
	pominKomentarze(plik);
	znak = getc(plik);

	while (feof(plik) == 0);
	{
		if (znak == '\n')
			i++;
		znak = getc(plik);
	}

	return i;
}

int main()
{
	int i;
	struct Punkt* tab;
	FILE *plik = fopen("sumaprzebiegow.csv" , "r");

           tab = (struct Punkt*)malloc(100*sizeof(struct Punkt));

	if (plik == NULL)
	{
		 printf ("Nie mozna otworzyc pliku do odczytu\n");
		 exit(1);
            }

	pominKomentarze(plik);

	for (i = 0; i < 100; i++)
		{
			fscanf(plik, "%lf,%lf", &tab[i].x, &tab[i].y);
		}

	for(i = 0; i < 100; i++)
		printf("%lf %lf\n", tab[i].x, tab[i].y);

	rewind(plik);
           printf("Ilosc probek: %d\n", zliczIloscProbek(plik));

           fclose(plik);
	return 0;
}

Program bez problemu wczytuje wszystko, ale musiałem podać, że próbek jest 100, program mi tego nie chce policzyć (wprost z pliku oczywiście). Mógłbym zliczyć ilość punktów w strukturze oczywiście, jednak nie o to chodzi. W czym rzecz? Jak powinienem zliczyć ilość punktów?

1
int PointCount=0;
while(!feof(plik))
  {
   if(fscanf(plik,"%lf,%lf",&tab[PointCount].x,&tab[PointCount].y)!=2) while(fgetc(plik)!='\n') {}
   else ++PointCount;
  }
1

Mam dla ciebie dobrą wiadomość, nie musisz wiedzieć ile masz tych punktów ;)
Widzę, że kod jest w C, więc użycia vector'a chyba chciałbyś uniknąć.
To co ci proponuję tutaj to lista jednokierunkowa.
Tworzysz sobie najpierw strukturę, która zawiera twój punkt i wskaźnik na samą siebie:

struct Element
{
   struct Punkt point;
   struct Element* next;
};

Nie wiem, czy wiesz co to są listy (polecam szybki wgląd w wikipedie), ale pokrótce idea polega na tworzeni kolejnych elementów połączonych ze sobą poprzez wskaźnik.

// na początku funkcji main tworzysz wskaźnik na pierwszy element listy
struct Element* head = NULL;

// dodawanie nowego elementu najłatwiej jest zrealizować dodając go na początek list
// ale najpierw tworzysz nowy element:
struct Element* newEl = (struct Element*) malloc(sizeof(struct Element));
newEl->point.x = x;
newEl->point.y = y;

// teraz dodawanie:
newEl->next = head; // ustawiasz wskaźnik na następny element na obecnie pierwszy element listy
head = newEl;          // i nasz nowy element staje się teraz pierwszym elementem listy

Jakie to ma minusy?
Otóż będziesz musiał potem usunąć te wszystkie elementy, by nie zaśmiecały pamięci. Co oznacza przejście się pod koniec działania programu przez całą listę i zrobienie delete na każdym elemencie (pamiętaj o tym by zapisać sobie wcześniej wskaźnik na następny element, bo inaczej do niego nie dotrzesz).
Kolejnym minusem tego rozwiązania jest, że przez dopisywanie elementów na początek listy odwróci ci się ich kolejność. Ale jeśli poczytasz trochę o listach to odkryjesz listę dwukierunkową, która rozwiąże ten problem.
Ostatnim minusem charakterystycznym dla list jest, to że chcąc się dostać do konkretnego (np siódmego) elementu musisz zaczynać od początku listy, bo jest ci znany wskaźnik tylko na jej pierwszy element.

Powodzenia z tym.
Gdybyś jednak ciągle chciał zliczyć listę elementów to puść program przez cały plik sprawdzając każdy pierwszy znak linii, czy nie jest '#' i jeśli nie jest to zwiększaj sobie jakiś licznik.

*kod był pisany bez sprawdzania, służy tylko jako przykład - nie kompilować, nie testować ;) *

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