Wczytanie tekstu z pliku do tablicy

Wczytanie tekstu z pliku do tablicy
KA
  • Rejestracja:ponad 12 lat
  • Ostatnio:prawie 7 lat
  • Postów:18
0

Witajcie. Piszę aplikację quiz. W sumie mam ją już ukończoną, ale bardzo amatorsko. Aplikacja napisana jest w C++ Builder. Chodzi mi o wczytywanie pytań i odpowiedzi do programu. Aktualnie wykonuje to tak:

Kopiuj
void __fastcall TForm1::Wczytaj()
{
       fstream plik;
       plik.open("pyt.txt", ios::in);

       if(plik.good() == false)
       {
              ShowMessage("Błąd! Nie udało się wczytac pliku!");
              exit(0);
       }


       int nr_linii = (nr_pytania - 1) * 5 + 1;
       int aktualny_nr = 1;

       while(getline (plik, Linia))
       {
              if(aktualny_nr == nr_linii) Tresc = Linia;
              if(aktualny_nr == nr_linii + 1) A = Linia;
              if(aktualny_nr == nr_linii + 2) B = Linia;
              if(aktualny_nr == nr_linii + 3) C = Linia;
              if(aktualny_nr == nr_linii + 4) Poprawna = Linia;
              aktualny_nr++;
       }
       plik.close();
       Wypisz();
}

screenshot-20171109202001.png

Czyli za każdym kliknięciem przycisku "Następne" wykonuje się ponownie wczytanie danych z pliku. Ja chcę, aby to zrobić tak, że w aplikacji użytkownik sam wskazuje plik, który ma zostać wczytany i wczytuje go do tablicy całościowo od razu. Czy jest taka możliwość?

C6
Metoda plik.good() zwraca boola to po co to porównanie?
KA
  • Rejestracja:ponad 12 lat
  • Ostatnio:prawie 7 lat
  • Postów:18
0

Klasa TForm2

Kopiuj
class TForm2 : public TForm
{
     __published:

     public:
       string Linia, Tresc, A, B, C, Poprawna, Odpowiedz;
       int nr_pytania, punkt, czas;
       vector < string > tab;

       void __fastcall Wczytaj(); 
       void __fastcall Wypisz(int nr); 
       void __fastcall Sprawdz();  
       void __fastcall Zapisz(); 
       void __fastcall LiczCzas();

       __fastcall TForm2();

};
Kopiuj
void __fastcall TForm2::Wczytaj()
{
       if (Form1 -> OpenDialog1 -> Execute())
        {
                ifstream plik (Form1 -> OpenDialog1 -> FileName.c_str());
                if (plik.good() == false)
                {
                        ShowMessage("Błąd. Wskaż prawidłowy plik!");
                }
                else {
                        while (getline(plik, Linia)) tab.push_back(Linia);
                        plik.close();
                        Form1 -> Tekst_BladNazwisko -> Caption = "Plik wczytano poprawnie!";
                        Form1 -> Przycisk_Start -> Enabled = true;
                }
                
        }
}

W Form1 mam wszystkie przyciski itp. (elementy wizualne)
Po skompilowaniu programu, wczytaniu pliku wywala błąd:
Bez tytułu.jpg

i otwiera się debugger z podświetloną tą linijką:

Kopiuj
  bool empty() const { return this->_M_start == this->_M_finish; }   

Zauważyłem, że jeżeli jest wszystko w jednej klasie to nie ma żadnych problemów!

edytowany 1x, ostatnio: Karpiusz
06
Dlaczego Linia jest polem klasy zamiast być zmienną lokalną?
06
  • Rejestracja:prawie 20 lat
  • Ostatnio:około rok
  • Postów:2440
0

Zgaduję, że odwołujesz się do tab w chwili, gdy obiekt klasy TForm2 już nie istnieje.

KA
  • Rejestracja:ponad 12 lat
  • Ostatnio:prawie 7 lat
  • Postów:18
0
0x666 napisał(a):

Zgaduję, że odwołujesz się do tab w chwili, gdy obiekt klasy TForm2 już nie istnieje.

Dlaczego miałby przestać istnieć?

06
  • Rejestracja:prawie 20 lat
  • Ostatnio:około rok
  • Postów:2440
0

Jak pisałem - zgaduje ;) Z kodu, który podałeś, niewiele da się wyciągnąć, jeśli chodzi o przyczynę błędu.

W Form1 mam wszystkie przyciski itp. (elementy wizualne)

Jeśli TForm1 jest główną formą, czym jest TForm2? Samo wywołanie TForm2::Wczytaj() powoduje błąd? Jak tworzysz obiekt klasy TForm2?

KA
  • Rejestracja:ponad 12 lat
  • Ostatnio:prawie 7 lat
  • Postów:18
0
0x666 napisał(a):

Jak pisałem - zgaduje ;) Z kodu, który podałeś, niewiele da się wyciągnąć, jeśli chodzi o przyczynę błędu.

W Form1 mam wszystkie przyciski itp. (elementy wizualne)

Jeśli TForm1 jest główną formą, czym jest TForm2? Samo wywołanie TForm2::Wczytaj() powoduje błąd? Jak tworzysz obiekt klasy TForm2?

https://pastebin.com/059ZUtRw

Błąd powoduje prawdopodobnie ta linijka:

Kopiuj
while (getline(plik, Linia)) tab.push_back(Linia);

Ale nie było z nią problemów kiedy istniała tylko jedna klasa.

06
  • Rejestracja:prawie 20 lat
  • Ostatnio:około rok
  • Postów:2440
0

Ta linia jest jak najbardziej ok. Nie widzę, żeby Form2 było tworzone (cały czas upieram się, że obiekt klasy TForm2 nie istnieje w czasie wywołania metody). Sprawdź, jaka jest wartość wskaźnika this wewnątrz TForm2::Wczytaj().

Jaki jest sens klasy TForm2, jeśli wszędzie odwołujesz się do Form1?

KA
  • Rejestracja:ponad 12 lat
  • Ostatnio:prawie 7 lat
  • Postów:18
0
0x666 napisał(a):

Ta linia jest jak najbardziej ok. Nie widzę, żeby Form2 było tworzone (cały czas upieram się, że obiekt klasy TForm2 nie istnieje w czasie wywołania metody). Sprawdź, jaka jest wartość wskaźnika this wewnątrz TForm2::Wczytaj().

Jaki jest sens klasy TForm2, jeśli wszędzie odwołujesz się do Form1?

Więc jak stworzyć Form2?
Co do sensu klasy TForm2. Robię projekt na uczelnie. Kazał jak najwięcej klas, a nie wiem jak to zrobić bardziej estetyczniej. Oczywiście klasę TForm2 podziele jeszcze na dwie inne. na razie walczę z tym błędem.

06
Sprawdziłeś ten this?
MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:3 minuty
0

Po pierwsze napisz nową klasę opisującą pytania.
Zgodnie z wzorcem MVC (Model View Controller), masz napisać klasę modelu danych, który przechowuje te dane.
TForm1 to twój kontroler, a widokiem są elementy UI-a, które wyklikałeś.

I jeszcze: https://4programmers.net/Forum/C_i_C++/300163-pytanie_o_strukture_danych_w_pliku_txt?p=1422976#id1422976 (pewnie kolega).


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 2x, ostatnio: MarekR22
KA
  • Rejestracja:ponad 12 lat
  • Ostatnio:prawie 7 lat
  • Postów:18
0
MarekR22 napisał(a):

Po pierwsze napisz nową klasę opisującą pytania.

Ale to mi nic nie da, bo i tak muszę się odwołać do TForm1, aby wskazać OpenDialog1.

Jak sprawdzić ten this?

MarekR22
a kto ci karze otwierać dialog w nowej klasie? Tam przekazujesz tylko strumień, albo nazwę pliku.
06
  • Rejestracja:prawie 20 lat
  • Ostatnio:około rok
  • Postów:2440
0

Jak sprawdzić ten this?

Debuggerem, albo nawet massageboxem (wyświetlasz zawartość AnsiString().sprintf("%p", this)).

aby wskazać OpenDialog1.

A po co? W onclicku przycisku odpalasz dialoga i ścieżkę podajesz w parametrze metody wczytaj().

KA
  • Rejestracja:ponad 12 lat
  • Ostatnio:prawie 7 lat
  • Postów:18
0

W ogóle nie rozumiem co wy do mnie mówicie. :|
To musi być coś popierdzielone z tymi klasami, ponieważ wkleiłem to do pierwszej klasy TForm1

Kopiuj
void __fastcall TForm1::Przycisk_WczytajClick(TObject *Sender)
{
        string Linia;
        if (OpenDialog1 -> Execute())
        {
                ifstream plik (OpenDialog1 -> FileName.c_str());
                if (plik.good() == false)
                {
                        ShowMessage("Błąd. Wskaż prawidłowy plik!");
                }
                else {
                        while (getline(plik, Linia)) tab.push_back(Linia);
                        plik.close();
                        Tekst_BladNazwisko -> Caption = "Plik wczytano poprawnie!";
                        Przycisk_Start -> Enabled = true;
                }
        }
}

oraz w publicu klasy dodałem

Kopiuj
vector < string > tab;

I wczytało plik bez żadnych problemów...

Ale ja chcę mieć wczytywanie w drugiej klasie, a w tej same przyciski...

MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:3 minuty
0
Karpiusz napisał(a):

Po skompilowaniu programu, wczytaniu pliku wywala błąd:
Bez tytułu.jpg

i otwiera się debugger z podświetloną tą linijką:

Kopiuj
  bool empty() const { return this->_M_start == this->_M_finish; }   

Zauważyłem, że jeżeli jest wszystko w jednej klasie to nie ma żadnych problemów!

To jest linijka z STL-a. Żeby ustalić co jest nie tak, to:

  1. Odtwórz crash
  2. jak debugger zatrzyma się na tej linijce, rozejrzyj się po UI IDE, powinieneś znaleźć widok "Call stack"
  3. "Call stack" zawiera listę funkcji, które wywołały bieżącą funkcję
  4. Klikaj kolejne pozycje, aż osiągniesz swój kod.
  5. Podejrzyj zmienne w okolicach swojego kodu i zastanów, się czy jakiś wskaźnik nie wskazuje na nieprawidłową wartość.

Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 1x, ostatnio: MarekR22
06
  • Rejestracja:prawie 20 lat
  • Ostatnio:około rok
  • Postów:2440
0

Inaczej. Ustaw breakpointa na linii Form2 -> Wczytaj();, wywołaj zdarzenie z tą linią i kiedy program zatrzyma się na niej, podejrzyj, jaką wartość ma wskaźnik Form2.

I wczytało plik bez żadnych problemów...

Dlatego że obiekt tej klasy istnieje w pamięci, a obiekt wskazywany przez wskaźnik Form2 najprawdopodobniej nie. Sprawdź ten wskaźnik...

RE
  • Rejestracja:ponad 18 lat
  • Ostatnio:około 3 godziny
0

Kolego jak wyżej koledzy wspomnieli o MVC. Poczytaj o tym wzorcu są przykłady na necie. To jedno
Napisz testy jednostkowe w gtest(gmock) do softu. Unikniesz pewnych problemów. Wpisz w google TDD gtest.


We are the 4p. Existence, as you know it, is over. We will add your biological and technological distinctiveness to our own. Resistance is futile
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)