[c]nowy wiersz, główna funkcja, linux
-
- Użytkownik
- Posty: 131
- Rejestracja: 4 wrz 2008, o 17:01
- Płeć: Mężczyzna
- Lokalizacja: Wrocław
- Podziękował: 33 razy
[c]nowy wiersz, główna funkcja, linux
Np. chce przerobić taki tekst:
Jeszcze tak przy okazji, jak zwykle czegoś nie wiem;] Otóż muszę jeszcze pododawać marginesy. I za nic nie mam pojęcia jak wstawić dodatkowe spacje na początku każdego wiersza... udaje mi się jedynie w pierwszym wierszu, a dalej nie chce nic ruszyć.
Chciałbym np. żeby jeden wiersz miał maksymalnie 20 znakówLitwo Ojczyzno moja ty jestes jak zdrowie Ile cie trzeba cenic ten tylko sie dowie Kto cie stracil
Dzis pieknosc twa w calej ozdobie Widze i opisuje bo tesknie po tobie Panno swieta co Jasnej bronisz Czestochowy I w Ostrej swiecisz Bramie Ty co grod zamkowy Nowogrodzki ochraniasz z jego wiernym ludem Jak mnie dziecko do zdrowia powrocilas cudem Gdy od placzacej matki pod Twoja opieke Ofiarowany martwa podnioslem powieke I zaraz moglem pieszo do Twych
Więcej niż 20 znaków mają miedzy innymi wersy:Litwo Ojczyzno moja
ty jestes jak
zdrowie Ile cie trzeba
cenic ten tylko sie
dowie Kto cie stracil
Dzis pieknosc twa w
calej ozdobie Widze
i opisuje bo tesknie
po tobie Panno
swieta co Jasnej bronisz
Czestochowy I w
Ostrej swiecisz Bramie
Ty co grod zamkowy
Nowogrodzki
ochraniasz z jego wiernym
ludem Jak mnie dziecko
do zdrowia
powrocilas cudem Gdy od
placzacej matki pod
Twoja opieke Ofiarowany
martwa podnioslem
powieke I zaraz moglem
pieszo do Twych
Może coś nie tak mam z kodem, jeśli tak to mnie skarćcie:swieta co Jasnej bronisz
ochraniasz z jego wiernym
powrocilas cudem Gdy od
Kod: Zaznacz cały
void newline(char zdanie[], int miejsce)
{
int spacja=-1;
int i=0;
int dlugosc=strlen(zdanie);
for(i=0; i<dlugosc; ++i)
{
if(zdanie[i]==' ')
spacja=i;
if((i % miejsce)==0 && zdanie[i]!='\n')
{
zdanie[spacja]='\n';
}
}
}
- Sokół
- Użytkownik
- Posty: 451
- Rejestracja: 17 wrz 2006, o 19:22
- Płeć: Mężczyzna
- Lokalizacja: Zielona Góra
- Podziękował: 15 razy
- Pomógł: 55 razy
[c]nowy wiersz, główna funkcja, linux
Ok, to już wiadomo co jest nie tak.
Załóżmy, że pętla leci od początku, na 15 pozycji jest spacja, a dalej wyraz, który kończy się na 23-tej pozycji. Program wstawi enter na 16 pozycji. Następnie w tekście jest kilka zwykłych wyrazów, z czego jeden kończy się na 39 pozycji (czyli na miejscu 40 jest spacja). Program wstawi więc enter w miejsce ostatniej spacji przed lub w miejsce, znaku o pozycji 40, czyli na miejscu 40. W rezultacie, drugi wiersz ma ponad 20 znaków (od 17 pozycji do 40 - ze znakiem nowej linii).
Jeśli w wersie ma być maks 20 znaków, to w pętli for dodaj zmienną licznik, która na początku będzie miała wartość 0. Inkrementuj ją wraz z każdym kolejnym przebiegiem pętli i w samej pętli napisz warunek, że kiedy licznik będzie równy maks. ilości znaków w wersie, to ma postawić znak nowej linii w ostatniej spacji, a samą zmienną licznik wyzerować. Po takiej operacji znowu będzie odliczała znaki, od ostatniego znaku nowej linii, aż do osiągnięcia wartości maks. znaków wersie, wtedy znowu nastąpi wpisanie entera i wyzerowanie licznika. Zabezpiecz odpowiednio się w razie występowania długich wyrazów, tzn. żeby nie było sytuacji, że dwa razy enter w tym samym miejscu albo coś. Niech wtedy jakoś przenosi ten wyraz, nie wiem jakie rozwiązanie przewidujesz
Co do marginesów, jak to nazywasz, zobacz jakie w C są operacje na stałych znakowych, tzn. kopiowanie jednej do drugiej etc. Stwórz stringa wynikowego, gdzie będziesz dodawał każdy wers już w wersji finalnej (ze spacjami). Kiedy podzielisz tekst na wersy, możesz pętlą sprawdzać ile znaków znajduje się w takim wersie, zobacz ile spacji brakuje na początku (bo rozumiem, że wiersz ma być uzupełniany spacjami, tak żeby ostatecznie było 20 znaków?) i dopisz tyle spacji do stringu wynikowego, a następnie przekopiuj cały wiersz. Nie ukrywam, że wskaźniki byłyby bardzo pomocne, mógłbyś kopiować stringi precyzyjnie od danego miejsca do danego miejsca, w odpowiednie miejsce w pamięci.
Załóżmy, że pętla leci od początku, na 15 pozycji jest spacja, a dalej wyraz, który kończy się na 23-tej pozycji. Program wstawi enter na 16 pozycji. Następnie w tekście jest kilka zwykłych wyrazów, z czego jeden kończy się na 39 pozycji (czyli na miejscu 40 jest spacja). Program wstawi więc enter w miejsce ostatniej spacji przed lub w miejsce, znaku o pozycji 40, czyli na miejscu 40. W rezultacie, drugi wiersz ma ponad 20 znaków (od 17 pozycji do 40 - ze znakiem nowej linii).
Jeśli w wersie ma być maks 20 znaków, to w pętli for dodaj zmienną licznik, która na początku będzie miała wartość 0. Inkrementuj ją wraz z każdym kolejnym przebiegiem pętli i w samej pętli napisz warunek, że kiedy licznik będzie równy maks. ilości znaków w wersie, to ma postawić znak nowej linii w ostatniej spacji, a samą zmienną licznik wyzerować. Po takiej operacji znowu będzie odliczała znaki, od ostatniego znaku nowej linii, aż do osiągnięcia wartości maks. znaków wersie, wtedy znowu nastąpi wpisanie entera i wyzerowanie licznika. Zabezpiecz odpowiednio się w razie występowania długich wyrazów, tzn. żeby nie było sytuacji, że dwa razy enter w tym samym miejscu albo coś. Niech wtedy jakoś przenosi ten wyraz, nie wiem jakie rozwiązanie przewidujesz
Co do marginesów, jak to nazywasz, zobacz jakie w C są operacje na stałych znakowych, tzn. kopiowanie jednej do drugiej etc. Stwórz stringa wynikowego, gdzie będziesz dodawał każdy wers już w wersji finalnej (ze spacjami). Kiedy podzielisz tekst na wersy, możesz pętlą sprawdzać ile znaków znajduje się w takim wersie, zobacz ile spacji brakuje na początku (bo rozumiem, że wiersz ma być uzupełniany spacjami, tak żeby ostatecznie było 20 znaków?) i dopisz tyle spacji do stringu wynikowego, a następnie przekopiuj cały wiersz. Nie ukrywam, że wskaźniki byłyby bardzo pomocne, mógłbyś kopiować stringi precyzyjnie od danego miejsca do danego miejsca, w odpowiednie miejsce w pamięci.
-
- Użytkownik
- Posty: 131
- Rejestracja: 4 wrz 2008, o 17:01
- Płeć: Mężczyzna
- Lokalizacja: Wrocław
- Podziękował: 33 razy
[c]nowy wiersz, główna funkcja, linux
Ale mi to coś ciężko wchodzi. Sposób Twój jest opisany bardzo zrozumiale. Wiem o co chodzi, ale jeśli już mam przenieść to na C, to mam ogromne problemy. No ale do rzeczy. Funkcja, która stworzyłem na podstawie Twoich rad wygląda następująco:
Nie dostosowałem się dokładnie tak jak napisałeś, bo nie wiedziałem jak licznik ma inkrementować będąc zadeklarowany w pętli. Ale jak na to patrze co napisałem to powinno być już dobrze, ale niestety działa tak jak poprzednio.
EDIT:
Już wiem, czemu działa tak samo jak poprzednio. Po prostu j=0, ale znów liczy od miejsce, a nie od ostatniej spacji. Próbowałem podstawić (spacja=j)==0; ale wtedy tylko w pierwszej linijce robi się znak nowej linii, dalej nie leci.
Kod: Zaznacz cały
void newline(char zdanie[], int miejsce)
{
int spacja=-1;
int i=0;
int dlugosc=strlen(zdanie);
int j=0;
for(i=0; i<dlugosc; ++i,++j)
{
if(zdanie[i]==' ')
{
spacja=i;
}
if(j==miejsce)
{
zdanie[spacja]='\n';
j=0;
}
}
}
EDIT:
Już wiem, czemu działa tak samo jak poprzednio. Po prostu j=0, ale znów liczy od miejsce, a nie od ostatniej spacji. Próbowałem podstawić (spacja=j)==0; ale wtedy tylko w pierwszej linijce robi się znak nowej linii, dalej nie leci.
- Sokół
- Użytkownik
- Posty: 451
- Rejestracja: 17 wrz 2006, o 19:22
- Płeć: Mężczyzna
- Lokalizacja: Zielona Góra
- Podziękował: 15 razy
- Pomógł: 55 razy
[c]nowy wiersz, główna funkcja, linux
Rzeczywiście, bo j=0 jest w warunku kiedy j==miejsce, a za pierwszym razem ten warunek zachodzi, kiedy 'i' równe jest maksymalnej ilości znaków w wersie.
Zamiast zmieniać j wartością 0 w pętli for, napisz:
bo dla pewnego j==miejsce, na -tej pozycji może być jakiś znak, czyli jeszcze jakieś słowo. Ostatnia spacja jest kilka pozycji przed -tą, więc nie ma sensu wtedy ustawiać wartość zmiennej j na 0, wtedy nie będzie liczyć ile znaków temu była spacja. Zapisując j=i-spacja uwzględniasz, że przed i po -tej pozycji jest słowo, które będzie w nowej linii. Przeanalizuj na kartce albo w debugerze jak to zachodzi dla dwóch pierwszych wersów inwokacji.
Zamiast zmieniać j wartością 0 w pętli for, napisz:
Kod: Zaznacz cały
j=i-spacja
-
- Użytkownik
- Posty: 131
- Rejestracja: 4 wrz 2008, o 17:01
- Płeć: Mężczyzna
- Lokalizacja: Wrocław
- Podziękował: 33 razy
[c]nowy wiersz, główna funkcja, linux
Dzięki wielkie;] Masz u mnie zgrzewkę piwa:) Rozumiem całkowicie algorytm. Jeszcze "tylko" dodanie spacji i margines. Ciężka noc przede mną.
EDIT: Właśnie znalazłem tekst na którym bedzie sprawdzany ten program. Jest to słownik mający 230tys. słów i program na nim w ogóle nie działa... tak jakby robił i robił i nic sie nie dzieje.
EDIT: Właśnie znalazłem tekst na którym bedzie sprawdzany ten program. Jest to słownik mający 230tys. słów i program na nim w ogóle nie działa... tak jakby robił i robił i nic sie nie dzieje.
- Sokół
- Użytkownik
- Posty: 451
- Rejestracja: 17 wrz 2006, o 19:22
- Płeć: Mężczyzna
- Lokalizacja: Zielona Góra
- Podziękował: 15 razy
- Pomógł: 55 razy
[c]nowy wiersz, główna funkcja, linux
Te 230k słów to spory kawałek pamięci, a u siebie masz tablicę na 1000 znaków (#define MAX 1000). W jaki sposób wczytujesz dane? Być może jest problem z zarządzaniem pamięcią, program wykrzacza się czy po prostu nic się nie dzieje? Spróbuj pododawać instrukcje w kodzie, które pozwolą zobaczyć gdzie tkwi błąd, tzn. czy program w ogóle przechodzi funkcję getline? Jak wygląda plik ze słownikiem? Pokaż też cały kod, po przeróbkach.
Może warto wczytywać plik w którąś z opisanych metod tutaj: ... lik%C3%B3w?
Może warto wczytywać plik w którąś z opisanych metod tutaj: ... lik%C3%B3w?
-
- Użytkownik
- Posty: 131
- Rejestracja: 4 wrz 2008, o 17:01
- Płeć: Mężczyzna
- Lokalizacja: Wrocław
- Podziękował: 33 razy
[c]nowy wiersz, główna funkcja, linux
aj. Kiedy starałem się dodać marginesy, sądziłem że właśnie przez getline mi nie działa i w main zrobiłem osobną funkcję, która pobierała te krótkie teksty, potem już zapomniałem o niej i korzystając z niej próbowałem uruchomić ten program na tym słowniku, przez co nie działało. Zmieniając z powrotem na funkcje getline działa. A już się przeraziłem;]
Nie wiem czemu robi mi tylko do literki i. Dalej program nie działa. Tak jakby tablica była za mała. Dałem na 1 000 000. Jak daje o jedno zero więcej to już mam naruszenie pamięci:
Oto mój kod:
funkcja przesuń dopiero będzie w użyciu w dodawaniu spacji, jeśli mi się uda coś wymyślić.
debugger coś wykrywa, ale nie umiem jeszcze w pełni z tego korzystać. Czas mnie nagli, w czwartek muszę to oddać, więc tylko siedzę nad tym prostym programem.
Valgrind się nazywa ten debugger, sprawdza wycieki pamięci, ale nic z tego nie rozumiem;]
No nic. Łudzę się, że prowadzący nie będzie sprawdzał całego wyniku, w końcu to 230 tys słów;] Zastanawiam się jak pobierać każdy wers i sprawdzać czy ma odpowiednia długość. Jeśli nie ma odpowiedniej długość to ma dodać spacje.
Nie wiem czemu robi mi tylko do literki i. Dalej program nie działa. Tak jakby tablica była za mała. Dałem na 1 000 000. Jak daje o jedno zero więcej to już mam naruszenie pamięci:
Oto mój kod:
Kod: Zaznacz cały
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 1000000
void usun(char zdanie[])
{
int i;
char znak = '\n';
int dlugosc = strlen(zdanie);
for(i=0;i<dlugosc-1;++i)
if(zdanie[i]==znak)
{
zdanie[i]=' ';
}
}
void newline(char zdanie[], int miejsce)
{
int spacja=-1;
int i=0;
int dlugosc=strlen(zdanie);
int j=0;
for(i=0; i<dlugosc; ++i,++j)
{
if(zdanie[i]==' ')
{
spacja=i;
}
if(j==miejsce)
{
zdanie[spacja]='\n';
j=i-spacja;
}
}
}
void przesun(char zdanie[], int miejsce, char znak){
int i;
int dlugosc = strlen(zdanie);
for(miejsce; dlugosc >= miejsce; dlugosc--){
i = dlugosc + 1;
zdanie[i] = zdanie[dlugosc];
}
zdanie[miejsce] = znak;
}
void getline(char zdanie[], int lim)
{
int c,i;
for(i = 0;i<lim-1 && (c=getchar())!=EOF;i++)
zdanie[i]=c;
zdanie[i]='\0';
}
int main( int argc, char* argv[] )
{
int i=0;
int c;
char zdanie[MAX];
int miejsce = atoi(argv[1]);
getline(zdanie,MAX);
usun(zdanie);
newline(zdanie,miejsce);
printf("%s",zdanie);
return 0;
}
debugger coś wykrywa, ale nie umiem jeszcze w pełni z tego korzystać. Czas mnie nagli, w czwartek muszę to oddać, więc tylko siedzę nad tym prostym programem.
Valgrind się nazywa ten debugger, sprawdza wycieki pamięci, ale nic z tego nie rozumiem;]
No nic. Łudzę się, że prowadzący nie będzie sprawdzał całego wyniku, w końcu to 230 tys słów;] Zastanawiam się jak pobierać każdy wers i sprawdzać czy ma odpowiednia długość. Jeśli nie ma odpowiedniej długość to ma dodać spacje.