Wyciąganie danych z pliku i podział

0

Otóż próbuje napisać część program która wyciąga linię z pliku, i dzieli ją odpowiednio na int/string/string/double/double/int.
Niestety program się wysypuje (przestaje odpowiadać), nie wczytuje ostatniej cyfry, oraz przy case 3 i wyrazie na 4 litery dopisuje jakieś 2-elementowe bzdury:

 void wczytaj_dane(char nazwa[20])
{	string s;
	char t[8];
	string t1;
	int k,p;
	fstream plik;
	plik.open(nazwa, fstream::in);
	if(plik.is_open())
	{ 
		for(int i=0;i<il_pociagow;i++){
			getline(plik,s);
			p=0;
			k=0;
			for (int l = 0; l<s.size() ;l++){
				if (s[l]!=';' && s[l]!='\n'){
				t[k]=s[l];
				k++;}
				else{t[k]='\0';
					switch(p){
						case 0:
							tablica_danych[i].ID = atoi(t);
							p++;
							k=0;
							cout<<tablica_danych[i].ID<<endl;
							break;
						case 1:
							k=0;
							while(t[k]!=NULL){
							tablica_danych[i].TRASA[k]=t[k];
							k++;
							}
							cout<<tablica_danych[i].TRASA<<endl;
							
							p++;
							k=0;
							break;
						case 2:
							k=0;
							while(t[k]!=NULL){
							tablica_danych[i].TYP[k]=t[k];
							k++;
							}
							cout<<tablica_danych[i].TYP<<endl;
							
							p++;
							k=0;
							break;
						case 3: 
							tablica_danych[i].PRZYJAZD=atof(t);
							cout<<tablica_danych[i].PRZYJAZD<<endl;
							p++;
							k=0;
							break;
							
						case 4:
							tablica_danych[i].POSTOJ=atof(t);
							cout<<tablica_danych[i].POSTOJ<<endl;
							p++;
							k=0;
							break;
						case 5:
							tablica_danych[i].PERON = atoi(t);
							p++;
							k=0;
							cout<<tablica_danych[i].ID<<endl;
							break;
					
				}	
				}
				
				
		}
		
	}
}
}

Co moze być źle?

1

To samo po ludzku brzmi następująco:

#include <iomanip> // dla ws

void wczytaj_dane(char nazwa[])
  {
   ifstream plik(nazwa);
   for(int i=0;(plik)&&(plik>>tablica_danych[i].ID);++i)
      {
       string s;
       getline(plik,s,';');
       plik.getline(tablica_danych[i].TRASA,8,';');
       plik.getline(tablica_danych[i].TYP,8,';');
       plik>>tablica_danych[i].PRZYJAZD; getline(plik,s,';');
       plik>>tablica_danych[i].POSTOJ; getline(plik,s,';');
       plik>>tablica_danych[i].PERON>>ws;
      }
  }

getline(plik,s,';'); możesz śmiało zastąpić na plik.get();

0

Wczytuje dobrze, ale tylko pierwszą linię z pliku. Próbowałem dodać pętlę przed tą, ale nic nie dała, oraz trochę modyfikować twój kod, ale też mi nie pomogło. ;/
Jakaś porada?

#include <iostream>
#include <fstream>
#include <conio.h>
#include <stdlib.h>
#include <iomanip> // dla ws

using namespace std;

struct dane{
	int ID; 
	char TRASA[8]; //np. WAW-KRK
	char TYP[8]; // np. EX...
	double PRZYJAZD;
	double POSTOJ;
	int PERON; // {1,2,3}
};

// ILOŚĆ POCIĄGÓW
//******************************************************************************
int il_pociagow; //zmienna globalna
dane *tablica_danych = new dane[il_pociagow];
void ilosc_pociagow(char nazwa[20]){
	fstream plik;
    plik.open(nazwa, fstream::in); //otwarcie pliku do odczytu

    if(plik.is_open())
    {
    	string s;
    	il_pociagow=0;
    	while(getline(plik,s)!=NULL){
    	
    	il_pociagow++;
    	
    	}
    }
    	else {
    	cout<<"brak pliku"<<endl;
    	}
    return;
}

// WCZYTANIE DANYCH
//******************************************************************************

 
void wczytaj_dane(char nazwa[])
  {
   ifstream plik(nazwa);
   for(int i=0;(plik)&&(plik>>tablica_danych[i].ID);++i)
      {
       string s;
       getline(plik,s,';');
       plik.getline(tablica_danych[i].TRASA,8,';');
       plik.getline(tablica_danych[i].TYP,8,';');
       plik>>tablica_danych[i].PRZYJAZD; getline(plik,s,';');
       plik>>tablica_danych[i].POSTOJ; getline(plik,s,';');
       plik>>tablica_danych[i].PERON>>ws;
       // sprawdzanie dodane ***************************************************
       cout<<tablica_danych[i].ID<<endl;
       cout<<tablica_danych[i].TRASA<<endl;
       cout<<tablica_danych[i].TYP<<endl;
       cout<<tablica_danych[i].PRZYJAZD<<endl;
       cout<<tablica_danych[i].POSTOJ<<endl;
       cout<<tablica_danych[i].PERON<<endl;
      }
  }
// FUNKCJA MAIN
//******************************************************************************

int main()
{
	char nazwa_pliku[20] = "stacja.txt";
	ilosc_pociagow(nazwa_pliku);
	wczytaj_dane(nazwa_pliku);
	
	
	return 0;
}

 

plik w formacie np:
1;WAW-KRK;ex;50.2;4.7;1
4;KRK-WAW;posp;27.2;5.5;2

@Edit:
Przepraszam, podałem program po nieudanych przeróbkach.

@edit2:
Program się "wiesza" po przeczytaniu dwóch linii i nie wiem z jakiego powodu... (wczytuje i wyświetlna i nagle "program przestał odpowiadać")

@edit3:
Wiem, że problem leży w:
dane *tablica_danych = new dane[il_pociagow];
ponieważ po zadeklarowaniu tablicy statycznej ( dane tablica_danych [4];) działa bez zarzutu.
Ale nie widzę niczego złego w powyższej deklaracji.... A nie wiem jaki będzie plik wejściowy duży dlatego chciałeś użyć dynamicznej.
W każdym razie dziękuję za pomoc.

A... zapomniałbym... Czy da sie jakoś zmienić ten kod, żeby w pliku wejściowym mogło być puste pierwsze pole (ID) i resztę robił pomyślnie?

1
superkasa napisał(a):

Wiem, że problem leży w:
dane *tablica_danych = new dane[il_pociagow];
ponieważ po zadeklarowaniu tablicy statycznej ( dane tablica_danych [4];) działa bez zarzutu.
Ale nie widzę niczego złego w powyższej deklaracji.... A nie wiem jaki będzie plik wejściowy duży dlatego chciałeś użyć dynamicznej.

Instrukcje nie działają wstecz.
Czyli po deklaracji:
dane *tablica_danych = new dane[il_pociagow];
tablica_danych ma dokładnie tyle elementów ile teraz wynosi il_pociagow, nawet jak później zmienisz wartość il_pociagow.
przydzielaj pamięć dopiero po policzeniu wierszy, a jeszcze lepiej od razu dodawaj je do listy jednokierunkowej, nic nie trzeba liczyć.

0

Czyli gdzie ją mogę zadekatować? O liście jednokierunkowej nic nie wiem... Ale zobaczę, czym się to je. Dziękuję.

@Edit:
Lista jednokierunkowa odpada, bo przegladac można ją tylko po kolei, a ja muszę inaczej danymi obracać ;)

@edit2:
Wolałbym jednak tą tablicę... :D Bo o liście jednokierunkowej nic nie wiem :D Ale dalej nie wiem gdzie zadeklarowac.. ;/

@edit3:
To już zrobiłem, dzięki.
A jeszcze pytałem już... Czy da się to przerobić tak, żeby nie potrzebowała pierwszej danej? (linijka w pliku wygląda tak: " ;KRK-WAW;.... itd."), bo teraz jeśli napotka puste pole to się zatrzymuje.

0
superkasa napisał(a):

Czy da się to przerobić tak, żeby nie potrzebowała pierwszej danej? (linijka w pliku wygląda tak: " ;KRK-WAW;.... itd."), bo teraz jeśli napotka puste pole to się zatrzymuje.
Jasne że można.

0

Dokładnie chodzi o to, że w pliku wejściowym może być pste pole tylko przy ID np:
8;WAW-KRK;ex;1.9;2.0;2
;KRK-WRO;posp:2.0.2.0;1

A gdy wczytuje to pętla się zatrzymuje... Konczy wczytywać przed pustą daną. A chciałbym żeby np wpisało tam 0 albo cokolwiek (jako brak danych) i wczytało resztę normalnie.

@Edit:
Własnie nie wiem... Po prostu może być w pliku "pusto", a chciałbym, żeby się w takim przypadku program nie zatrzymywał tylko "przeszedł" i zostawiając niewypełnioną daną (nie wiem czy się da) lub dodając coś innego np -, 0 , _ spację.

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