Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Wczytywanie danych z pliku .txt do programu w C.

anonymousexd 25 Gru 2008 09:31 11183 20
  • #1 25 Gru 2008 09:31
    anonymousexd
    Poziom 24  

    Witam
    Jak w C wczytać dane z danego pliku w folderze programu? Chciałbym by kod

    Code:
    #define   MOJA_ZMIENNA1      50
    
    #define   MOJA_ZMIENNA2      100


    zamiast ustawiać zmienne na podane tu wartości ustawiał je na wartości wczyta z pliku .txt (jeśli sie da np pliku .zmn itp).. jak to prosto wykonać?

    PS przeczytałem ten
    temat lecz po pierwsze jest on o C++, a ja pisze o C, i po drugie... za bardzo go nie rozumiem..Licze na waszą pomoc, pozdawiam...

    0 20
  • #3 25 Gru 2008 10:24
    anonymousexd
    Poziom 24  

    Chyba znalazłem.. był jeszcze jeden problem, brakowało mi jednego include...
    jeszcze jedno pytanie, czy mógłbym zapisać te zmienne zamiast przez define przez int, tak bym mógł je zmienić w czasie działania programu? Na początku int ZMIENNA1; i coś co wczyta jej wartość z txt, a potem ZMIENNA1 = 10; ?

    0
  • #4 25 Gru 2008 10:38
    lord_dagoth
    Poziom 25  

    eeee... no tak, możesz -.-
    Po co w ogóle przez define'a w tym przypadku to robić?
    Po prostu deklarujesz odpowiednią zmienną, a potem z jej wartością robisz już co Ci się tylko podoba. Tylko pamiętaj o zakresie zmiennych.

    I powszechnie odradza się stosowania zmiennych globalnych!

    0
  • #5 25 Gru 2008 12:00
    anonymousexd
    Poziom 24  

    Więc przeczytałem kilka tematów znalezionych dzięki neo_dc, napisałem troche kodu... lecz mam jedno pytanie, a mianowicie jak powinien wyglądać plik z kodu opisanego tutaj?

    lord_dagoth napisał:

    Po co w ogóle przez define'a w tym przypadku to robić?


    W oryginalnym programiku było przez defina, a ja chce móc tą wartość ustawiać z pliku txt... więc jeśli nic nie stoi na przeszkodzie zrobie to przez coś innego :D

    0
  • #6 25 Gru 2008 12:28
    lord_dagoth
    Poziom 25  

    Ale z czym masz dokładniej problem? Pobieranie danych z pliku niewiele różni się od wczytywania danych z konsoli. Musisz zadeklarować wskaźnik na typ FILE, następnie otworzyć plik (poczytaj o funkcji fopen(), bo może ona otworzyć dany plik w kilku trybach, między innymi tylko do odczytu, do nadpisywania, do dopisywania itp.) A następnie to już działa analogicznie jak z wczytywaniem danych z konsoli, tyle że zamiast zwykłego scanf'a używasz fscanf'a, gdzie na początku podajesz mu wskaźnik powiązany z plikiem.

    0
  • #7 27 Gru 2008 21:28
    anonymousexd
    Poziom 24  

    Próbowałem troche, miałem też problem z wyświetleniem tekstu... nie było błędu, po prostu tekst sie nie pojawiał..

    W każdym razie przerzuciłem sie na C++.. przeczytałem troche o otwieraniu plików, ale nadal nie rozumiem jak mam rozdzielić liczby dla poszczególnych zmiennych?
    Opisze dokładnie problem:


    Mam 13 liczb o różnej ilości cyfr.. są one przypisane przez define w pewnym skomplikowanym kodzie... chce by program wczytywał te liczby z pliku txt... każda kolejna liczba będzie oddzielona spacją... z tym że w jednej liczbie oprócz pewnej ilości cyfr może znaleźć sie kropka (ułamki dziesiętne)

    Mógłby mnie ktoś bardzo nakierować na rozwiązanie? Albo podać prawie gotową część kodu? Z tego co przeczytałem orientuje sie że trzeba zastosować .open, while, i getline? Ale proszę o pomoc....

    0
  • #8 27 Gru 2008 22:29
    lord_dagoth
    Poziom 25  

    Nie za bardzo rozumie o co chodzi z tymi liczbami, które są przypisane przez define'a, a Ty chcesz je wczytywać?

    Bo jeżeli chodzi o wczytanie trzynastu cyfr dowolnej długości, oddzielonych od siebie spacjami, do jakiś tam zmiennych, to nie widze żadnego problemu. Tylko jakiego typu chcesz mieć te zmienne? Bo jak wystarczy Ci string, to najłatwiej to będzie wczytać. Po prostu 13 razy używasz scanf'a (albo fscanf'a jak chcesz z wcześniej otwartego pliku). Bo jeżeli nie znasz ilości cyfr w liczbie, to najlepiej będzie trzymać ją w stringu.

    A jeżeli nadal nie rozumiesz wczytywania danych z pliku do string'a (ew. tablicy) aż do napotkania spacji, to daj dokładną treść zadania albo kod jaki tam masz ;)

    EDIT: Co ja gadam, nawet nie musisz 13 razy używać scanf'a. Wystarczy raz. Podajesz mu po prostu wcześniej utworzone puste zmienne typu string, a on wszystko wciąga.

    Tutaj masz przykładowy kod na wczytanie 4 liczb dowolnej długości (mogą być kropki, przecinki i co tylko chcesz, byle nie spacje i entery) oddzielonych od siebie spacjami. Przerobienie tego na wczytanie tych liczb z pliku jest banalnie proste.

    Code:
    #include<stdio.h>
    
    #include<string>
    using namespace std;

    int main()
    {
       string z1,z2,z3,z4;
       scanf("%s%s%s%s",z1.c_str(),z2.c_str(),z3.c_str(),z4.c_str());
       printf("\n%s\n%s\n%s\n%s\n",z1.c_str(),z2.c_str(),z3.c_str(),z4.c_str());
       return 0;
    }

    0
  • #9 27 Gru 2008 23:13
    anonymousexd
    Poziom 24  

    Dziękuje za odpowiedź! Nie chce wczytywać definów... chce zamienić

    Code:

    #define   MOJA_ZMIENNA1      27122008.225

    na

    Code:
    #define   MOJA_ZMIENNA1      z1 


    I tak 13 zmiennych.... a zmienne są typu cyfry i przecinek, jak w przykładzie(można tak ustawić define na wcześniej wczytaną liczbe?)

    Co do tego kodu trzeba dodać? Widziałem różne sposoby odczytywania plików.. open, fstream? Z liczbą liczb wczytanych z pliku sobie poradze..

    0
  • #10 27 Gru 2008 23:20
    lord_dagoth
    Poziom 25  

    Nie chodziło mi o to jakiego typu są dane do wczytania, tylko w jakim typie chcesz je przechowywać. Bo wiesz, to że liczba do wczytania jest liczbą z przecinkiem to niewiele nam mówi, bo równie dobrze może się składać z 10 tys. cyfr, i żaden wbudowany typ jej nie pomieści ;) Więc jeżeli nie znasz długości liczby, to może lepiej przechowywać ją stringu, a w razie konieczności, gdy jej rozmiar będzie znany po prostu zamienić ją na np. typ float jakąś funkcją pokrewną do atoi().

    Naprawde, daruj sobie te #define'y, w tym przypadku są one nie potrzebne i tylko przeszkadzają. U nas na uczelni za używanie w ten sposób define'ow są odejmowane punkty! (zresztą za używanie zmiennych globalnych też ;) I racja, po co uczyć się złych nawyków?) Zadeklaruj normalnie w ciele funkcji main zwykłe 13 zmiennych, albo lepiej, tablice.

    A jeżeli nadal upierasz się przy define'nie to poczytaj co to w ogóle jest, http://pl.wikibooks.org/wiki/C/Preprocesor .

    A co do wczytywania z pliku... zaraz wkleje Ci kod, który wczyta 13 liczb z pliku do zmiennych...

    Oto program. Wczyta z pliku 13 liczb (plik o nazwie dane.txt, musi być w katalogu gdzie jest exe programu), a następnie je wypisze:

    Code:
    #include<stdio.h>
    
    #include<string>
    using namespace std;

    int main()
    {
       string zmienna[13];
       FILE *fp;
       fp=fopen("dane.txt", "r");
       for (int i=0;i<13;i++)
       {
          fscanf(fp,"%s",zmienna[i].c_str());
       }
       for (int i=0;i<13;i++)
       {
          printf("%s\n",zmienna[i].c_str());
       }
       fclose(fp);
       getchar();
       return 0;
    }

    Oczywiście można go troche uprościć, i zamiast dwóch pętli for użyć jednej, ale w tym wypadku nie ma to znaczenia, chodzi o zobrazowanie problemu ;)

    0
  • #11 28 Gru 2008 09:24
    anonymousexd
    Poziom 24  

    Rozumiem że ta druga pętla wypisuje zmienne?
    Probowalem skompilować, pojawiło sie dużo błędów z cstdio i cslib z folderu include...zrobiłem kopie zapasową i usunąłem zawartość tych plików, pojawiły sie błędy z cstdef... jak to naprawić?

    0
  • #12 28 Gru 2008 10:02
    lord_dagoth
    Poziom 25  

    Jakie błędy? Jakiego kompilatora używasz? Ja to pod visualem skompilowałem i nie było żadnego błędu, wszystko śmiga. Wklej treść błędu.

    0
  • #13 28 Gru 2008 11:25
    Dr.Vee
    VIP Zasłużony dla elektroda

    lord_dagoth, jeśli udzielasz porad, to przynajmniej z głową...

    1) Jeśli w c, to używamy scanf i printf; jeśli w c++ to strumieni.
    2) metoda c_str() klasy std::string zwraca const char*, czyli nie powinno się przekazywać takiego wskaźnika do fscanf. Obiekt klasy std::string sam zarządzą pamięcią dla przechowywanego napisu - zapisując dane używając wskaźnika zwroconego przez c_str() uniemożliwiasz automatyczną zmianę rozmiaru.
    3) plik "dane.txt" nie musi być w katalogu z exe, tylko w katalogu bieżącym.
    4) funkcja main powinna mieć pełen prototyp...

    anonymousexd: skasowałeś pliki nagłówkowe kompilatora? To bardzo sprytne posunięcie :) Jak u mnie się pojawi błąd kompilacji to też zawsze najpierw szukam błędów w kompilatorze ;)

    Pozdrawiam,
    Dr.Vee

    0
  • #14 28 Gru 2008 11:48
    lord_dagoth
    Poziom 25  

    Dr.Vee napisał:
    1) Jeśli w c, to używamy scanf i printf; jeśli w c++ to strumieni.

    Hmmm... to jest kwestia sporna. Pisząc programy w C++ bardzo często korzystam z scanf'a i printf'a, gdyż powszechnie wiadomo że strumienie są znacznie wolniejsze (a oddając projekty na SPOJ'u liczy się czas wykonywania programu, więc nawet nie używa się funkcji do zwalniania pamięci przy dynamicznym alokowaniu, bo tylko niepotrzebnie spowalnia program ;) ). Oczywiście w tym przypadku to nie ma najmniejszego znaczenia, użyłem tego do zobrazowania problemu. Autor chyba sam do końca nie wie, czy pisze to w C czy Cpp. Chociaż klasa string jest z cpp. Poza tym tytuł topic'u mówi nam, że korzystamy z C...
    Dr.Vee napisał:
    2) metoda c_str() klasy std::string zwraca const char*, czyli nie powinno się przekazywać takiego wskaźnika do fscanf. Obiekt klasy std::string sam zarządzą pamięcią dla przechowywanego napisu - zapisując dane używając wskaźnika zwroconego przez c_str() uniemożliwiasz automatyczną zmianę rozmiaru.

    Tutaj mój błąd, zapomniałem że zwrócony będzie const. Ale widzę że przekazanie samego obiektu klasy string nie za bardzo działa, więc chyba trzeba będzie zastosować strumienie...
    Dr.Vee napisał:
    3) plik "dane.txt" nie musi być w katalogu z exe, tylko w katalogu bieżącym.

    Plik tekstowy miałem umieszczony w kilku miejscach, między innymi w folderze z projektem. Za każdym razem Visual krzyczał, że wskaźnik jest pusty, dopóki nie przeniosłem pliku tekstowego do folderu, gdzie znajdowało się exe.
    Dr.Vee napisał:
    4) funkcja main powinna mieć pełen prototyp...

    Nie do końca rozumiem :P Poza tym, z tego co ja zrozumiałem, to nie trzeba było napisać autorowi programu do wczytania 13 liczb dowolnej długości, tylko nakierować go żeby mógł wykorzystać ten fragment w "skomplikowanym" kodzie. Tutaj kluczowe znaczenie ma otwarcie pliku i wczytanie liczb...
    -------------------------------------
    Można w ogóle zrezygnować z klasy string, i napisać to wszystko w czystym C, o ile autor mógłby powiedzieć, jakich rozmiarów mogą być dane wejściowe ;)

    0
  • #15 28 Gru 2008 20:35
    anonymousexd
    Poziom 24  

    Wczytywanie musi być w C++, bo chce dodać je do gry napisanej w C++.
    Co powinienem zmienić by ten kod działał? Wygląda na to że błąd jest w plikach z include w folderze Visual Studio... tylko że wcześniej gdy kompilowałem gre nic takeigo sie pojawiało, a pliki były te same.. wyczyściłem kilka z nich a błąd przechodzi jkakby do następnego!

    0
  • #16 28 Gru 2008 21:18
    maciek_slon
    Poziom 29  

    W plikach z katalogu include z VisualStudio nie ma błędów. A przynajmniej nie ma w nich takich błędów, które mógłbyś tak łatwo zauważyć. :P W każdym razie przywróć te pliki do stanu, w jakim były. To, że błąd pokazuje się niby w pliku jakimś standardowym to nie znaczy, żę tam jest. To znaczy jedynie, że od tamtego miejsca coś zaczęło się sypać, na 100% coś, co Ty napisałeś. :-) Jesli wkleisz komunikaty o błedach jakie otrzymujesz, będzie można pomóc...

    Dodano po 3 [minuty]:

    A jeśli chodzi o wczytywanie tych zmiennych z pliku .txt, to tak (zakładam, że zmienne typu double)

    Code:

    #include <fstream>
    using namespace std;

    double zmienne[20];

    void wczytaj_dane() {
      ifstream plik("dane.txt");
      for (int i = 0; i < 20; ++i)
        plik >> zmienne[i];
    }


    W tablicy zmienne będziesz miał 20 liczb wczytanych z pliku. Nie ma żadnego sprawdzania poprawności danych, najprostsza wersja, jaką się da napisać chyba. Plik z danymi powinien wyglądać mniej więcej tak, żeby to działało:
    Code:
    10.1 12 -1300.120 1 3.14

    Tyle, że liczb powinno być 20 :P

    0
  • #17 28 Gru 2008 21:28
    Dr.Vee
    VIP Zasłużony dla elektroda

    lord_dagoth: co do 1) to zacytuję Knutha: "Premature optimisation is the root of all evil" :)
    Co do 3), to zachowanie takie jest "windowsizmem" - domyślnie program uruchamiany jest z katalogu, w którym znajduje się plik exe - no ale czepiam się... ;)
    Co do 4): prototypy main:

    Code:
    int main(void);
    
    // lub
    int main(int argc, char *argv[]);
    // lub (nieprzenośne)
    int main(int argc, char *argv[], char *envp[]);

    anonymousexd - spróbuj tak:
    Code:
    #include <vector>
    
    #include <fstream>
    #include <iostream>

    int main(void)
    {
        std::ifstream stream("dane.txt");
        std::vector<std::string> vec;
        std::string s;

        // wczytaj
        while (stream >> s)
            vec.push_back(s);

        // wypisz
        for (int i = 0; i < (int)vec.size(); ++i)
            std::cout << vec[i] << std::endl;

        return 0;
    }

    Pozdrawiam,
    Dr.Vee

    0
  • #18 28 Gru 2008 21:35
    lord_dagoth
    Poziom 25  

    Ja myślę że najłatwiej to byłoby pomóc, jakby kolega anonymousexd nam powiedział:
    a) Czy zna dokładny typ, rozmiar i format danych wejściowych (bo jeżeli tak, to nie ma najmniejszego problemu)
    b) Wkleił nam, jakie błędy wyrzuca kompilator ;)
    Bo bez tych informacji to my sobie możemy gdybać i wymyślać sto milionów sposobów wczytania liczb nawet mających sto tysięcy liczb po przecinku ;)

    I tak się zastanawiam... jak autor tematu stoi z wiedzą o cpp? Bo jeżeli nie za dobrze chociaż z podstawami, to używanie wektora nie jest chyba zbyt dobrym pomysłem :P Pozatym jak już wspomniałem wyżej... wszystko zależy od tego, ile informacji mamy o danych wejściowych (czy znamy ich dokładną liczbę, format, itp itd) ;) Bo pewnie się okaże, że będzie to zawsze 13 liczb pokroju: 13.45 itp :P

    0
  • #19 29 Gru 2008 08:55
    anonymousexd
    Poziom 24  

    Tak, to właśnie liczby pokroju 13.45 . Ew 130000 albo 0.000013. Co do

    Code:
    int main(void)
    
    {


    }

    Nie umieściłem tego w kodzie bo jeden main był już otwarty... ale zaraz jeszcze raz spróbuje skompilować i wkleję błędy.


    Z ciekawości usunąłem cały kod poza oryginalnym i
    Code:
    #include "cg_local.h"
    
    #include<stdio.h>
    #include<string>


    I dalej pojawiająsie błędy!
    Cała masa typu
    Code:
    1>c:\microsoft visual studio 9.0\vc\include\cstring(26) : error C2143: syntax error : missing '{' before ':'
    


    A na koniec

    Code:
    1>c:\microsoft visual studio 9.0\vc\include\cstring(26) : fatal error c1003: error count exceeds 100;stopping compilation


    I podsumowanie:
    Code:
    1>cgame - 103 error(s), 0 warnings(s)







    Zostawiłem tylko include<stdio.h>, (string usunąłem). Kompiluje sie...

    Lecz po dodaniu kodu na wczytywanie pliku wychodzą różne błedy z nim związane, np:
    Code:
    syntax error : identifier 'string'

    Code:
    'fp' ; 'int' differs in levels of inderection from 'FILE *'



    Z tym na początku
    Code:
    #include <vector>
    
    #include <fstream>
    #include <iostream>
    też pojawiaja sie błędy "syntax error" w cstring i cwchar.

    0
  • #21 02 Sty 2009 17:05
    Dr.Vee
    VIP Zasłużony dla elektroda

    Kolego anonymousexd, mała porada. Jeśli pojawiają się błędy, to należy przedstawić:
    1) minimalny kompletny kod, przy kompilacji którego pojawia się błąd,
    2) rodzaj i wersję kompilatora + opcje użyte podczas kompilacji,
    3) listę wersji bibliotek, które są statycznie lub dynamicznie dołączane do programu.

    Pisanie, że coś tam dodałeś czy skasowałeś w Twoim projekcie/programie/plikach kompilatora i teraz nie działa nie zbliży Cię do rozwiązania, bo (chyba) nikt tutaj nie jest wróżką.

    A więc: upewnij się, że Twój kompilator jest poprawnie zainstalowany, a następnie skompiluj programy, które Ci tutaj zaproponowano. Jeśli pojawią się błędy, to je opisz. Jeśli nie, to znaczy, że problem leży w Twoim kodzie i jest to temat na osobny wątek.

    Pozdrawiam,
    Dr.Vee

    0