Jump to content

Archived

This topic is now archived and is closed to further replies.

MatthewPL

[C++] Wybieranie z pliku tekstowego liczb rzeczywistych

Recommended Posts

Więc mam taki program na zaliczenie, jeszcze nie sprawdzony. Ogólnie wszystko co ma być to chyba jest, tylko poprawiłbym w nim parę rzeczy a nie wiem za bardzo jak.

Po pierwsze, nie ma mowy o użyciu tablic.

Wcześniej trzeba stworzyć plik z zawartością.

Jedna rzecz to: jak wczytuję plik gdzie każda liczba, litera lub słowo jest w oddzielnej linijce to przy wypisywaniu liczb zostają puste linie tam gdzie były litery. Niby ok, ale trochę brzydko wygląda i nie wiem jak to zlikwidować. Wydaje mi się, że problem tkwi w sposobie, który rozwiązuje problem i nie jest on chyba najlepszy bo jeśli w pliku będzie liczba zapisana w postaci 1e3, to e zostanie pominięte (chyba, że zrobię wyjątek). Da radę coś z tym zrobić czy muszę pisać od nowa innym sposobem? Jestem początkujący, a ktoś zaawansowany pewnie poradziłby sobie bez problemu.

//---------------------------------------------------------------------------

#include <vcl.h>      //w Dev-C++ jest blad w tym miejscu (?), usunac
#pragma hdrstop
#include <conio.h>
#include <iostream.h>
#include <fstream.h>

//---------------------------------------------------------------------------
#pragma argsused

void zapis() {    //zapisanie liczb rzeczywistych z pliku do nowego pliku
        char liczba;
        ofstream zapis;
        ifstream odczyt;
        odczyt.open("plik.txt",ios::in);     //plik z zawartoscia, musi byc przed uruchomieniem
        zapis.open("liczby.txt",ios::out);   //plik, w ktorym sa zapisywane liczby

        while ((liczba=odczyt.get())!=EOF)   //dopoki wczytywany znak nie jest znakiem konca pliku
                {
                        if ((liczba>=48) && (liczba<=57) || (liczba==46)
                        || (liczba==45) || (liczba==32) || (liczba==10))   //jesli kod ASCII znaku jest kodem cyfry, -, ., spacji lub entera
                                zapis<<liczba;  //zapisanie do pliku

                }

        odczyt.close();
    zapis.close();
}

void odczyt() {         //odczyt z pliku i wybranie liczb rzeczywistych
        char liczba1, liczba2;
        ofstream zapis;
        ifstream odczyt1,odczyt2;
        odczyt1.open("plik.txt",ios::in);   //do odczytania calego pliku
        odczyt2.open("plik.txt",ios::in);   //do odczytania liczb rzeczywistych
        zapis.open("liczby.txt",ios::out);  //do zapisania liczb rzeczywistych

    if (!odczyt1)     //sprawdzenie istnienia pliku do odczytu
            {
                    cerr<<"\nBrak pliku do odczytu.";
                        getch();
                        exit( 1 );
                }

        cout<<"\n"<<"To jest zawartosc pliku:\n";
        while ((liczba1=odczyt1.get())!=EOF)    //dopoki wczytywany znak nie jest znakiem konca pliku
                cout<<liczba1;                  //wypisanie zawartosci pliku

        cout<<"\n\nTo sa liczby rzeczywiste z pliku:\n";
        while ((liczba2=odczyt2.get())!=EOF)                          //dopoki wczytywany znak nie jest znakiem konca pliku
                if ((liczba2>=48) && (liczba2<=57) || (liczba2==46)
                || (liczba2==45)|| (liczba2==32) || (liczba2==10))     //jesli kod ASCII znaku jest kodem cyfry, -, ., spacji lub entera
                        cout<<liczba2;                                //zapisanie liczb do pliku
        cout<<"\n\n";

        odczyt1.close();
        odczyt2.close();
    zapis.close();
}

int menu() {    //menu glowne programu
        int o;
        cout<<"Wybieranie liczb rzeczywistych z pliku tekstowego\n\n";
        cout<<"1: Odczyt z pliku\n0: Koniec\nWybieram: ";
        cin>>o;
        return o;
}

int main(int argc, char* argv[]) {
        int b, o=menu();
        while (o!=0)
        {
                switch(o)       // menu z opcja zapisu do pliku
                {
                        case 1:
                        {
                        odczyt();
                        cout<<"Zapisac do pliku?\n1: tak\n0: nie\nWybieram: ";
                        cin>>b;
                        switch (b)
                                {
                                case 1:
                                        {
                                        zapis();
                                        system("cls");
                                        cout<<"Zapisano do pliku \"liczby.txt\"\n\n";
                                        break;
                                        }
                                case 0:
                                        system("cls");
                                        break;
                        }
                        break;
                }
        }
        o=menu();
        }
        return 0;
}
//---------------------------------------------------------------------------

Link to comment
Share on other sites

Żartujesz?

int wybierz_liczbe(std::fstream & plik, unsigned int indeks, double & wynik)
{
   plik.seekg(0, std::fstream::end);
   const unsigned int rozmiar = plik.tellg();
   plik.seekg(0, std::fstream::beg);

   const unsigned int pozycja = indeks * sizeof(double);

   if (rozmiar <= pozycja + sizeof(double))
   {
      return -1;
   }

   plik.seekg(pozycja, std::fstream::beg);
   plik.read(&wynik, sizeof(double));
   return 0;
}

Link to comment
Share on other sites

co do treści zadania to jeszcze zapisywanie tych liczb do innego pliku,

a w tej funkcji daje mi dwa błędy: Cannot convert 'double*' to 'char*' i Type mismatch in parameter '__s' (wanted 'char *', got 'double *')

po za tym nie za bardzo wiem co z tym zrobić bo zbyt wiele ten kod mi nie mówi :icon_eek:,

jak wywołać funkcję (jakie parametry) i gdzie się określa wczytywany plik,

no nie jestem w tym za bardzo biegły, ech

(używam C++ Builder 6)

Link to comment
Share on other sites

Cannot convert 'double*' to 'char*' i Type mismatch in parameter '__s' (wanted 'char *', got 'double *')
Metoda read przyjmuje parametr typu char *, a ja przekazałem double *. Trzeba zrobić rzutowanie typu wskaźnika:
(char *)

po za tym nie za bardzo wiem co z tym zrobić bo zbyt wiele ten kod mi nie mówi ,
To jest odczyt wartości typu double znajdującej się na wskazanej pozycji w pliku binarnym. Skoro treść zadania nie narzuca formy pliku, to moim zdaniem najprościej jest używać właśnie plików binarnych.

EDIT:

Tak właśnie przeczytałem treść zadania drugi raz i jest wyraźnie podane, że ma być plik tekstowy. Tak, nie ma to jak uważne czytanie. W takim razie, trzeba będzie nieco inaczej to rozwiązać.

END

jak wywołać funkcję (jakie parametry) i gdzie się określa wczytywany plik,
Parametry to chyba masz podane, prawda?

1. strumień pliku, w zasadzie mógłby tutaj być dowolny strumień wejściowy,

2. indeks/Pozycja/Numer liczby którą chcesz odczytać ze strumienia wejściowego,

3. zmienna typu double do której ma zostać zapisana odczytana z pliku wartość.

Funkcja zwraca 0, gdy uda jej się odczytać zadaną wartość, w przeciwnym razie zwraca wartość nie zerową.

co do treści zadania to jeszcze zapisywanie tych liczb do innego pliku,
No przecież treść zadania brzmi: "Wybieranie z pliku tekstowego liczb rzeczywistych". Nie było mowy o zapisie. Zapis binarny jest podobny do odczytu. Zamiast obiektu std::istream i metody read potrzebujesz std::ostream i metody write. Do przesuwania i pobierania pozycji służą seekp i tellp. Jeżeli plik jest za krótki, to trzeba by go przed zapisem przedłużyć, myślę, że najlepiej wypełnić zerami.

int zapisz_liczbe(std::ostream & plik, unsigned int indeks, double & wartosc)
{
   plik.seekp(0, std::ostream::end);
   const unsigned int rozmiar = plik.tellp();
   const unsigned int pozycja = indeks * sizeof(double);

   if (rozmiar <= pozycja)
   {
      double temp = 0;
      for (unsigned int i = rozmiar; i < pozycja; i += sizeof(double) )
      {
         plik.write((char *) &temp, sizeof(double));
      }
   }

   plik.seekp(pozycja, std::ostream::end);
   plik.write((char *) &wartosc, sizeof(double));
   return 0;
}

Link to comment
Share on other sites

Nagłówki

#include <fstream>
#include <iostream>
#include <string>
#include <sstream>

Pobranie wskazanej wartości double ze strumienia

int GetDoubleValueFromStream(std::istream & in, unsigned int index, double & val)
{
    std::string line;
    in.clear();
    in.seekg(0, std::istream::beg);

    for (unsigned int i = 0; i <= index; ++i)
    {
        std::getline(in, line);
        if (false == in.good())
        {
            return -1;
        }
    }

    std::stringstream str(line);
    str >> val;

    return 0;
}

Skopiowanie wartości double ze strumienia do strumienia

int CopyDoubleValuesFromStreamToStream(std::istream & in, std::ostream & out)
{
    double val;
    std::string line;
    in.clear();
    in.seekg(0, std::istream::beg);

    while (1)
    {
        std::getline(in, line);
        if (false == in.good())
        {
            break;
        }

        
        std::stringstream str(line);
        str >> val;
        out << val << std::endl;
    }

    return 0;
}

Przykład użycia

int main()
{
    //Open files
    std::fstream input("test.txt", std::fstream::in);
    if (false == input.is_open())
    {
        system("pause");
        return -1;
    }
    std::fstream output("out.txt", std::fstream::out);
    if (false == output.is_open())
    {
        system("pause");
        return -1;
    }

    //Show contents of input file
    int result = CopyDoubleValuesFromStreamToStream(input, std::cout);

    //Get first and second value from input
    double val;
    result = GetDoubleValueFromStream(input, 0, val);
    std::cout << val << "@" << result << std::endl;
    result = GetDoubleValueFromStream(input, 1, val);
    std::cout << val << "@" << result << std::endl;

    //Copy input file to output file
    CopyDoubleValuesFromStreamToStream(input, output);

    system("pause");
    return 0;
}

Przykładowy plik z danymi

-123.123
-123e-2
123.123

Link to comment
Share on other sites



  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...