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

Justowanie tekstu - konsola

Ostatnio zmodyfikowano 2014-03-02 11:42
Autor Wiadomość
Rafals
Temat założony przez niniejszego użytkownika
Justowanie tekstu - konsola
» 2014-02-06 11:00:30
Witam.
Na zaliczenie mam do napisania program:
"Zadanie polega na zmianie miejsc łamania linii oraz wstawieniu dodatkowych spacji w tekście
czytanym z pliku lub standardowego wejścia tak, żeby tekst był wyrównany do prawej i lewej
strony w jednej kolumnie o szerokości 80 znaków. W przypadku wprowadzania dodatkowych
spacji należy zadbać o równomierność, czyli zagwarantować że wolne przestrzenie pomiędzy
słowami w jednej linii nie różnią się więcej niż 1 spacją."

Już jeden pomysł chciałem i po części zrealizowałem, lecz zrezygnowałem, bo napotkałem pewien problem.
Obecnie mam dwa pomysły jak by to miało wyglądać.
1. Pobieram wiersz z pliku.
2. Sprawdzam 79 znak, jeżeli jest to litera, cofam się o jeden znak aż napotkam spację.
3. Wrzucam znak nowej linii, sprawdzam długość obecnego wiersza i liczę ilość wyrazów.
4. ilość wyrazów - 1 daje mi ile jest przerw.
5. Do każdej przerwy dodaję spację do momentu osiągnięcia żądanej długości wiersza.
6. Powtarzam całość od znaku 81 (bo 80 jest znakiem nowej linii).

To tak mniej więcej jak ja to widzę. Drugiego sposobu w sumie nie podaję, bo jak pisałem to kompletnie bez sensu się wydaje.
Jak macie jakieś inne sugestie, pomysły to z chęcią wysłucham.
Zabieram się za pisanie kodu.
Niebawem coś wrzucę.
P-104080
alixir
» 2014-02-06 14:55:24
Ogólnie nie mam w zwyczaju wykonywać za kogoś zadań, ale z czystej ciekawości napisałem sobie programik justujący. Jednak nalegałbym, abyś się nim nie sugerował, a raczej spróbował swoich sił.

C/C++
#include <string>
#include <iostream>

#define NUM_IN_ROW 50

std::string text_cut( std::string &, int &, int & );
void text_align( std::string & );

int main()
{
    std::string original_text;
    std::string result_line;
   
    /* Tekst zaczerpniety z ksiazki "Beginning C" Ivor Horton */
    original_text = "The process for developing a program in C may not be obvious if you've never written a program before. "
    "It's very similar to many other situations in life where it just isn't clear how you're going to achieve "
    "your objective when you first start out. Normally you begin with a rough idea of what you want to achieve, "
    "but you need to translate this into a more precise specification of what you want. Once you've reached this "
    "more precise specification, you can work out the series of steps that will lead to your final objective. "
    "Having the idea that you want to build a house just isn't enough. You need to know what kind of house you want, "
    "how large it's going to be, what kinds of materials you have to build it with, and where you want to build it. "
    "You will also want to know how long it's going to take and the likely cost. This kind of detailed planning is "
    "also necessary when you want to write a program. Let's go through the basic steps that you need to follow when "
    "you're writing a program. The house analogy is useful, so I'll work with it for a while.";
    int t_length = original_text.length();
   
    int start_pos = 0;
    int end_pos =(( start_pos + NUM_IN_ROW ) < t_length ) ?( start_pos + NUM_IN_ROW )
        : t_length;
    while( start_pos < end_pos ) {
        result_line = text_cut( original_text, start_pos, end_pos );
        text_align( result_line );
        end_pos =(( start_pos + NUM_IN_ROW ) < t_length ) ?( start_pos + NUM_IN_ROW )
            : t_length;
        std::cout << result_line << std::endl;
    }
   
    return 0;
}

std::string text_cut( std::string & txt, int & s_pos, int & e_pos ) {
    std::string buff;
   
    /* jesli koncowa pozycja wskazuje na koniec tekstu
        wczytujemy i zwracamy pozostaly tekst
        ustawiajac pozycje startowa na koniec tekstu */
    if( e_pos == txt.length() ) {
        buff.insert( 0, txt, s_pos, txt.length() - s_pos + 1 );
        s_pos = txt.length();
        return buff;
    }
   
    /* w innym przypadku wyszukujemy od koncowej pozycji znaku spacji,
        wczytujemy tekst do spacji, ustawiamy nowa wartosc startowa
        i zwracamy wczytany tekst */
    while( e_pos > s_pos ) {
        if( txt[ e_pos-- ] != ' ' )
             continue;
       
        break;
    }
    buff.insert( 0, txt, s_pos, e_pos - s_pos + 1 );
    s_pos = e_pos + 2;
   
    return buff;
}

void text_align( std::string & txt ) {
    /* do puki linia jest krotsza od wymaganej dodajemy spacje
        w kolejne wolne miejsca */
    int pos = 0;
    while( txt.length() < NUM_IN_ROW ) {
        if( txt[ pos++ ] == ' ' ) {
            txt.insert( pos, " ", 1 );
            pos++;
        }
        if( pos >= txt.length() )
             pos = 0;
       
    }
}
P-104092
Rafals
Temat założony przez niniejszego użytkownika
» 2014-02-06 16:01:15
Dzięki bardzo zaraz sobie przejrzę.
Zapomniałem dodać w pierwszym poście, że to jest 1 semestr podstaw programowania i max to tablice, funkcje, pętle, warunki, obsługa plików. W sumie to co jest w kursie na forum.
Widzę, że lepiej Ci poszło niż mi ;)
Właśnie swoją wersję ukończyłem. Kwestia jeszcze odporności na różne dziwne rzeczy w tekście, jak więcej spacji pomiędzy wyrazami, aby je usunąć i wyrównać.
Nigdy nie pomyślałem nawet, żeby pytać o napisanie kodu, bo mija się to z celem. W tym przypadku bardziej chodziło mi o ogólny opis, co i jak. Ale dzięki.
Trochę bajzlu jest, bo jeszcze nie sprzątałem. Później wrzucę uporządkowaną wersję.
C/C++
#include <iostream>
#include <fstream>
#include <string>
#define SZER 80
using namespace std;

int main()
{
    string wiersz, nazwa_pliku = "tekst.txt";
    ifstream plik;
    int n, i, k, ile_do_konca_wiersza, dlugosc_tekstu;
    plik.open( nazwa_pliku.c_str() );
   
    do
    {
        n = 1;
        k = - 1;
        dlugosc_tekstu = i = 0;
       
        getline( plik, wiersz );
        for(;; )
        {
            dlugosc_tekstu = wiersz.length();
            if( n > 1 )
                 k++;
           
            ile_do_konca_wiersza = 0;
            if( wiersz[ n * SZER + k ] != ' ' )
            {
                for( i = n * SZER + k;; i-- )
                {
                    ile_do_konca_wiersza++;
                    if( wiersz[ i ] == ' ' )
                    {
                        wiersz[ i ] = '\n';
                        break;
                    }
                }
            }
            else if( wiersz[ n * SZER + k ] == ' ' )
            {
                ile_do_konca_wiersza = 1;
                wiersz[ n * SZER + k ] = '\n';
            }
           
            for( int t =(( n - 1 ) * SZER ) + 1; t < n * SZER; t++ )
            {
                if( ile_do_konca_wiersza == 0 )
                     break;
               
                if( wiersz[ t ] == ' ' )
                {
                    wiersz.insert( t, " " );
                    ile_do_konca_wiersza--;
                    t++;
                }
            }
            n++;
            if( n * SZER > dlugosc_tekstu )
                 break;
           
        }
        cout << wiersz << endl;
        if( plik.eof() )
             break;
       
    } while( true );
   
    return 0;
}

Wstawiona wersja poprawiona, jeszcze zamierzam dodać zapis wyjustowanego tekstu do pliku i możliwość wpisywania tekstu w konsoli.
P-104106
alixir
» 2014-02-06 16:43:28
Osobiście twój kod mi nie działa poprawnie, choć jeszcze nie analizowałem całości kodu (jest dość zagmatwany :) ).

Mój kod też nie jest odporny na podwójne spacje, ale to żaden problem je usunąć. Wystarczy dodać kolejny moduł w postaci funkcji.
Wersja mojego program raczej nie wychodzi zakresem poza twoją specyfikację (no chyba że nie znasz referencji). Starałem się używać najprostszych mechanizmów.
P-104109
Rafals
Temat założony przez niniejszego użytkownika
» 2014-02-06 17:12:46
Co się dzieje jak uruchamiasz? W sensie wynik jest zły czy sypie się?
Bufor okna konsoli sprawdź.
P-104111
alixir
» 2014-02-06 17:15:53
Błędnie justuje. Dla przykładu wczytałem sobie dokładnie ten sam tekst co w moim przykładzie. Testowałem dla różnych szerokości pól.

Tu masz porównanie (z lewej justowanie twoim kodem, z prawej moim)
http://zapodaj.net​/def885d894ac9.png.html
P-104112
Rafals
Temat założony przez niniejszego użytkownika
» 2014-02-06 17:22:59
Hmm możesz wrzucić wynik do wglądu?
Domyślam się o co Ci chodzi. Spróbuj w txt wrzucić, zdanie po zdaniu w jednej linii.
P-104113
alixir
» 2014-02-06 17:26:37
Wczytywałem zarówno z pliku jak i z jego pominięciem - czyt. ze zmiennej typu string.
Z plikiem to ogólnie jest problem. Jeśli tekst nie jest w całości w jednej linii, to wygląd justowania jest bardzo nieładny.
W zasadzie justuje się poprawnie tylko pierwszy wczytany ciąg. Reszta zostaje przepisywana bez zmian.
W kolejnej linii tak samo. Pierwszy wczytany ciąg ok, reszta przepisana, itd.
Dodatkowo jeśli plik zawiera puste linie, to program się wysypuje.
P-104114
« 1 » 2
  Strona 1 z 2 Następna strona