Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Zapis łańcucha znaków do pliku .txt.

Ostatnio zmodyfikowano 2017-09-17 14:54
Autor Wiadomość
DieG
Temat założony przez niniejszego użytkownika
[C++] Zapis łańcucha znaków do pliku .txt.
» 2017-09-17 00:07:41
Witam.

Powoli brnę do przodu przez książkę do nauki C++ i testowo napisałem program, który zapisywałby mi dane podane w konsoli do pliku.
Problem napotkałem podczas zapisu łańcucha znaków do pliku .txt. Mianowicie sprawdzenie warunku pętli i zapis łańcucha. Przepuszczanie każdego znaku oddzielnie nie zadziałało. Koniec końców wychodzi pętla nie do przerwania.

(Po drodze testowałem też unię i trochę ctype, więc użycie może być nie do końca konwencjonalne)

Kod (cały):
C/C++
#include <iostream>
#include <fstream>
#include <cctype>
#include <cstdlib>
#include <cstring>

void cin_clearFlags( void );
char shiftHeight( char );
void clearArray( char[] );
bool checkForChar( char[], char );

const int ArSize = 20;

int main()
{
    using std::cout;
    using std::cin;
    using std::endl;
    using std::ifstream;
    using std::ofstream;
   
    ifstream readStorage;
    readStorage.open( "storage.txt" );
   
    ofstream fillStorage;
    fillStorage.open( "storage.txt" );
   
    cout << "Dane wprowadzone z klawiatury zostana zapisane w pliku.\nZadecyduj teraz jaki typ danych bedziesz wprowadzac:"
    << "\n 1 - INT ( '0' aby zakonczyc )"
    << "\n 2 - FLOAT ( '0' aby zakonczyc )"
    << "\n 3 - CHAR ( '@' aby zakonczyc )\n";
   
    int choice = 0; //na 0 zeby zapobiec 'cudownemu' pojawieniu sie liczby od 1 do 3 w tym miejscu w pamieci za sprawa przebywajacych tam danych w danym czasie
    cin >> choice;
    while( !(( choice > 0 ) &&( choice < 4 ) ) )
    {
        cout << "\nNie ma takiej opcji !"
        << "\nSprobuj jeszcze raz:";
        cin >> choice;
    };
   
    union uType
    {
        int inputINT;
        float inputF;
        char inputCH;
    };
   
    uType keyboard;
   
    switch( choice )
    {
    case 1: keyboard.inputINT = 1; break;
    case 2: keyboard.inputF = 1; break;
    case 3: keyboard.inputCH = 'a'; break;
    }
   
    cout << "\nMozesz teraz podawac dane:\n";
   
    if( 1 == keyboard.inputINT )
    {
        int * tempINT = new int;
       
        cin >> * tempINT;
        cin.get();
        while( 0 != * tempINT )
        {
            if( cin )
            {
                keyboard.inputINT = * tempINT;
                fillStorage << keyboard.inputINT << "\n";
               
                cin >> * tempINT;
                cin.get();
            }
            else
            {
                cin_clearFlags();
               
                cin >> * tempINT;
                cin.get();
            }
        };
        if( 0 == * tempINT )
             delete tempINT;
       
    }
    else if( 1 == keyboard.inputF )
    {
        fillStorage.setf( std::ios_base::showpoint ); //Podczas zapisu do pliku uwzgledni tez kropki (przecinki) w liczbach zmiennoprzecinkowych.
       
        float * tempF = new float;
       
        cin >> * tempF;
        cin.get();
        while( 0 != * tempF )
        {
            if( cin )
            {
                keyboard.inputF = * tempF;
                fillStorage << keyboard.inputF << "\n";
               
                cin >> * tempF;
                cin.get();
            }
            else
            {
                cin_clearFlags();
               
                cin >> * tempF;
                cin.get();
            }
        };
        if( 0 == * tempF )
             delete tempF;
       
    }
    else if( 'a' == keyboard.inputCH )
    {
        char * tempCH = new char[ ArSize ];
        //tempCH[0] = 'a';
        char ch;
        cout << "(Max. " << ArSize << " znakow na wejscie)\n";
       
        //cout << "\ntempCH[0] " << tempCH[0] << "\n";
       
        cin.getline( tempCH, ArSize ).get();
        while( !checkForChar( tempCH, '@' ) )
        {
            if( cin )
            {
                int i;
                for( i = 0; i < ArSize; i++ )
                {
                    ch = tempCH[ i ];
                    keyboard.inputCH = shiftHeight( ch );
                   
                    if( keyboard.inputCH != '\n' )
                         fillStorage << keyboard.inputCH;
                   
                }
                fillStorage << "/n"; //przejdz do nastepnej linijki
                clearArray( tempCH );
               
                cin.getline( tempCH, ArSize ).get();
            }
            else
            {
                cin_clearFlags();
               
                cin.getline( tempCH, ArSize ).get();
            }
        };
        if( checkForChar( tempCH, '@' ) )
             delete[] tempCH;
       
    }
    else
    {
        cout << "Cos poszlo nie tak! Zamykam program.";
        exit( EXIT_FAILURE );
    }
   
    fillStorage.close();
    readStorage.close();
    return 0;
}

void cin_clearFlags()
{
    std::cout << "Czyszcze flagi obiektu 'cin'.\n";
    std::cin.clear();
    std::cin.sync();
}

char shiftHeight( char ch )
{
    if( isalpha( ch ) )
         islower( ch ) ? toupper( ch )
        : tolower( ch );
   
    return ch;
}

void clearArray( char ch[ ArSize ] )
{
    int i;
   
    for( i = 0; i < ArSize; i++ )
         ch[ i ] = ' ';
    /*for (i=0; i<ArSize; i++)
        {
            char x = ch[i];
            std::cout << x << " "; //wypisz zeby sprawdzic, czy 'wyzerowana'
        };
        std::cout << "\n(clearArray) Wyczyszczono tablice.\n";*/
}

bool checkForChar( char ch[ ArSize ], char whatToFind )
{
    bool found;
   
    for( int i = 0; i < ArSize; i++ )
    {
        if( ch[ i ] == char( whatToFind ) )
        {
            found = 1;
            break;
        }
        else
             found = 0;
       
    };
   
    return found;
}

Kod (problematyczna część):
C/C++
else if( 'a' == keyboard.inputCH )
{
    char * tempCH = new char[ ArSize ];
    //tempCH[0] = 'a';
    char ch;
    cout << "(Max. " << ArSize << " znakow na wejscie)\n";
   
    //cout << "\ntempCH[0] " << tempCH[0] << "\n";
   
    cin.getline( tempCH, ArSize ).get();
    while( !checkForChar( tempCH, '@' ) )
    {
        if( cin )
        {
            int i;
            for( i = 0; i < ArSize; i++ )
            {
                ch = tempCH[ i ];
                keyboard.inputCH = shiftHeight( ch );
               
                if( keyboard.inputCH != '\n' )
                     fillStorage << keyboard.inputCH;
               
            }
            fillStorage << "/n"; //przejdz do nastepnej linijki
            clearArray( tempCH );
           
            cin.getline( tempCH, ArSize ).get();
        }
        else
        {
            cin_clearFlags();
           
            cin.getline( tempCH, ArSize ).get();
        }
    };
    if( checkForChar( tempCH, '@' ) )
         delete[] tempCH;
   
}
P-164957
pekfos
» 2017-09-17 14:52:39
Takie użycie unii jest błędne. Reszta kodu jest bezsensownie przekombinowana.

C/C++
ifstream readStorage;
readStorage.open( "storage.txt" );

ofstream fillStorage;
fillStorage.open( "storage.txt" );
Nie otworzysz pliku do zapisu, gdy masz go wcześniej otwartego.
P-164962
Kinexity
» 2017-09-17 14:54:02
Zasadniczym problemem twojego programu jest to, że wymuszasz używanie pewnych elementów języka. Jeżeli chcesz wykorzystać daną wiedzę, to znajdź dla niej odpowiedni przypadek do rozwiązania, a nie na przykład wpychasz unię w łańcuch else if'ów.

EDIT: Ten kod można sprowadzić do takiej postaci:

C/C++
#include <iostream>
#include <fstream>
#include <limits>
#include <cctype>
#include <cstdlib>
#include <cstring>
using namespace std;

void cin_clearFlags( void );
char shiftHeight( char );
void clearArray( char * );
bool checkForChar( char *, char );

const int ArSize = 20;

int main() {
    fstream StorageIO( "storage.txt" );
    cout << "Dane wprowadzone z klawiatury zostana zapisane w pliku." << endl << "Zadecyduj teraz jaki typ danych bedziesz wprowadzac:"
    << endl << "1 - INT ( '0' aby zakonczyc )"
    << endl << "2 - FLOAT ( '0' aby zakonczyc )"
    << endl << "3 - CHAR ( '@' aby zakonczyc )" << endl;
    int choice = 0; //na 0 zeby zapobiec 'cudownemu' pojawieniu sie liczby od 1 do 3 w tym miejscu w pamieci za sprawa przebywajacych tam danych w danym czasie
    cin >> choice;
    while( choice < 1 || choice > 3 ) {
        cout << endl << "Nie ma takiej opcji !" << endl << "Sprobuj jeszcze raz:";
        cin >> choice;
    }
    union {
        int inputINT;
        float inputF;
        char inputCH;
    } keyboard;
    switch( choice ) {
    case 1: keyboard.inputINT = 1; break;
    case 2: keyboard.inputF = 1; break;
    case 3: keyboard.inputCH = 'a'; break;
    }
    cout << endl << "Mozesz teraz podawac dane:" << endl;
    if( int( 1 ) == keyboard.inputINT ) {
        int tempINT;
        cin >> tempINT;
        while( int( 0 ) != tempINT ) {
            if( cin ) {
                keyboard.inputINT = tempINT;
                StorageIO << keyboard.inputINT << endl;
            }
            else {
                cin_clearFlags();
            }
            cin >> tempINT;
        };
    }
    else if( float( 1 ) == keyboard.inputF ) {
        StorageIO.setf( std::ios_base::showpoint );
        float tempF;
        cin >> tempF;
        while( 0 != tempF ) {
            if( cin ) {
                keyboard.inputF = tempF;
                StorageIO << keyboard.inputF << endl;
            }
            else {
                cin_clearFlags();
            }
            cin >> tempF;
        }
    }
    else if( 'a' == keyboard.inputCH ) {
        char tempCH[ ArSize ];
        cout << "(Max. " << ArSize << " znakow na wejscie)\n";
        cin.getline( tempCH, ArSize );
        while( !checkForChar( tempCH, '@' ) ) {
            if( cin ) {
                for( int i = 0; i < ArSize; i++ ) {
                    keyboard.inputCH = shiftHeight( tempCH[ i ] );
                    if( keyboard.inputCH != '\n' ) {
                        StorageIO << keyboard.inputCH;
                    }
                }
                StorageIO << endl;
                clearArray( tempCH );
            }
            else {
                cin_clearFlags();
            }
            cin.getline( tempCH, ArSize );
        };
    }
    else {
        cout << "Cos poszlo nie tak! Zamykam program.";
        exit( EXIT_FAILURE );
    }
    StorageIO.close();
    return 0;
}

void cin_clearFlags() {
    cout << "Czyszcze flagi obiektu 'cin'.\n";
    cin.clear();
    cin.ignore( numeric_limits < streamsize >::max(), '\n' );
}

char shiftHeight( char ch ) {
    return islower( ch ) ? toupper( ch )
        : tolower( ch );
}

void clearArray( char * ch ) {
    for( int i = 0; i < ArSize; i++ ) {
        ch[ i ] = ' ';
    }
}

bool checkForChar( char * ch, char whatToFind ) {
    bool found = false;
    for( int i = 0; i < ArSize && !found; i++ ) {
        found =( ch[ i ] == whatToFind );
    };
    return found;
}

Z łańcuszkiem będziesz musiał radzić sobie sam...
P-164963
« 1 »
  Strona 1 z 1