Odczytywanie pliku - powrót na początek pliku

0

Pewnie da się to znaleźć w Google, ale jest to właśnie jeden z tych momentów, kiedy kompletnie nie wiem co wpisać w tą wyszukiwarkę.

Mam sobie na pulpicie plik tekstowy w którym są liczby całkowite oddzielone spacją, ustawione w trzech kolumnach (liczba wierszy nie ma znaczenia dla programu, ale liczba kolumn już tak):

100 256 666
2126 13609 195 
1205 -666 291
125 516 16
125 6 21
666 -12 51

Piszę program, który odczyta ten plik tekstowy i wyświetli na ekranie, a potem zsumuje te liczby.

Oto kod mojej radosnej twórczości: http://4programmers.net/Pastebin/3362 Mam nadzieję, że nikt się tu nie złapie za głowę z niedowierzaniem "Co ten noob nawymyślał!?" :D

Wyświetlenie na ekranie zawartości pliku przychodzi bez problemu, ale do zsumowania nie dochodzi po program przestaje działać:

user image

(ten tekst "otwieram plik tekstowy o zawartości" dałem chwilę po wklejeniu tego do pastebina, więc w pastebinie nie ma tej linijki, ale to żaden problem)

Myślę, że wiem, na czym polega problem. Program dotarł już na koniec pliku gdy już wyświetlił wszystkie wiersze. No i więc nie miał jak dodawać do wektora zmiennych z kolejnych wierszy w pliku. Jestem pewien, że nie ma żadnego błędu w samym kodzie odpowiadającym za dodawanie do wektora itp.

A więc moje pytanie: Co zrobić, by program powrócił na początek odczytywanego pliku?

zamiana znacznika <quote> na <code> - furious programming

0
void zapisanieDoWektora(ifstream &plik,vector<int> &wektor)
  {
   int a,b,c;
   while(plik>>a>>b>>c) wektor.push_back(a+b+c);
   dodawanie(wektor);
  }
1

http://ideone.com/KrJ5JH

#include <iostream>
using namespace std;
     
int main() {
    int sum = 0, number;
    for(size_t i = 1; cin >> number; ++i, sum += number)
        cout << number << (i%3? " " : "\n");
    cout << "sum: " << sum;
     
    return 0;
}

out:

100 256 666
2126 13609 195
1205 -666 291
125 516 16
125 6 21
666 -12 51
sum: 19296
0

Co do kodu.

void dodawanie(vector<int> & wektor)
{
    for(unsigned int a = 1; a < wektor.size(); a++)
    {
        wektor[0] += wektor[a];//sumowanie wszystkich elementow wektora
    }
    cout <<"Suma wszystkich liczb podanych w pliku tekstowym wynosi: " << wektor[0] << endl;
}

Na moje oko ta funkcja jest kompletnie nieintuicyjna. Dlaczego nie zwracasz sumy tych elementow jako wartosc z funkcji, tylko upychasz na pierwszy element podanego wektora. No i wypadaloby usuniac tego cout, oraz przekazywac wektora przez const ref. Dodatkowo, maly tip: wersja preferowana przeze mnie - std::accumulate. Wersja blizsza twojemu kodowi - for ranged loop.

void zapisanieDoWektora(ifstream & plik, vector<int> & wektor)
{
    while(plik.good())
    {
        int liczba[3];
        plik >> liczba[0] >> liczba[1] >> liczba[2];
        wektor.push_back(liczba[0]+liczba[1]+liczba[2]);

        if(!plik.good())
        {
            break;
        }
    }
    dodawanie(wektor);
}

Po co przekazujesz wektora jako parametr skoro jest uzyty tylko w tej funkcji? Po co przekazujesz konkretna klase (ifstream) skoro korzystasz jedynie z bardziej generalnego interfejsu? Dodatkowo ten while jest paskudny, znowu 2 wersje - std::copy + std::istream_iterator, ewentualnie prostsza:

int numbers[3];
while(stream >> numbers[0] >> numbers[1] >> numbers[2]) { ... }

I juz bez ifa na koncu.
Co do czytelnosci - tu rowniez lepiej byloby, gdyby ta funkcja po prostu wczytywala dane do wektora i zwracala ten wektor przez wartosc.

Generalnie funkcje void nie sa najlepszym pomyslem.

    ifstream plik;
    plik.open("C:/users/oem/desktop/zajebistyplik.txt");

Mozna zamienic na:

ifstream file(path)
for(bool wczytano = getline(plik, wiersz); wczytano; wczytano = getline(plik, wiersz))//odczytywanie pliku tekstowego

Zamien na:

while(getline(stream, line)) { ... }

Co do oryginalnego bledu, uloz kod w taki sposob.

std::ifstream file = open_file();
std::vector<string> lines = read_all(file);
std::vector<int> numbers = get_numbers(lines);
int numbers_sum = sum(numbers);

I wielokrotne czytanie badz otwieranie (czy przesuwanie wskaznika pliku) nie bedzie potrzebne.

0

@spartanPAGE

walnąłeś jak łysy grzywą o kant stołu

Masz jakies argumenty czy tak sobie piszesz, zeby pisac?

Bo za idea ograniczania funkcji wywolywanych dla efektow ubocznych kryje sie wiele pozytywnych skutkow:
#praktycznie darmowy cache
#praktycznie darmowe zrownoleglanie
#latwosc w zachowaniu poprawnosci kodu
#umozliwia equational reasoning (nie wiem jak to brzmi po polsku, ale pewnie niezbyt fajnie)
#latwosc w komponowaniu funkcji (tak, to ten element 'kluczowy')
#wiele, wiele innych.

Ale jak to nie przemawia, to nie wiem co moze przemowic, bo gwiazdki z nieba raczej nie ma.

0

Rozumiem np settery też powinny coś zwracać?

Rozumiesz znaczenie slowa 'ograniczenia'. Jesli cos jest potrzebne faktycznie, to jest i tego nie zmienisz. Fakt, mozna robic obejscia, ale to nie na tym zabawa polega. Chodzi o eliminowanie efektow ubocznych w miejscach, w ktorych one tak czy siak nie powinny wystepowac. Settery sa akurat specyficznym rodzajem metod, i tak jesli obiekty klasy 'moga' sie zmieniac to nie powinny zwracac zadnej wartosci, ani na sile nie ma sensu pchac tam czegokolwiek. Jesli natomiast potrzeba wygenerowac obiekt w czesciach (do czego czesto sluza settery) to duzo lepszy jest builder, ktorego niezaleznie od tego czy metody sa pure czy nie, podobnie sie implementuje.

Z reguly przy rozsadnym odcinaniu efektow ubocznych, dodatkowy naklad pracy jest niewielki, a korzysci dosc spore. Wiec czemuby nie?

Anyway... Settery sa zle z innych powodow, niezaleznie czy w formie:

val p = new Person()
p.setAge(10)

czy

val p = Person(3)
val modified = p.copy(age = 10)

Choc druga wersja jest w wiekszosci przypadkow i tak lepsza.

ciężko mi się czyta to, co piszesz

Mi sie ciezko dyskutuje jak ktos odpisuje w komentarzach z niewiadomych konkretnie przyczyn.

0

Już sobie poradziłem z problemem sam, a zrobiłem to w dość prosty sposób i aż nie mogę uwierzyć, że na to nie wpadłem i musiałem pytać na forum.

8f4bd6a062.png
Przepraszam za IMG, ale po przekopiowaniu kodu z codeblocks się okazało, że w podglądzie nie ma enterów, a co za tym idzie wszystkie linijki są zlepione razem, a mi się nie chciało tych enterów wsadzać ręcznie.

Aż nie mogę uwierzyć, że problem był taki banalny. Temat więc można zamknąć.
Cóż, tak naprawdę to jeśli plik wygląda tak, że są tylko liczby całkowite oddzielone spacjami, to zwykłe wypisanie zmiennych wyciągniętych z pliku również działa.

Nawet nie trzeba było cofać wskaźnika :P
I tak przydałoby się nauczyć jak cofnąć wskaźnik w pliku (aha, to tak się ta czynność nazywa), ale ta sprawa jest poruszana za dwie lekcje w kursie który biorę.

A co do sugestii o których pisał _tmp, to nie poprawię swojego kodu, bo propozycje _tmp zawierają różne metody o których pierwsze słyszę, a ja mam zasadę, że mój kod nie musi być najlepszy, ale ja mam za to rozumieć wszystko co napisałem. Na naukę C++ będę miał jeszcze masę czasu i wiele rzeczy się nauczę, zajebisty kod też będę kiedyś pisał, a na razie to będę po prostu szedł za swoim kursem.

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