Prosíme přihlašte se nebo zaregistrujte.

Přihlašte se svým uživatelským jménem a heslem.
Vaše pomoc je stále potřeba!

Autor Téma: ukol v C [vyřešeno]  (Přečteno 6205 krát)

premet

  • Host
ukol v C [vyřešeno]
« kdy: 25 Listopadu 2008, 17:06:26 »
Zdravím,
Když už tady je to téma s tím programováním tak by mě zajímalo tohle, protože jinde nemám kde koho otravovat. Mám úkol v Cčku napsat funkci, která vrátí počet výskytů podřetězce (slova) v řetězci. Nejsem s prácí s řetězci ješte tak sběhlej a na ten úkol mám ješte dost času, ale nešel mi net tak sem neměl co dělat  :).
Úkol :
Kód: [Vybrat]
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/*funkcni prototypy*/
int pocet_vyskytu(char *p_vyskyt, char *p_retezec);

int main(void) {

    int i, delka_vys, delka_ret;
    char *retezec, *vyskyt;

    retezec = (char *) malloc(101 * (sizeof(char)));
    vyskyt = (char *) malloc(31 * (sizeof(char)));

    printf ("Zadejte řetězec maximální délky 100 znaků: \n");
    fgets (retezec, 101, stdin);
   
    /*while (getchar() != '\n')
            ;
    */
    delka_ret = strlen(retezec);

    if (retezec[delka_ret-1] == '\n') {
       retezec[delka_ret-1] = '\0';
    }

    printf ("Zadejte hledaný řetezec: \n");
    fgets (vyskyt, 31, stdin);

    delka_vys = strlen(vyskyt);

    if (vyskyt[delka_vys-1] == '\n') {
       vyskyt[delka_vys-1] = '\0';
    }

    i = pocet_vyskytu(vyskyt, retezec);
   
 
    printf ("Počet výskytů řetězce %s je %d.\n", vyskyt, i);
   
}

int pocet_vyskytu(char *p_vyskyt, char *p_retezec) {
 
    int pocet = 0;
    char *p_c;

    p_c = (char *) malloc(100 * (sizeof(char)));
   
    while ((p_c = strstr(p_retezec, p_vyskyt)) != NULL) {
        pocet++;
        p_retezec = ++p_c;     
    }

    return pocet;
}
a problém je v tom, že když zadám příliš dlouhou větu tak to zůstane v bufferu a automaticky se to použije ten zbytek i jako vyhledávaný řetězec a mě by zajímalo jestli tam lze dát nějakou podmínku na začátku jak mám zakomentovaný to while na vyprázdnění bufferu, že se to použije jen tehdy, když je to delší než má.
Ukázka :
Kód: [Vybrat]
Zadejte řetězec maximální délky 100 znaků:
Pejsek s kocickou si koupily novej dum. Bydleli tam asi pul roku a pak si pejsek nasel jinou kocicku. Kocicka z toho byla nestatstna a sla pejska zabit, protoze to byl peknej zmetek. Zili bez sebe stastne az do smrti.
Zadejte hledaný řetezec:
Počet výskytů řetězce . Kocicka z toho byla nestatst je 0.
jinak to funguje  :).
PS: Kod není určitě dokonalej a určitě se tam najde spousta blbých a zbytečných věcí  ;). Začínám no  :-\
« Poslední změna: 26 Listopadu 2008, 20:15:36 od Pavel Půlpán »

Martin - ViPEr*CZ*

Re: ukol v C
« Odpověď #1 kdy: 25 Listopadu 2008, 18:45:20 »
No jestli jsem to pochopil, tak pokud je řetězec větší než 100 nevejde se to samozřejmě do proměnný.

Todle:

Kód: [Vybrat]
delka_ret = strlen(retezec);

    if (retezec[delka_ret-1] == '\n') {
       retezec[delka_ret-1] = '\0';
    }

bych nahradil:

Kód: [Vybrat]
delka_ret = strlen(retezec);
if (delka_ret > 100)
retezec[100] = '\0';

ted mě napadá, jestli strlen vrátí vůbec někdy více jak 100.

Btw fgets? To se používá u souboru ne? Možná bych zkusil scanf ;)
Open source is gold way... Mint 17.2, Debian 8.1 Jessie| Ubuntu Wiki (návody) | Google vyhledávač | Qt4 návody

nettezzaumana

  • Host
Re: ukol v C
« Odpověď #2 kdy: 25 Listopadu 2008, 18:49:12 »
.. protože jinde nemám kde koho otravovat...
?IRC neznas..

premet

  • Host
Re: ukol v C
« Odpověď #3 kdy: 25 Listopadu 2008, 19:14:12 »
Nemůže tam být scanf, protože ten to načítá až po první bílej znak, takže když budou mezi slovy mezery tak to načte jen to první. Zkoušel sem ten způsob, ale takhle to nejde. Budu muset nad tím ješte koumat jak to vylepšit  :).

.. protože jinde nemám kde koho otravovat...
?IRC neznas..
Znám IRC, ale nikdy sem tam nechodil, jenom jednou na spolužácký a zkoušel sem se akorát podívat na nějaký Linuxový, ale to bylo na začátku školního roku a pak už ne. Tohle mě vůbec nenapadlo  :).

Martin - ViPEr*CZ*

Re: ukol v C
« Odpověď #4 kdy: 25 Listopadu 2008, 19:29:55 »
Jo jasně máš pravdu.... spíš teda jen gets ;) namísto fgets.

Hmm to je potvora... jsem si to myslel, že strlen vrátí max 100 a víc ne... a co tam dát rovnou:

Kód: [Vybrat]
retezec[100] = '\0';
Open source is gold way... Mint 17.2, Debian 8.1 Jessie| Ubuntu Wiki (návody) | Google vyhledávač | Qt4 návody

premet

  • Host
Re: ukol v C
« Odpověď #5 kdy: 25 Listopadu 2008, 19:41:14 »
Podle mojí moudré knihy  ;D "učebnice jazyka C" se nedoporučuje používat gets, protože nehlídá přetečení řetězce, kdežto u fgets to je přímo parametr. Ono se dá použít to while (getchar() != '\n', ale pokud ten řetězec není delší tak to musím navíc od-enterovat. Dát tam ukončovací nulu nepomůže, protože ten zbytek co to odkrojí za tou stovkou jde dál.

premet

  • Host
Re: ukol v C
« Odpověď #6 kdy: 25 Listopadu 2008, 19:41:55 »
Jako nemusím to mít za každou cenu, prostě mu to dám tak  :). Ale děkuji za snahu  :-*  ;D.

tripot

  • Návštěvník
  • Příspěvků: 17
Re: ukol v C
« Odpověď #7 kdy: 26 Listopadu 2008, 11:34:59 »
alokovat delsi retezec by nepomohlo? nebo rozdelit tu dlouhou vetu do nekolika retezcu a ty pak zkontrolovat?

Martin - ViPEr*CZ*

Re: ukol v C
« Odpověď #8 kdy: 26 Listopadu 2008, 12:23:11 »
No alokovat více paměti je samozřejmě možný... ale pokus se zase překročí ten max, tak to zase bude dělat to co to dělá.
Co takhle alokovat takhle:

Kód: [Vybrat]
char * l_retezec = new char[];
Open source is gold way... Mint 17.2, Debian 8.1 Jessie| Ubuntu Wiki (návody) | Google vyhledávač | Qt4 návody

premet

  • Host
Re: ukol v C
« Odpověď #9 kdy: 26 Listopadu 2008, 12:28:11 »
Tohle jsem teda nějak nepochopil  ??? . Můžu poprosit o trochu bližšího vysvětlení ?.

existpierre

  • Host
Re: ukol v C
« Odpověď #10 kdy: 26 Listopadu 2008, 12:38:10 »
pokial viem, new a delete je vec c++ a nie c..

myslim ze by ti stacilo dat pole o 1000 znakov, dlhsie vety asi pisat nebudes ze ?

premet

  • Host
Re: ukol v C
« Odpověď #11 kdy: 26 Listopadu 2008, 12:41:59 »
No vidíš, tohle mě vůbec nenapadlo  :D. Sem si říkal, že mi to new char[] nic neříká  :). Tak já to udělám takhle a už na to kašlu abych se s tím trápil, když je to jen za 2 body. Tak dík chlapi

Martin - ViPEr*CZ*

Re: ukol v C
« Odpověď #12 kdy: 26 Listopadu 2008, 12:47:08 »
Kruci... je pravda, že mě netrápí C/C++ a ty to chceš jen v C. Tadle kombinace je dobrá nebot by měla dynamicky zvětšovat to pole.
Až mě to na... tak to hodím do visualu :D

Jináč není zač.... rád pomohu... C/C++ je koníček ;)
Open source is gold way... Mint 17.2, Debian 8.1 Jessie| Ubuntu Wiki (návody) | Google vyhledávač | Qt4 návody

premet

  • Host
Re: ukol v C
« Odpověď #13 kdy: 26 Listopadu 2008, 12:52:17 »
Jo mě taky to C jaksi chytlo, možná až se naučím dobře C tak se vrhnu na C++ uvidíme, času je dost  :). Kdybych nemusel strávit víc času nad učením se jazyka Scheme tak bych si nemusel knížku o C číst jen v buse  ;D.

premet

  • Host
Re: ukol v C
« Odpověď #14 kdy: 26 Listopadu 2008, 20:13:11 »
Poslal jsem úkol, ale prej máme zakázáno použít jakékoliv knihovny jako string.h nebo stdlib.h takže sem to musel udělat bez toho. Vypadá, že mi to funguje už

EDIT: Tak učitelovi tam zase něco nefungovalo tak koho zajímá, dal jsem sem již opravenou verzi, která mi snad již funguje  ;D.
EDIT2: Stejně tam našel něco blbě tak jsem to udělal ješte jinak :D.
Kód: [Vybrat]
#include <stdio.h>

/*funkcni prototypy*/
int pocet_vyskytu(char *p_vyskyt, char *p_retezec) ;

int main(void) {

    int i, j;
    char retezec[1000];
    char vyskyt[30];

    printf ("Zadejte řetězec maximální délky 1000 znaků: \n");
    fgets (retezec, 1000, stdin);

    printf ("Zadejte hledaný řetezec: \n");
    fgets (vyskyt, 30, stdin);
 
    for (j = 0; j < 30; j++) {
        if (vyskyt[j] == '\n') {
            vyskyt[j] = '\0';
        }
    }


    i = pocet_vyskytu(vyskyt, retezec);

    printf ("Počet výskytů řetězce %s je %d.\n", vyskyt, i);
   
}

int pocet_vyskytu(char *p_vyskyt, char *p_retezec) {
 
    int pocet = 0;
    int i = 0;
    int j, k = 0;

   
    for (j = 0; j < 1000; j++) {
         if (p_vyskyt[i] == p_retezec[j]) {
             i++;
             if (p_vyskyt[i] == '\0') {
                 pocet++;
                 i = 0;
                 for (k = 0; k < 30; k++) {
                     if (p_vyskyt[k] == '\0') {
                        break;
                     }
                 }
                 if (k > 1) {
                    j = j - (k - 1);
                 }
                 
             }
         }
         if (p_retezec[j] == '\0') {
             break;
         }
     }
   
   return pocet;
}
« Poslední změna: 27 Listopadu 2008, 13:12:58 od Premet »

Martin - ViPEr*CZ*

Re: ukol v C [vyřešeno]
« Odpověď #15 kdy: 27 Listopadu 2008, 12:05:15 »
To jo potvora ten učitel :D

Jj hezký... nechce se mi to dávat do VS, tak se zeptám... teď když je to staticky alokováno, tak pokud je retezec větší jak 1000, tak už se to chová normálně?
Open source is gold way... Mint 17.2, Debian 8.1 Jessie| Ubuntu Wiki (návody) | Google vyhledávač | Qt4 návody

premet

  • Host
Re: ukol v C [vyřešeno]
« Odpověď #16 kdy: 27 Listopadu 2008, 12:22:50 »
Nene, stále pokud dám řetězec delší než těch 1000 znaků tak to dělá to co předtím, ale jakože "nepředpokládám", že by někdo dal delší tak sem to neřešil  ;D. Stejně tam mám blbě ješte jednu věci tak se na to musím ješte mrknout  :).

Martin - ViPEr*CZ*

Re: ukol v C [vyřešeno]
« Odpověď #17 kdy: 27 Listopadu 2008, 12:47:07 »
Tak mi to nedalo a zalistoval jsem trochu v msdn a použil debug v MS Visual Studiu a ejhle... našel jsem ti řešení:

Kód: [Vybrat]
printf ("Zadejte hledaný řetezec: \n");
flushall();
fgets (vyskyt, 30, stdin);

Zjistil jsem, že v nějakým globálním bufferu zůstane ten ořízlej zbytek a ten se pak automaticky hodí jako vyhledávaný řetězec. No tak jsem hledal jak ten buffer vynulovat a našel jsem funkci flushall ;)
Takže teď pokud zadáš něco větší jak 1000 znaků, tak se to prostě samo ořízne a veme se jen max 1000 znaků.
Open source is gold way... Mint 17.2, Debian 8.1 Jessie| Ubuntu Wiki (návody) | Google vyhledávač | Qt4 návody

premet

  • Host
Re: ukol v C [vyřešeno]
« Odpověď #18 kdy: 27 Listopadu 2008, 12:57:40 »
Bohužel takhle se ta funkce použít nedá  :-[. Co jsem se díval tak to funguje taklhe
Kód: [Vybrat]
#include <stdio.h>

int main( void )
{
   int numflushed;

   numflushed = _flushall();
   printf( "There were %d streams flushed\n", numflushed );
}
a to mi bohužel nepomůže. Však mu nejde o tohle, ale hlavně aby fungovala ta funkce pocet_vyskytu  :).

Martin - ViPEr*CZ*

Re: ukol v C [vyřešeno]
« Odpověď #19 kdy: 27 Listopadu 2008, 13:08:19 »
? já to mám vyzkoušený a pomohlo to ;) vymazalo to buffer co si to pamatovalo z minulýho vstupu.
Jo to jsem si všimnul, že ta funkce to špatně počítá, ale tu jsem neopravoval to nechám na tobě :P
Open source is gold way... Mint 17.2, Debian 8.1 Jessie| Ubuntu Wiki (návody) | Google vyhledávač | Qt4 návody

premet

  • Host
Re: ukol v C [vyřešeno]
« Odpověď #20 kdy: 27 Listopadu 2008, 13:12:18 »
Mě to hodilo chybu při kompilaci, tak jdu na matiku a vyzkouším pozdějí tak díky :).

Martin - ViPEr*CZ*

Re: ukol v C [vyřešeno]
« Odpověď #21 kdy: 27 Listopadu 2008, 13:55:23 »
No ještě jsem se pro jistotu koukal a tato funkce je dostupná z hlavičkového souboru stdio.h a ta se na poslední tebou daném výpisu zde objevuje, tak nevidím problém ;)
Open source is gold way... Mint 17.2, Debian 8.1 Jessie| Ubuntu Wiki (návody) | Google vyhledávač | Qt4 návody

premet

  • Host
Re: ukol v C [vyřešeno]
« Odpověď #22 kdy: 27 Listopadu 2008, 14:58:14 »
To je divný  ???
Kód: [Vybrat]
prema@debian:ukoly_skola$ gcc -o navic_uloha navic_uloha.c
/tmp/ccwNFrfr.o: In function `main':
navic_uloha.c:(.text+0x4c): undefined reference to `flushall'
collect2: ld returned 1 exit status

Martin - ViPEr*CZ*

Re: ukol v C [vyřešeno]
« Odpověď #23 kdy: 27 Listopadu 2008, 15:10:17 »
zkus to takto: _flushall();
Open source is gold way... Mint 17.2, Debian 8.1 Jessie| Ubuntu Wiki (návody) | Google vyhledávač | Qt4 návody

premet

  • Host
Re: ukol v C [vyřešeno]
« Odpověď #24 kdy: 27 Listopadu 2008, 15:22:00 »
To jsem taky zkoušel a udělá to to samí. Je to divný no :).

 

Provoz zaštiťuje spolek OpenAlt.