C: wczytywanie danych z pliku

C: wczytywanie danych z pliku
M1
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 11 lat
  • Postów:2
0

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

Kopiuj
#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:

Kopiuj
#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?

edytowany 4x, ostatnio: marcinek16-11
_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:około 14 godzin
1
Kopiuj
int PointCount=0;
while(!feof(plik))
  {
   if(fscanf(plik,"%lf,%lf",&tab[PointCount].x,&tab[PointCount].y)!=2) while(fgetc(plik)!='\n') {}
   else ++PointCount;
  }

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
gabr
  • Rejestracja:ponad 12 lat
  • Ostatnio:prawie 7 lat
  • Lokalizacja:Śląsk
  • Postów:9
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:

Kopiuj
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.

Kopiuj
// 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ć ;) *

_13th_Dragon
Przy okazji odczytania można zliczyć po czym przepisać do tablicy.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.