Czy słowo jest wykreślanką drugiego słowa

0

Mam napisać funkcję, która sprawdza czy slowo1 jest wykreślanką slowa2 . np. Irak jest wykreślanką słowa Informatyka (po wykreśleniu liter N,F,O,M,T,Y,A powstaje wyraz irak)

#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>

int czy_wykreslanka( char *slowo1 , char *slowo2)
{   if (strlen(slowo1)== strlen(slowo2)) return 0;
    int licznik_zmian=0;
    while (*slowo1 && *slowo2) {
         if (*slowo2 == *slowo1)
         ++slowo1;
         ++slowo2;
         licznik_zmian ++;
    }
    if (licznik_zmian =strlen(slowo1)-strlen(slowo2))
        return 1;
    else
        return 0;
    }
 int main (){
 char *slowo1=" informatyka ";
 char *slowo2="  irak ";
 printf("%d",czy_wykreslanka(slowo1, slowo2));
 return 0;
 }

Problem w tym ,że jak wpiszę abcd to program też działa jak dopisać warunek , że litery w wykreślonym muszą być tak jakby "podciągiem" wyjściowego słowa?

0

Jest tam sporo błędów, np., nie ma klamry po if - ie, więc nie wiem czy Wiesz co Robisz:); wskaźniki do char to nie są statyczne tablice, jak je Inkrementujesz, to się zmienia strlen (wskaźnik jest do następnej litery - przykład w main). Ja widzę, że problem jest równoważny temu(niech mnie ktoś poprawi): wyraz jest wykreślanką drugiego wyrazu, jeśli każda jego litera znajduje się w wyrazie drugim i wyraz pierwszy jest krótszy od drugiego. Stąd program, złożoność niestety O(n^2) (naiwna), ale za to jest pole do optymalizacji:):

#include <stdio.h>
#include <string.h>

int char_in_string(char c, char * str){
	int cnt = 0;
	while(*str) {
		if (c == *str)
			return cnt + 1;
		cnt++;
		str++;
	}
	return 0;
}

int czy_wykreslanka( char *slowo1 , char *slowo2){   
	int s = strlen(slowo1);
	if (s >= strlen(slowo2)) return 0;
	int cnt = 0;
	int max = 0;
	int tmp;
    while (*slowo1) {
		tmp = char_in_string(*slowo1, slowo2);
         if (tmp) {
			if (tmp >= max) 
				cnt++;
		 }
		 slowo1++;
	}
    if (cnt >= s)
        return 1;
    else
        return 0;
}
int main (){
   	char *slowo1="irak";
	char *slowo2="informatyka";
	printf("%d\n",czy_wykreslanka(slowo1, slowo2)); // -> 1
	char *slowo3="iraku";
	char *slowo4="informatyka";
	printf("%d\n",czy_wykreslanka(slowo3, slowo4)); // -> 0
	printf("%ld\n", strlen(slowo3)); // -> 5
	slowo3++;
	printf("%ld\n", strlen(slowo3)); // -> 4
	return 0;
}

EDIT: "Ja widzę, że problem jest równoważny temu(niech mnie ktoś poprawi): wyraz jest wykreślanką drugiego wyrazu, jeśli każda jego litera znajduje się w wyrazie drugim i wyraz pierwszy jest krótszy od drugiego", oraz zachowana jest kolejność liter.

0
  1. Dla każdej litery w słowie 1:
  2. Jeśli obecna litera w słowie 1 pasuje do obecnej litery w słowie 2, to przechodzisz do następnej litery w słowie 2.
  3. W przeciwnym wypadku zwiększasz licznik.
  4. Jeśli zmatchowałeś wszystkie litery w słowie 2, to zwracasz licznik, w przeciwnym wypadku nie jest to "wykreślanka".

Przykład w C:

int czy_wykreslanka(char *word_a, char *word_b) {
    int counter = 0;

    while (*word_a) {
        if (*word_b == *word_a)
            ++word_b;
        else
            ++counter;

        ++word_a;
    }

    return *word_b ? -1 : counter;
}
0
hauleth napisał(a):
  1. Dla każdej litery w słowie 1:
  2. Jeśli obecna litera w słowie 1 pasuje do obecnej litery w słowie 2, to przechodzisz do następnej litery w słowie 2.
  3. W przeciwnym wypadku zwiększasz licznik.
  4. Jeśli zmatchowałeś wszystkie litery w słowie 2, to zwracasz licznik, w przeciwnym wypadku nie jest to "wykreślanka".

Przykład w C:

int czy_wykreslanka(char *word_a, char *word_b) {
    int counter = 0;

    while (*word_a) {
        if (*word_b == *word_a)
            ++word_b;
        else
            ++counter;

        ++word_a;
    }

    return *word_b ? -1 : counter;
}

Mam coś takiego:

#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>


int czy_wykreslanka(char *word_a, char *word_b) {
    int counter = 0;

    while (*word_a) {
        if (*word_b == *word_a)
            ++word_b;
        else
            ++counter;
            ++word_a;

    }

    return *word_b;}
int main (){
 char *word_a=" informatyka ";
 char *word_b=" irak";
 printf("%d",czy_wykreslanka(word_a, word_b));
 return 0;
 }

i niestety nadal nie działa

0

Skoro program @hauleth nie działa (lub wymaga debugu), szkoda było wyrzucać tak pięknego kawałka kodu:) i zedytowałem swój post: funkcja: char_in_string zwraca teraz indeks litery w słowie (plus jeden, ale to bez znaczenia), a główna funkcja sprawdza czy te indeksy rosną, i dopiero wtedy instrumentuje licznik, który, gdy dojdzie do długości pierwszego słowa, zwraca 1.

0
int czy_wykreslanka(char *s, char *t)
{
    for ( ; *s; ++s, ++t) {
        for ( ; *t && *s != *t; ++t)
            ;
        if (!*t) {
            return 0;
        }
    }
    return 1;
}
1

https://4programmers.net/Forum/C_i_C++/327220-sprawdzanie_czy_wyraz_jest_skrotka?p=1594636#id1594636

int isSubsequence(const char *s, const char *sub)
{
    while (*sub && *s) {
         if (*sub == *s) ++sub;
         ++s;
    }
    return *sub == 0;
}

https://wandbox.org/permlink/JkEpjDHPXrw9jDt0

0

Napisałam inaczej jeszcze ten program sprawdzi ktoś

#include <conio.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>

int wykreslanka(char slowo1[31], char slowo2[31]){
int i=0;
int j=0;
while (slowo2[i]=='/0'){
   while(slowo1[j]!= slowo2[i]){
       if(slowo1[j]=='/0')
           return 0;
       else j++;}
       i++;
       j++;}
       return 1;
       }

int main (){
   char slowo1[31], slowo2[31];
   printf("Proszę podać slowo");
   scanf("%s",slowo1);
   FILE *tekst;
   tekst=fopen("lownik.txt", "r");
   while(!feof(tekst)){
       fscanf(tekst, "%s", slowo2);
       if(wykreslanka(slowo1,slowo2)==1){
           printf("%s\n", slowo2);}}
           fclose(tekst);
           getch();
           return 0;
       }


0
  1. Zamień '/0' na '\0' w obu miejscach. To pierwsze jest interpretowane jako tzw. multicharacter constant (szczegóły tu), więc pewnie nie było Twoim zamierzeniem napisanie tego, natomiast to drugie jest tzw. octal escape sequence (szczegóły tu) i może oznaczać koniec ciągu znaków.
  2. Dodaj pierwszą literę do nazwy pliku "lownik.txt" – wielką albo małą (nie wiem, jak masz u siebie w systemie).
  3. Poniżej wklejam sformatowany Twój kod, by lepiej wyglądał (poprawiłem też literały '\0', niemniej "lownik.txt" nadal jest do poprawy). Deklarację char slowo1[31], slowo2[31]; przeniosłem pod wywołanie funkcji printf.
  4. W kwestii poprawności programu – nie znam się na C, poczekaj raczej na kogoś innego.
#include <conio.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>

int wykreslanka(char slowo1[31], char slowo2[31])
{
    int i = 0;
    int j = 0;

    while (slowo2[i] == '\0')
    {
        while (slowo1[j] != slowo2[i])
        {
            if (slowo1[j] == '\0')
            {
                return 0;
            }
            else
            {
                j++;
            }
        }

        i++;
        j++;
    }

    return 1;
}

int main()
{
    printf("Proszę podać slowo");
    char slowo1[31], slowo2[31];
    scanf("%s", slowo1);

    FILE *tekst;
    tekst = fopen("lownik.txt", "r");

    while (!feof(tekst))
    {
        fscanf(tekst, "%s", slowo2);

        if (wykreslanka(slowo1, slowo2) == 1)
        {
            printf("%s\n", slowo2);
        }
    }

    fclose(tekst);
    getch();

    return 0;
}
0

Powyższy jest niepoprawny, daje 1 dla pary: "fin" i "informatyka".

0

@lion137: A w tym co jest nie tak?


int czy_wykreslanka( char *slowo1[] , char *slowo2[]){
   if (strlen(slowo1)<= strlen(slowo2)) return 0;
    int licznik_zgodnosci=0;
    while (*slowo1 && *slowo2) {
         if (*slowo2== *slowo1){
         ++slowo2;
         ++slowo1;
         licznik_zgodnosci++;}
         else
         ++slowo1;

    }
    if (licznik_zgodnosci ==strlen(slowo2))
        return 1;
    else
        return 0;
    }
 int main (){
 char slowo1[]=" informatyka ";
 char slowo2[]=" irak ";
 printf("%d",czy_wykreslanka(slowo1, slowo2));
 getch();
 return 0;
 }

0

Zdebuguj sobie, daje 0 dla pary: "irak", informatyka".

0

@lion137: może wpisałeś słowa w złej kolejności?

0

Tak, wpisałem, ale dalej daje zero!:)

0

@lion137: wiem, że dla irak , informatyka powinno być 0, ale nwm co nie tak jest w moim myśleniu, czegoś nie zauważam , ale nwm czego , dlatego nie wiem co powinnam zmienić

0
Kate321 napisał(a):

@lion137: wiem, że dla irak , informatyka powinno być 0

lion137 napisał(a):

Powinno być 1. - lion137 1 minuta temu

Powinno być 0, ponieważ zła kolejność.


UPDATE:

Zła kolejność, ponieważ w algorytmie jest

int czy_wykreslanka( char *slowo1[] , char *slowo2[]){
  if (strlen(slowo1)<= strlen(slowo2)) return 0;
  ...
}

co oznacza, że słowo podane jako pierwsze musi być słowem, z którego się wykreśla. @lion137, może u siebie w testach podajesz dobrą kolejność, ale jak @Kate321 napisała "irak, informatyka", to to jest zła kolejność.

0

Tak informatyka i irak powinno być 1 ale dostaje 0 , więc gdzie błąd?

0

Najprostsza metoda debugowania (w funkcji main() są też moje komentarze):

int czy_wykreslanka(char *slowo1[], char *slowo2[])
{
    printf("%s", slowo1); // czy wypisuje `informatyka`?
    printf("%s", slowo2); // czy wypisuje `irak`?

    printf("%d", strlen(slowo1)); // czy wypisuje `11`?
    printf("%d", strlen(slowo1)); // czy wypisuje `4`?

    if (strlen(slowo1) <= strlen(slowo2))
    {
        return 0;
    }

    int licznik_zgodnosci = 0;
    while (*slowo1 && *slowo2)
    {
        if (*slowo2 == *slowo1)
        {
            ++slowo2;
            ++slowo1;
            licznik_zgodnosci++;
        }
        else
        {
            ++slowo1;
        }
    }

    if (licznik_zgodnosci == strlen(slowo2))
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

int main()
{
    char slowo1[] = " informatyka "; // tu masz spacje, może to wpływać na wynik
    char slowo2[] = " irak "; // tu masz spacje, może to wpływać na wynik

    printf("%d", czy_wykreslanka(slowo1, slowo2));

    getch();
    return 0;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1