Zmiena plikowa w funkcji

0

Witam.
Borykam się z pewnym problemem.
Otóż nie wiem jak zrobić tak, aby zmienna plikowa była użyta w funkcji wewnątrz funkcji głównej. Funkcja jest w pętli dlatego nie chce za każdym razem otwierać ten sam plik i go nadpisywać. Chciałbym zadeklarować taką zmienną plikową i móc korzystać z niej wewnątrz pętli w funkcji.

0

Z pomocą przychodzi referencja/wskaźnik. Tu akurat refrencja

#include <iostream>
#include <fstream>
using namespace std;

void funkcja( std::fstream &plik )
{
	...
}
int main() {
	std::fstream plik( "plik.txt", std::ios::in );
	
	while(1)
	{
		funkcja( plik );
	}
	return 0;
}

Ogólnie to trochę nie rozumiem, ale może to Ci pokaże jak takie rzeczy robić

0

Błędu o braku zdefiniowanej zmiennej plikowej już nie ma. Mam natomiast inny problem.
Otóż nie wiem czemu funkcja zwraca zawsze wartość zero mimo, że tak nie powinno być.
Oto kod:

//deklaracja funkcji
int GetFileInfo(fstream &tempFile);

//deklaracja zmiennej plikowej, także w main
fstream tempFile(PLIK.c_str(), ios::in | ios::out);

//wywołanie funkcji w głównej main
records = GetFileInfo(tempFile) - 1;
cout<<records;

//zawartość funkcji
int GetFileInfo(fstream &tempFile){
	string line;
	do
    {
        getline(tempFile, line);
        lines++;
    }while(!tempFile.eof());
    
    return lines;
}

P.S wiem, że w kodzie jest fragment:

records = GetFileInfo(tempFile) - 1;

Moje pytanie jest, dlaczego funkcja wczytuje tylko jedną linię, mimo że fizycznie w pliku jest ich 5 (wynikiem funkcji powinno wyświetlić 4), zgodzicie się ?

Ktoś pomoże, bo szukam błędu i nic :(

0

1.Nazwa funkcji powinna opisywać to co ona robi. Twoja funkcja zwraca liczbę linii w danym pliku i tak właśnie powinna się nazywać, a nie jakieś GetFileInfo.
2.Gdzie masz deklarację/definicję lines i dlaczego nie jest to zmienna lokalna?
3.Na początku tej funkcji powinieneś ustawiać wskaźnik pliku na pozycję zerową (początek) pliku.

0

Co do nazwy to początkowo miała być inna, ale chwilowo tak zostało.

EDIT
Poprawiłem na:

int GetFileInfo(fstream &tempFile){
	string line;
	int lines = 0;
	tempFile.clear();
    tempFile.seekg(0, ios::beg);
	do
    {
        getline(tempFile, line);
        lines++;
    }while(!tempFile.eof());
    cout<<lines;
    return lines;
}

Wyrzuca 10 linii (a cały czas jest 5), a przy następnym uruchomieniu znowu 1.

Poza tym poniższy fragment:

records = GetFileInfo(tempFile) - 1;
cout << records;

cały czas daje 0

0

Czy przypadkiem nie zliczasz wierszy w pliku aby później przydzielić tablice na rekordy zapisane w tych wierszach?
Bo jeżeli tak to nie tędy droga, należy użyć (ewentualnie samemu stworzyć) jakiś kontener najprościej vector.

0

Z vectorów zawsze miałem problem :(

0

Jaki problem z vector'em?

0

Nigdy nie pamiętam jak poprawnie ich używać. Poza tym poszukałem przykładu w necie, przerobiłem na swoje potrzeby i kod się komplikuje, ale dalej zlicza źle :(

0

No to najwyższa pora się nauczyć.
Nie możesz omijać czegoś bo to tródne!!111!!11!!1 - ponieważ prędzej czy później Twoje braki w niewiedzy się odbiją. Tak samo jak z tabliczką mnożenia - wiadomo, możesz sobie dziewięć razy w pamięci czy na kartce dodawać ósemkę, ale po co iść na około?

0

Problem jest taki, że program cały plik traktuje jako jedna linia, mimo że tak nie jest (każda linia zakończona jest znakiem końca linii).

0

@Kremius - pokaż kod lub idź do wróżbitów.

0

Jestem poza domem bez dostepu do komputera. Pamiętam że mniej więcej funkcja wygląda nastepujaco.

int lines = 0;
std::vector<std::string> line;
do
{
     getline (plik, line);
     lines ++;

} while (!plik.eof());

Chyba tak to szło (tak czy inaczej zmieniłem zmienną line na wektorową). Albo wczytuje jako całość, albo źle zlicza, sam nie wiem ....

1

Nie, po prostu zgadujesz i programujesz przez permutacje, zamiast pomyśleć.
getline oczekuje strumienia oraz stringa. Ty mu przekazujesz strumień oraz wektor. Coś zgrzyta.
Mając tę wiedzę, popraw kod.

Poza tym wtedy to już line będzie zmienną globalną, a sama funkcja czymś w stylu LoadFileContent bez osobnego zliczania liczby linii (no bo liczba linii == liczba elementów w wektorze).

1
std::vector<std::string> content;
for(std::string line;getline(plik,line);) content.push_back(line);
//size_t lines=content.size(); // to nie jest potrzebne
0

Jeszcze jedna sprawa ;)
Czy na

vector

mogę wykonać takie operacje jak substr. Gdyż każda linijka rozpoczyna się od innych znaków (dokładnie trzech różnych kombinacji) i w zależności od tego która by to była kombinacja program wykonywałby inną funkcję. A w skrócie:

std::vector<std::string> content;
for(std::string line;getline(plik,line);) 
     content.push_back(line);
if(line.substr(0,3) == "010") funkcja010(line);
else if(line.substr(0,3) == "013") funkcja013(line);
else if(line.substr(0,3) == "030") funkcja030(line);
else cout<<"brak dopasowania :(";

Czy taki kod ma prawo zadziałać??

0
Kremius napisał(a):
std::vector<std::string> content;
for(std::string line;getline(plik,line);) content.push_back(line); // odradzam przenoszenia zawartości if/for/while na następny wiersz bez klamer
if(line.substr(0,3) == "010") funkcja010(line); // jaka line? skąd? gdzie masz deklaracje?

@Patryk27, @Endrju - od razu macie namacalny dowód na pożyteczność chowania zmiennej do for - kompilator go powstrzymał.

0

_13th_Dragon
Potrzebuje wczytać cały plik i w zależności od pierwszych trzech znaków każdej z linii wykonać inną funkcję, na całej linii.

0

No to masz wczytany cały plik do vector'a teraz musisz zrozumieć tą część zadania: "... znaków każdej z linii ..."

0

Stąd było moje pytanie z użyciem substr na zmiennej line (string)

0

Poczytaj jakiś kurs, naucz się, w nauce pomożemy (absolutnie nieodpłatnie) lub zamów gotowca (niestety odpłatnie).

0

Sęk w tym, że wcześniej to zrobiłem jako:

do
{
     getline(plik,line);
     lines++;
//obie zmienne były globalne
}while(!plik.eof());

i wszystko w wczytywało normalnie (nawet nie przesuwałem wskaźnika w pliku na początek). Teraz ten sam kod wczytuje mi całość jako jedna linia, czego nie mogę zrozumieć.

0

Ten kod nie jest poprawny, ustawienie flagi eof którą sprawdzasz w warunku (!plik.eof()) następuje podczas próby odczytu, jeżeli flaga została ustawiona to znaczy że odczyt się nie powiódł.
W tym kodzie zliczasz nawet ten nieudany odczyt.
Pamiętaj pętla do while() zakłada że przynajmniej jeden krok musi wykonać, czyli nie przywidujesz sytuacji kiedy to plik jest pusty?
Poza tym ta pętla jedynie zlicza wiersze (owszem niepoprawnie), ale nawet po ewentualnym naprawieniu po kiego ci ta pętla?

0
Kremius napisał(a):

Witam.
Borykam się z pewnym problemem.
Otóż nie wiem jak zrobić tak, aby zmienna plikowa była użyta w funkcji wewnątrz funkcji głównej. Funkcja jest w pętli dlatego nie chce za każdym razem otwierać ten sam plik i go nadpisywać. Chciałbym zadeklarować taką zmienną plikową i móc korzystać z niej wewnątrz pętli w funkcji.

Jaka zmienna plikowa.. znowu?

Otwierasz plik:
hf = CreateFile(....), albo inne podobne badziewie... jak fopen, czy coś tam.

no i potem masz to hf, którym się posługujesz przy operacjach na tym pliku.
the end of sztroy..

0

Pętla zliczająca ilość wierszy była mi potrzebna kiedyś. Kiedy potrzebowałem napisać to na szybko (od 5 miesięcy działa :) ).
Teraz chciałbym to poprawić tak, jak być powinno, stąd moje pytania.

Jeśli jest sposób na wczytanie pierwszego wiersza (albo chociaż jakieś jego części, tutaj był pomocny substr(), gdyż interesujące mnie dane zawsze były w tym samym miejscu) a później przetworzenie każdego z wierszy w oparciu o ich pierwsze znaki. W przypadku wystąpienia 010 na początku długość linii będzie inna niż w przypadku początku 013, więc interesujące mnie dane będą w innym miejscu.
a w krótkim schemacie:

line <- wiersz
[x] <- pozycja w pliku

wczytaj line[0] - obowiązkowe, jeśli nie jest w danym schemacie nie wczytuj dalej, zamknij plik, wyłącz program itp - po prostu dalsze wczytywanie nie ma sensu ;)
for(int i=0; i < ilosc pozostałych linii w pliku; i++){
   wczytaj line[i];
   if(line[i].substr(0,3) == "010") { funkcja010; } 
   if(line[i].substr(0,3) == "013") { funkcja013; } 
   if(line[i].substr(0,3) == "030") { funkcja030; } 
itp...
}

potrzebuje tak, gdyż każda linia zawiera inną długość oraz zawartość. Na podstawie 3 pierwszych znaków mogę rozpoznać, które dane ma wczytać...

0
Kremius napisał(a):

Pętla zliczająca ilość wierszy była mi potrzebna kiedyś. Kiedy potrzebowałem napisać to na szybko (od 5 miesięcy działa :) ).
Teraz chciałbym to poprawić tak, jak być powinno, stąd moje pytania.

Jeśli jest sposób na wczytanie pierwszego wiersza (albo chociaż jakieś jego części, tutaj był pomocny substr(), gdyż interesujące mnie dane zawsze były w tym samym miejscu) a później przetworzenie każdego z wierszy w oparciu o ich pierwsze znaki. W przypadku wystąpienia 010 na początku długość linii będzie inna niż w przypadku początku 013, więc interesujące mnie dane będą w innym miejscu.
a w krótkim schemacie:

line <- wiersz
[x] <- pozycja w pliku

wczytaj line[0] - obowiązkowe, jeśli nie jest w danym schemacie nie wczytuj dalej, zamknij plik, wyłącz program itp - po prostu dalsze wczytywanie nie ma sensu ;)
for(int i=0; i < ilosc pozostałych linii w pliku; i++){
   wczytaj line[i];
   if(line[i].substr(0,3) == "010") { funkcja010; } 
   if(line[i].substr(0,3) == "013") { funkcja013; } 
   if(line[i].substr(0,3) == "030") { funkcja030; } 
itp...
}

potrzebuje tak, gdyż każda linia zawiera inną długość oraz zawartość. Na podstawie 3 pierwszych znaków mogę rozpoznać, które dane ma wczytać...

No to czytaj to sobie... ewentualnie możesz całkiem olać pliki, i jechać po prostu po tablicy znaków,
używając File mapping.

TFileMap f(nazwapliku);

char *p = f.getPtr(); // początek tabicy
int lenp = f.size(); // rozmiar tej tablicy

i teraz zapierdalasz po tym p - jak po zwyczajnej tablicy;
żadnych operacji na plikach nie potrzebujesz!

0

Jeszcze jedno pytanie, czy jeśli prześlę zmienną wektorową jako argument funkcji (w moim przypadku void jeśli to ma znaczenie), to prześlę całą zawartość wektora ??
Krócej ;) , czy vector traktowany jest jako jedna zmienna, mimo iż może "chować" w sobie przykładowo 100 linii ??

0
Kremius napisał(a):

Jeszcze jedno pytanie, czy jeśli prześlę zmienną wektorową jako argument funkcji (w moim przypadku void jeśli to ma znaczenie), to prześlę całą zawartość wektora ??
Krócej ;) , czy vector traktowany jest jako jedna zmienna, mimo iż może "chować" w sobie przykładowo 100 linii ??

Chyba sam sobie na to odpowiedziałem, a chodziło mi o

void SaveToFile(vector<string> &OutputLines) // definicja funkkcji ;)

Mam za to inne pytanie, czy robiąc operację (czy jak to nazwać ;) replace() na zmiennej string, która później zwracana jest jako zmienna "wrzucana" do vectora jak rozumiem, wszystko zmieni się w pliku wyjściowym. Jak zapisać taką zamianę do pliku wejściowego ??

P.S Dlaczego operacje na pliku ?? Gdyż mógłbym w teorii zrobić, tak, aby wszystko robił w pamięci (nie wiem jak pobieranie z FTP, gdyż z tym w C++ mam problem (jakiś błąd przy użyciu Chilkat ;( ), ale potrzebuje archiwum ostatnich przerobionych plików. Stąd wszystko się zapisuje do innego pliku :).

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