Program
Benny: Mam taką wskazówkę:
Warto utożsamić nawias ( z liczbą 1 oraz ) z liczbą −1.
Jak mam utożsamić znak z liczbą?
23 lip 15:04
jc: Do czego to jest wskazówka?
23 lip 15:11
Benny: Mam napisać pewien program, który sprawdza wyrażenia nawiasowe.
Wyrażeniem nawiasowym nazywamy niepusty ciąg składający się z nawiasów otwierających i
zamykających. Powiemy, że wyrażenie nawiasowe jest poprawne, jeżeli każdy nawias otwierający
można sparować z nawiasem zamykającym, występującym po nim, tak aby ciąg nawiasów znajdujących
się pomiędzy nimi był poprawnym ciągiem nawiasowym. Na przykład (()())() jest poprawnym
wyrażeniem nawiasowym, ale )( i ()( już nie są poprawne. Innymi słowy poprawne wyrażenie
nawiasowe ma tyle samo nawiasów otwierających co zamykających oraz licząc od początku
wyrażenia nawiasowego, liczba nawiasów otwierających jest cały czas nie mniejsza od liczby
nawiasów zamykających. Napisz program, który poprosi użytkownika o wprowadzenie ciągu
nawiasów, a następnie wszystkie poprawne wyrażenia nawiasowe utworzone z podanego ciągu
wypisze do pliku o nazwie nawiasy.txt, tak aby wybrane wyrażenie nawiasowe było wydzielone
znakiem |.
Dla przykładu (()())() plik nawiasy.txt będzie wyglądał np. tak (kolejność wypisywanych
wyrażeniem nawiasowym nie ma znaczenia):
(|()|())()
(()|()|)()
(()())|()|
(|()()|)()
|(()())|()
|(()())()|
wsk1. Warto utożsamić nawias ( z liczbą 1 oraz ) z liczbą −1.
23 lip 15:31
jc: Kto to pisał? Czy jesteś w stanie czytać tak okropny tekst? Ja czuję jakiś ucisk w brzuchu.
O co tu chodzi?
Napisz program, który poprosi użytkownika o wprowadzenie ciągu nawiasów, a następnie wszystkie
poprawne wyrażenia nawiasowe utworzone z podanego ciągu wypisze do pliku o nazwie nawiasy.txt,
tak aby wybrane wyrażenie nawiasowe było wydzielone znakiem |.
23 lip 15:59
Benny: To pisał pewien prowadzący na AGH−u.
23 lip 16:04
Benny: Coś z tym się da zrobić?
23 lip 16:51
jc: Spojrzałem na przykład. Myślę, że trzeba w danym ciągu nawiasów, należy na wszelkie
możliwe sposoby postawić pionowe kreski tak, aby nawiasy pomiędzy kreskami tworzyły
poprawny schemat.
Poradzisz sobie, zadanie nie jest trudne.
Faktycznie wygodnie przetłumaczyć ciąg nawiasów na ciąg z łożony z liczb 1, −1:
( → +1
) → −1.
23 lip 16:54
jc: Nie skasowałem słowa.
Spojrzałem na przykład. Myślę, że w danym ciągu nawiasów, należy na wszelkie możliwe sposoby
postawić pionowe kreski tak, aby nawiasy pomiędzy kreskami tworzyły poprawny schemat.
Powtórzę, pomyśl sam, na pewno sobie poradzisz
23 lip 17:00
Benny: Nie rozumiem tego utożsamienia. Mam zrobić podstawienie?
23 lip 17:05
jc: Chodzi o to, że dla prawidłowego rozstawienia nawiasów, na każdym etapie
suma początkowych znaków jest liczbą nieujemną.
Przykład
((()())())
+ + + − + − − + − −
1 2 3 2 3 2 1 2 1 0
23 lip 17:25
Benny: Jak mam wczytywać z konsoli te nawiasy, aby sprawdzić czy jest to ) czy (?
23 lip 17:43
jc: Najpier przetestuj. Wpisz dane na stałe.
char we [ ] = "((()())())"; // to mozesz latwo zmienic
Jak juz program bedzie dzialal, pomyslisz, jak wczytywac.
Nie musisz zamieniać nawiasów na +/−.
Po prostu będziesz w programie pisał
if( we[ i ] == '(' )
s ++;
else if( we[ i ] == ')' )
s −−;
else
jakies bledne dane;
Czy coś podobnego
23 lip 17:54
Benny: Z tym ifem to tak chciałem zrobić tylko zastanowiło mnie to wczytywanie.
23 lip 17:56
Benny: Tylko z tą tablicą jest kłopot. Muszę określić jej długość.
23 lip 17:58
Benny: char tab[100];
printf("Podaj ciąg nawiasów");
scanf("%s", tab[100]);
printf("%s", tab[100]);
Czemu po wpisaniu czegokolwiek nie wyświetla mi tego tylko wyskakuje mi błąd?
23 lip 18:07
jc: tab[100] oznacza 100 wyraz tablicy. Wpisz samo słowo tab
tab oznacza adres początku tablicy.
23 lip 18:10
jc: Oczywiście w deklaracji musi być 100.
char tab[100];
23 lip 18:10
Benny: char tab[100];
printf("Podaj ciąg nawiasów");
scanf("%s", tab);
printf("%s", tab);
tak jest ok
tab[100] musi być, bo muszę określić rozmiar tej tablicy. Jak mam niby zdefiniować nieskończoną
tablicę?
23 lip 18:13
jc: Tak, w deklaracji musi być tab[100]
23 lip 18:17
Benny: Dodatkowo trzeba dać warunek, aby przy s<0 wychodziło z programu.
23 lip 18:21
Benny: Jak możesz to sprawdź tą część. Na razie wydaje mi się że wszystko ok wyświetla.
23 lip 18:23
Benny: #include<stdio.h>
#include<string.h>
main()
{
char tab[100];
int s=0;
printf("Podaj ciąg nawiasów\n");
scanf("%s", tab);
for(int i=0; i<strlen(tab);i++)
{
if(tab[i]=='(')
s++;
else
{
if(tab[i]==')')
s−−;
else return 0;
}
if(s<0)
break;
}
if(s==0)
printf("%s", tab);
else
printf("Wyrażenie nawiasowe nie jest poprawne");
return 0;
}
23 lip 18:23
jc: Napisz tak:
if(tab[i]=='(')
s++;
else if(tab[i]==')')
s−−;
else
return 0;
To jest to samo, ale czytelniej
23 lip 18:27
Benny: Przyzwyczaiłem się dawać więcej nawiasów niż mniej, bo zawsze coś mi umykało
23 lip 18:29
23 lip 22:07
Benny: b, wiem, że napis może być dłuższy niż 100 znaków, lecz nie wiem jak zadeklarować
nieskończoną tablicę. Mój angielski nie jest na dobrym poziomie i nie rozumiem w większości
tych publikacji.
24 lip 01:53
jc: Benny, tym się nie przejmuj. Ryzyko istnieje, kiedy program ma uprawnienia administratora,
a z komputera korzystają obcy użytkownicy.
fgets() czyta linię, ale nie więcej niż dana liczba znaków.
Potem czytasz z tablicy funkcją sscanf().
24 lip 08:23
asdf: Benny, angielski jest równie istotny dla programisty jak umiejętność programowania, really
W
prosty sposób możesz się go uczyć − czytając / oglądając tutoriale po angielsku
Nie szukaj
niczego po polsku...to jest droga przez mękę, po 2) i tak nie znajdzeisz za wiele.
24 lip 10:49
Benny: Ja nie jestem programistą
24 lip 10:56
Dziadek Mróz:
Użyj stosu
24 lip 12:28
Dziadek Mróz:
typedef struct Elem
{
char nawias;
} Elem;
typedef struct Stack
{
Elem *first;
Elem *next;
} Stack;
void push(Stack *stack);
void pop(Stack *stack);
Elem *top(Stack *stack);
24 lip 12:33
Benny: Nie miałem czegoś takiego.
24 lip 13:44
asdf: Benny, raczej chodziło mi o to, że jak chcesz uczyć się programowania to przy okazji DOBRZE
JEST znac angielski.
Co do zadania − zrobiłbym to przez rekurencję.
24 lip 14:19
Benny: Jak?
24 lip 14:23
Programista: Ciąg nawiasów od pozycji l...r jest poprawny, jeżeli:
al ≥ 0
al + al+1 ≥ 0
...
al + al+1 + ... + ar−1 ≥ 0
al + al+1 + ... + ar = 0 (tak, równa się)
przy czym "a" to ciąg, w którym ai jest równe 1 jeżeli i'ty znak to ( a −1 jeżeli ). Stąd
sprawdź wszystkie możliwe pary (l, r) gdzie l < r (jest ich O(n2), n to liczba nawiasów), i
jeżeli odpowiadają poprawnemu nawiasowaniu przepisz je do pliku. Pesymistyczna złożoność
wynosi O(n3), jednak nie da się dostać lepszej, dla nawiasów ()()()...() mamy O(n2)
poprawnych nawiasowań, więc przepisując je wszystkie do pliku dostajemy O(n3).
24 lip 14:48
Dziadek Mróz:
Rozkminiłem ale dopiero pod Pythonem, nie babrałem się w C, to już tam kwestia konwersji:
http://ideone.com/9v8BVq
25 lip 08:40
Programista: W takim razie trzymaj mój kod z zaimplementowanym algorytmem o którym pisałem (kod w C++,
jeżeli potrzebujesz w C łatwo przerobisz
). Program na standardowe wejście przyjmuje ciąg
nawiasów, wynik jego działania jest w pliku ,,result.txt".
http://pastebin.com/GpxuhMzV
25 lip 11:00
27 lip 11:56
Benny: Dzięki bardzo, ale jakoś bardzo skomplikowane jak dla mnie
27 lip 20:12
Dziadek Mróz: a gdzie tam, pętla podwójna na napisie generujące wszystkie możliwe podciągi, funkcja
sprawdzająca te podciągi i pętla zapisująca do pliku
27 lip 23:35
Benny: typedef enum
{
false, // domyslnie = 0
true // = 1
} bool;
Typ bool zwraca 0 lub 1 to wiem, ale nie rozumiem co to jest.
Czy to co ja pisałem da się jakoś pociągnąć dalej?
28 lip 12:25
jc: Benny, nie zawracaj sobie głowy czymś takim.
W języku C wielkość różna od zera oznacza prawdę, a zero fałsz.
Są jednak sytuacje, gdzie wyliczenia bardzo rozjaśniają kod.
28 lip 16:52