C
Benny: Napisz funkcję o nazwie wykreślanka, której parametrami będą dwa słowa co najwyżej 30−literowe:
slowo1 i slowo2, która zwraca 1, jeśli w slowo1 da sie wykreślić niektóre litery, tak aby
pozostałe litery(bez zmiany ich kolejności) tworzyły slowo 2 i wraca 0 w przeciwnym wypadku.
Np. po wykreśleniu ze słowa INFORMATYKA liter: N, F, O, M, T, Y, A da się otrzymać słowo IRAK.
Wskazówka: zauważ, że jeśli potraktujemy słowa jak ciągi, to slowo2 jest podciągiem slowo1.
23 cze 18:43
Saizou :
ja bym to zrobił w tablicy i porównywał elementy tablic
23 cze 19:35
jc: Opisz algorytm, a potem zapisz w wymaganym języku (pewnie C, jak poprzednio)
−−−−−
#include<stdio>
int wykreslanka(char slowo1 [ ], char slowo2 [ ] ){
// miejsce na Twoje dzieło
}
int main(){
printf("%d\n", wykreslanka("informatyka", "irak") );
}
23 cze 19:54
Benny: Udało się. Nie wiedziałem, gdzie mam błąd. W końcu okazało się że w mainie nie deklarowałem
długości tablicy
23 cze 19:56
Benny: jc mógłbyś sprawdzić czy czegoś nie brakuje?
#include<stdio.h>
#include<string.h>
#include<conio.h>
int wykreslanka(char slowo1[30], char slowo2[30])
{
int i=0;
int licznik=0;
for(i=0; i<strlen(slowo2); i++)
{
for(int j=0; j<strlen(slowo1); j++)
{
if(slowo2[i]==slowo1[j])
{
licznik ++;
break;
}
}
}
if(licznik==strlen(slowo2))
return 1;
return 0;
}
main()
{
char slowo1[30], slowo2[30];
printf("Podaj slowo pierwsze:");
scanf("%s", &slowo1);
printf("Podaj slowo drugie:");
scanf("%s", &slowo2);
if(wykreslanka(slowo1,slowo2)==1)
printf("Slowo drugie jest wykreslanka");
printf("Slowo drugie nie jest wykreslanka");
getch();
}
23 cze 19:57
jc: Drobna uwaga. Nie rozciągj tak tekstu bo trudno się czyta.
Oj, coś mi się zdaje, że źle to działa ... (mój program działa, zaraz skomiluję Twój).
23 cze 20:10
jc: To ma być C, czy C++ ?
Kompilacja nie powiodła się
23 cze 20:15
jc: slowo jest już adresem, więc npais &slowo jest błędem.
23 cze 20:23
jc:
Proponuję cos takiego. Będzisz mógł wielokrotnie wpisywać dane.
Wyjdzisz z programu wpisując pojedynczą literę.
I nie dopisuje tego getch(). To na pradwę nie potrzebne.
Program konsolowy uruchamiasz w konsoli i po problemie!
−−−−
int main() {
char slowo1[30], slowo2[30];
while(1){
printf("Podaj slowo pierwsze:");
scanf("%s", slowo1);
if(strlen(slowo1)==1) return 0;
printf("Podaj slowo drugie:");
scanf("%s", slowo2);
printf("%d\n", wykreslanka(slowo1,slowo2));
}
return 0;
}
23 cze 20:36
Benny: Dzięki, tylko powiedz czemu moja wersja u mnie działa. No i oczywiście piszę w C.
23 cze 21:18
Benny: No i kiedy mam dawać & a kiedy nie?
23 cze 21:22
jc: Może kompilujesz jako c++ ? Chodzi o drobiazg: for(int i; ; )
Jakiego kompilatora używasz ?
& liczba jest adresem zmiennej o nazwie liczba.
Aby funkcja scanf() mogła coś umieścić w zmiennej, należy przekazać jej adres zmiennej.
Nazwa tablicy sama jest adresem − adresem początku tablicy.
23 cze 21:38
Benny: Używam deva
23 cze 21:55
jc: Pewnie wydajesz polecenie g++ zamiast gcc (wiem, robi to za Ciebie system).
Teraz rozumiem, po co Ci getch( ). Po prostu uruchamiasz progrma przyciskiem
w systemie dev, a nie poleceniem.
23 cze 22:36
Benny: Ty kompilujesz program i dopiero później odpalasz go przez wiersz poleceń?
23 cze 23:24
jc: Używam Geany. Ostatnio bardzo rzadko zdarza mi się kompilować,
Najczęściej używam pythona.
Konsola (terminal, wiersz poleceń) pozwala na coś takiego
program < dane > wyniki
program zamiast z klawiatury czyta z pliku dane, a wynik umieszcza w pliku wyniki.
W takiej sytacji dodatkowe pytania zadwane przez program czy też oczekiwanie
na przyciśnięcie klawisza przeszkadzają.
Tylko kilka razy napisałem program, który sam tworzył pliki (ale za to dużo!).
24 cze 00:08
Benny: Mam teraz napisać program, który wczyta wpisane przez użytkownika slowo1 a następnie wypisze na
ekranie wszystkie takie słowa(każde słowo w innym wierszu) ze slownik.txt, które dadzą się
otrzymać ze slowo1 poprzez wykreślenie niektórych liter. Trzeba wykorzystać tą funkcję co
napisałem powyżej. W tym pliku slownik.txt w każdym wierszu znajduje się jedno słowo.
24 cze 09:25
jc: Zaproponowałbym coś takiego (zmieniasz u siebie tylko main):
−−−
int main(int argc, char * argv[]){
char slowo[30];
if(argc != 2) return 1;
while( scanf("%s", slowo) != EOF )
if(wykreslanka(argv[1], slowo)) printf("%s\n", slowo);
return 0;
}
−−−
Uruchamiasz wydając komendę:
wyliczanka informatyka < slownik.txt > wyjscie.txt
Program wyliczanka umieści w pliku wyjscie.txt te słowa ze słownika.txt,
które można uzyskać wykreslając litery w słowie informatyka.
24 cze 10:18
Benny: Właśnie on ma to na ekranie wypisać. Nie rozumiem w ogóle tego programu i maina.
24 cze 10:19
jc: Jak napiszesz
wyliczanka informatyka < slownik.tx
to wypisze na ekranie. Sprawdź!
A potem napisz program, który spyta Cię o słowo, potem o nazwę pliku
ze słownikiem, otworzy plik, napisze wynik na ekranie. Będzie to jednak program mniej
wygodny w obsłudze.
Czy nie pisałeś komend z argumentami? np. gcc wyliczanka.c −o wyliczanka
24 cze 10:31
Benny: Nie wydaje mi się
24 cze 10:39
jc: Co Ci się nie wydaje?
Zapewne chciałes mieć coś takiego:
−−−−−
int main(){
char we[30];
scanf("%s", we);
FILE *f;
f=fopen("slownik.txt", "r");
while( fscanf("%s", slowo) != EOF)
if(wykreslanka(we, slowo)) printf("%s\n", slowo);
fclose(f);
return 0;
}
24 cze 10:41
Benny: co to jest slowo?
24 cze 10:48
jc: A teraz?
int main(){
char slowo1[30], slowo2[30];
scanf("%s", slowo1);
FILE *f;
f=fopen("slownik.txt", "r");
while( fscanf("%s", slowo2) != EOF)
if(wykreslanka(slowo1, slowo2)) printf("%s\n", slowo2);
fclose(f);
return 0;
}
24 cze 10:52
Benny: Nie rozumiem tej pętli.
24 cze 10:57
jc:
Czytsz słowo. Może się nie udać. Jeśli plik się skończył, wychodzisz z pętli.
Jeśli się udało odczytać słowo, to zostanie ono zapamiętane w zmiennej slowo2.
Sprawdzasz, czy słowo2 można utworzyć ze słowa1.
Jeśli tak, to piszesz słowo2 i przechodzisz do nowej linii.
Wracasz na początek pętli.
24 cze 11:21
Benny: No właśnie coś nie chciało działać. Spróbowałem tak, ale po wpisaniu słowa do terminala od razu
wyskakuje "skonczylem".
char slowo1[30], slowo2[30];
scanf("%s", slowo1);
FILE *f;
f=fopen("slownik.txt", "r");
while(!feof(f))
{ fscanf(f, "%s", slowo2);
if(wykreslanka(slowo1, slowo2)==1)
printf("%s\n", slowo2);
}
fclose(f);
printf("skonczylem");
getch();
24 cze 11:23
jc: Nie działało, bo nie wpisałem pierwszego argumentu do funkcji fscanf().
Dziwne, że się skompilowało. Nie powinno! Jaką komendę wydajesz w celu kompilacji?
Mimo wszystko proponuję pisać tak, jak pisali klasycy C (twórcy!)
int main(){
char slowo1[30], slowo2[30];
scanf("%s", slowo1);
FILE *f;
f=fopen("slownik.txt", "r");
while( fscanf(f, "%s", slowo2) != EOF)
if(wykreslanka(slowo1, slowo2)) printf("%s\n", slowo2);
fclose(f);
return 0;
}
24 cze 11:36
jc: A może inaczej: z jakim rozszerzeniem tworzysz pliki?
24 cze 11:59
Benny: cpp
24 cze 12:14
jc: Jeśli chcesz sprawdzać zgodność z C, pisz rozszerzenie c, choć wybór cpp nie jest zły.
Najlepiej pisz tak, jak zaproponowano na zajęciach.
Sprawdziłem, kompilator c++ też jest zły na brak litery f!
24 cze 12:25
Benny: To co napisałeś powinno działać?
24 cze 12:26
jc: Przecież to to samo, co Ty napisałeś, tylko ja zgodnie z książka piszę
while( fscanf(f, "%s", slowo2) != EOF)
if(wykreslanka(slowo1, slowo2)) printf("%s\n", slowo2);
a Ty rozdzielasz na dwie instukcje
while(!feof(f)) {
fscanf(f, "%s", slowo2);
if(wykreslanka(slowo1, slowo2)==1) printf("%s\n", slowo2);
}
Poza tym pytasz, czy wykreślanka równa jest jeden. Naturalniejsze jest pytanie,
czy udało się wykreślić, czyli bez tego ==1. Lepiej się czyta.
24 cze 12:35
Benny: Tylko coś mi to nie chce działać.
24 cze 12:40
jc: Niemożliwe, oto cały mój program. Sprawdź
−−−
#include<stdio.h>
int wykreslanka(char slowo1[], char slowo2[]){
int i;
int j = 0;
for(i = 0; slowo2[i]; i++){
while( slowo1[j] && slowo2[i] != slowo1[j]) j++;
if( slowo1[j]==0 ) return 0;
j ++;
}
return 1;
}
int main(){
char slowo1[30], slowo2[30];
scanf("%s", slowo1);
FILE *f;
f=fopen("slownik.txt", "r");
while( fscanf(f, "%s", slowo2) != EOF)
if(wykreslanka(slowo1, slowo2)) printf("%s\n", slowo2);
fclose(f);
return 0;
}
24 cze 13:05
Benny: Ok Twoje działa poprawnie, a moje coś nie do końca.
24 cze 13:24