Avatar
Swixi
Neregistrovaný
Avatar
Swixi:

Ahoj, dostali jsme ve škole úkol, tak jsem na něm začal dělat. 1 úloha zvládnutá ale u této druhé jsem se sekl a dost.. Mohl by ji někdo udělat a vysvětlit mi jak to vlastně udělal (respektivě nějak to "analizovat")abych to pochopil . Byl bych moc vděčný. Lámu si nad tím hlavu už 2dny a zatím jsem vymyslel jen jak to udělat teoreticky ale i to možná bude špatně.. (když jsem požádal učitele o vysvětlení tak to vysvětlil na jiném příkladu a já z toho byl ještě víc blbej.:( )

úloha :

*Napište funkci char * strCatAt(char *s1, const char *s2, int p), která vloží do řetězce s1 na pozici p
řetězec s2. Je-li p větší, než délka s1, připojí s2 na konec s1. Uvažujte, že v s1 je alokován dostatečný
prostor. Návratovou hodnotou je ukazatel na výsledný řetězec, resp. hodnota NULL byl-li s2 prázdný
nebo p záporné.
Např.: strCatA( strCatA( „Dům a“, „n“, 5), „kraji silnice“, 100)  “Dům na kraji silnice“
*

**Toto jsem tak zhruba psal a zajímalo by mne zdali jsem to pochopil správně a šlo by to tak použít, ale zpětně si myslím že asi ne no .. Prosím o pomoc. **

char * strCatAt(char *s1, const char *s2, int p)
{
int p = 0;
char *s1 = "Proč nevytváříme";
char *s2 = "programy ve škole.";
/
zde bude nějaká smyčka co bude nebo funkce

,která vloží něco na pozici p a dále porovná s řetězcem

a když bude větší tak proběhne následující funkce a vytiskne*/
}
/* funkce připojení jednoho řetězce na konec druhého*/
strcat(char s2[], char s1[], int p)

{
int i, j;
i = j = 0;
while (s2[i] != '\0')
i++;
while ((s2[i++] = s1[j++]) != '\0')
;
/*ted bude tisk /
}

 
Odpovědět 3.2.2014 15:30
Avatar
Odpovídá na Swixi
Lukáš Hruda (Luckin):

Nejdřív si původní obsah od dané pozice do konce (do nulového znaku) ulož do nějaké pomocné paměti, pak znak po znaku překopíruj s2 do s1 přičemž začneš od té dané pozice a zaznamenej, u kterého znaku kopírování skončilo, nakonec vem obsah té pomocné paměti a znak po znaku ho překopíruj od té zaznamenané poslední pozice dál, pak jenom na konec přidej nulový znak.

 
Nahoru Odpovědět 3.2.2014 15:45
Avatar
Swixi
Neregistrovaný
Avatar
Odpovídá na Lukáš Hruda (Luckin)
Swixi:

Takle nějak jsem to myslel původně, a tak jsem psal učite-li nějaké otázky. On odpověděl toto :

"hledáš problém, kde není. Klidně tu poznámku k hodnotě p na začátku práce ignoruj. Jde jen o to, že bys měl v programu ošetřit nesmyslné zadání, tj. požadavek na vložení dál, než je konec řetězce. Například do řetězce „Ahoj“ těžko mohu požadovat vložení na pozici 100. V zásadě je to pak možné ošetřit jednou podmínkou typu: je-li p větší, než délka s1 nastav ho na délku s1.
Pokud jde o příklad, pak je ho nutné rozložit. Představ si například požadavek na výpočet:
sin( sin(0.2) + 1.3),
který taky řešíš ve více krocích. Nejdřív spočteš vnitřní sinus (v příkladu s řetězci je to ten vnitřní stCatAt) a pak výsledek postoupíš do dalšího kola."

Podle toho si myslím, že to půjde i bez nějakého kopírování (pro inf v C neděláme ani měsíc a letíme hrozným stylem dopředu..)

 
Nahoru Odpovědět 3.2.2014 16:01
Avatar
Odpovídá na Swixi
Lukáš Hruda (Luckin):

Zkus najít a projít si dokumentaci knihovny string.h, je docela dobře možné, že na tohle má C už nějaké standardní funkce.

 
Nahoru Odpovědět 3.2.2014 16:09
Avatar
Swixi
Neregistrovaný
Avatar
Odpovídá na Lukáš Hruda (Luckin)
Swixi:

Ať hledám kde hledám nevím kde ty knihovny najít. Jak už jsem psal neučíme se to vůbec dlouho a o ničem takovém nám ani neříkal..

 
Nahoru Odpovědět 3.2.2014 16:45
Avatar
Odpovídá na Swixi
Lukáš Hruda (Luckin):

Tak na vkládání řetěžců v C asi nic nebude ale na kopírování můžeš používat funkci strcpy. Je potřeba naincludovat soubor string.h. Jinak tu pomocnou paměť asi budeš potřebovat.

 
Nahoru Odpovědět 3.2.2014 16:54
Avatar
Swixi
Neregistrovaný
Avatar
Odpovídá na Lukáš Hruda (Luckin)
Swixi:

No tak naincludovat soubor slyším poprvé.. takže to budu muset udělat asi přes tu paměť .. ale nevim jak.. Je to ironie.. učitel s námi neprogramuje vysvětluje pár příkazů a pak vám dá úkol takový kde neumíte ještě ani udělat to aby se to někam uložilo a postupně vkládalo znaky... a teď babo raď ... Prosím tě je něco (nějaká stránka nebo něco takového) kde bych se postupně učil C stylem malých snadných prográmků až bych postoupil takle ? (doufám, že mne chápeš.)

 
Nahoru Odpovědět 3.2.2014 17:09
Avatar
Odpovídá na Swixi
Lukáš Hruda (Luckin):

Naincludovat znamená že na začátek napíšeš #include <string.h>
To nevím, můžeš zkusit tady na devbooku a nebo tutoriály na youtube.

 
Nahoru Odpovědět 3.2.2014 17:15
Avatar
Swixi
Neregistrovaný
Avatar
Odpovídá na Swixi
Swixi:

copy(char s1[], char s2[])
{
int i;
i = 0;
while ((s1[i] = s2[i])!= '\0')
++i;
}

tímto bych kopíroval s2 do s1 ne ?

ale kde je to porovnání, které chce. To s tou pozicí nechápu ..

 
Nahoru Odpovědět 3.2.2014 17:16
Avatar
petrph
Člen
Avatar
petrph:

Ahoj, jestli můžu pár tipů.

1. Ty v té své funkci nebudeš na konci tisknout výsledek (viz /*ted bude tisk / ale jenom vrátíš výsledek (nějaké to return s1). Čímž máš zajištěné to co o čem píše učitel -napřed vnitřní, pak vnější.-překladač to udělá za tebe - a pak si to ověříš v tom úvodním příkladu kde se ta funkce sama volá vnořeně strCatA( strCatA( ..))
2.Čili pak na začátku té funkce provedeš ty kontroly "byl-li s2 prázdný
nebo p záporné"-a rovnou vrátíš NULL.
3. No a pak asi budeš muset kopírovat..Můžeš to řešit tak jak píše Swixi , tedy uložit si znaky v s1 od pozice p jinam, nakopírovat od pozice p znaky s2 a za ně pak uložený zbytek s1. A nebo "ftipně" si napřed posunout znaky v s1 o potřebný počet pozic dozadu (ten počet znaků je délka s2).Posunovat to v cyklu odzadu od pozice '\0' k pozici p.A pak do té vzniklé mezery od pozice p nakopírovat znaky s2...
4. A jak jsem tedy psal v bodu 1. return s1.
5.A všechno pořádně otestovat a odladit..
Bohužel tohle se moc ošvindlovat nedá, práce s poli, pointery a kopírování, to je gró jazyka C...

 
Nahoru Odpovědět 3.2.2014 18:08
Avatar
Nahoru Odpovědět 3.2.2014 18:46
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Odpovídá na petrph
Libor Šimo (libcosenior):

Ja som to už spravil na linuxe. Musel som nahradiť chýbajúcu funkciu strrev() inou.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SWAP(T, a, b) \
    do { T save = (a); (a) = (b); (b) = save; } while (0)

char *reverse_string(char *s)
{
    size_t len = strlen(s);
    if (len > 1) {
        char *a = s;
        char *b = s + len - 1;
        for (; a < b; ++a, --b)
            SWAP(char, *a, *b);
    }
    return s;
}

char * strCatAt(char *s1, const char *s2, int p)
{
    char *s1_dyn, *s2_dyn, *pom1, *pom2;

    // dynamické alokovanie pamäti pre jednotlivé reťazce
    s1_dyn = (char *) malloc(200);
    s2_dyn = (char *) malloc(100);
    pom1 = (char *) malloc(200);
    pom2 = (char *) malloc(100);
    // nakopírovanie reťazcov z parametrov funkcie do dynamicky alokovaných reťazcov
    strcpy(s1_dyn, s1);
    strcpy(s2_dyn, s2);

    // ak je veľkosť prvého reťazca 0 alebo hodnota p je mínusová
    if (strlen(s1_dyn) < 1 || p < 0) {
        return NULL; // vráti NULL
    }
    else {
        // ak je p väčšie ako veľkosť prvého reťazca
        if (p > strlen(s1_dyn)) {
            strcat(s1_dyn, s2_dyn); // spoja sa s1 a s2 za sebou
            return s1_dyn; // vráti spojený reťazec
        }
        else {
            strncpy(pom1, s1_dyn, p); //vloží do pom1 prvých p znakov
            // vloží do pom2 zvyšné znaky, výsledok je otočený
            strncpy(pom2, reverse_string(s1_dyn), strlen(s1_dyn) - p);
                        /* na windowse použi na otočenie teťazca naopak funkciu strrev()
               ja som na linuxe musel použiť náhradnú reverze_string */
            reverse_string(pom2); // otočiť späť
            strcat(strcat(pom1, s2_dyn), pom2); // spojiť reťazce v správnom poradí

            return pom1; // vráti konečný reťazec
        }
    }
}

int main(void)
{
    printf("%s", strCatAt(strCatAt("Dům a", "n", 5), " kraji silnice.", 100));
    // Dům na kraji silnice.

    return 0;
}
Editováno 3.2.2014 20:43
Nahoru Odpovědět 3.2.2014 20:42
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Swixi
Neregistrovaný
Avatar
Odpovídá na Libor Šimo (libcosenior)
Swixi:

Odkud ses učil ? pls :) já jsem došel do půlky a ještě s 2 chybami oproti tobě jak koukám asi..

 
Nahoru Odpovědět 3.2.2014 23:37
Avatar
TsukiRa
Člen
Avatar
TsukiRa:

do řetězce s1 na pozici p řetězec s2 + v s1 je alokován dostatečný prostor => sypu to přímo do s1 a žádnou další paměť není potřeba

např:

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

char *strcatat(char *s1, const char *s2, int p) {
    if (p < 0 || strlen(s2) <= 0)
        return NULL;

    if (p >= strlen(s1)) {
        strcpy(s1, strcat(s1, s2));
    } else {
        int i = 0;
        const int s2_size = strlen(s2);
        for (; i < s2_size; i++) {
            s1[p+i+s2_size] = s1[p+i]; // posunu původní znak dozadu
            s1[p+i] = s2[i];           // vložím jeden znak z s2
        }
    }
    return s1;
}
Nahoru Odpovědět 4.2.2014 1:59
Někdy je lepší zůstat v pondělí v posteli než celý týden ladit pondělní kód.
Avatar
Odpovídá na TsukiRa
Libor Šimo (libcosenior):

To Swixi učil som sa z knižky od Heroouta a pokúsil som sa to previezť do podoby pre začínajúcich na fóre: skolka jazyka c (nájdeš na webe).
To TsukiKo pokiaľ mám správne informácie, keď nie je alocovaná pamäť v céčku, môžeš sa pridaním ďalších znakov dostať do neošetrenej pamäti, tam prepísať uxistujúce data a tým aj napríklad narušiť program.

Editováno 4.2.2014 5:42
Nahoru Odpovědět 4.2.2014 5:42
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
vitamin
Člen
Avatar
vitamin:

Da sa to spravyt aj takto:

char* strcatat(char *s1, const char *s2, int p) {
    if(!strlen(s2) || p < 0)return 0;
    if(strlen(s1) < p)memcpy(s1+strlen(s1), s2, strlen(s2)+1);
    else{
        memmove(s1+p+strlen(s2), s1+p, strlen(s1)-p+1);
        memcpy(s1+p, s2, strlen(s2));
    }
    return s1;
}
 
Nahoru Odpovědět 4.2.2014 8:10
Avatar
vitamin
Člen
Avatar
Odpovídá na Libor Šimo (libcosenior)
vitamin:

Ten tvoj kód je veľmi zlý. Dynamicky alokuješ polia s 100 a 200 znakmi, čo ak ma vstupný reťazec 201 znakov? V zadaní bolo napísané že reťazec s1 má dostatok alokovanej pamäte, tie tvoje dynamicky alokované reťazce sú alokované pomocou konštanty vycucanej z prstu... Máš tam 4x malloc() a 0x free(), takže 4x memoryleak. Musel si si vytvoriť funkciu na reverse string a celé je to zbytočne zložité a pomalé.

 
Nahoru Odpovědět 4.2.2014 8:33
Avatar
Odpovídá na vitamin
Libor Šimo (libcosenior):

Testoval som funkcie od TsukiKo aj od vitamin, ani jedna funkcia nefunguje. Aspoň mne na WinXP v IDE CODE:BLOCKS.

Moju som upravil pre win a je plne funkčná:

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

char * strcatat(char *s1, const char *s2, int p)
{
    char *s1_dyn, *s2_dyn, *pom1, *pom2;

    // dynamické alokovanie pamäti pre jednotlivé reťazce
    s1_dyn = (char *) malloc(200);
    s2_dyn = (char *) malloc(100);
    pom1 = (char *) malloc(200);
    pom2 = (char *) malloc(100);
    // nakopírovanie reťazcov z parametrov funkcie do dynamicky alokovaných reťazcov
    strcpy(s1_dyn, s1);
    strcpy(s2_dyn, s2);
    // vytvoriť prázdne reťazce aby mali na konci znak '\0'
    strcpy(pom1, "");
    strcpy(pom2, "");

    // ak je veľkosť prvého reťazca 0 alebo hodnota p je mínusová
    if (strlen(s1_dyn) < 1 || p < 0) {
        return NULL; // vráti NULL
    }
    else {
        // ak je p väčšie ako veľkosť prvého reťazca
        if (p > strlen(s1_dyn)) {
            strcat(s1_dyn, s2_dyn); // spoja sa s1 a s2 za sebou
            return s1_dyn; // vráti spojený reťazec
        }
        else {
            strncat(pom1, s1_dyn, p - 1); //vloží do pom1 prvých p znakov
            // vloží do pom2 zvyšné znaky, výsledok je otočený
            strncat(pom2, strrev(s1_dyn), strlen(s1_dyn) - 5 + 1);
            strrev(pom2); // otočiť späť
            strcat(strcat(pom1, s2_dyn), pom2); // spojiť reťazce v správnom poradí

            return pom1; // vráti spojený reťazec
        }
    }
}

int main(void)
{
    printf("%s\n", strcatat(strcatat("Dom a", "n", 5), " kraji silnice.", 100));

    return 0;
}
Nahoru Odpovědět 4.2.2014 9:06
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
vitamin
Člen
Avatar
Odpovídá na Libor Šimo (libcosenior)
vitamin:

Skus si spustiť toto:

int main(void){
    char str[300];
    for(unsigned i = 0; i < 220; ++i)str[i] = 'a';
    str[219] = '\0';

    strcatat(str, "xxx", 6);
    return 0;
}

A pozri sa co ti na tvoj kód povie valgrind.

 
Nahoru Odpovědět 4.2.2014 9:21
Avatar
Odpovídá na Swixi
Libor Šimo (libcosenior):

Swixi, zabudol som na uvoľnenie pamäte, doplň si na koniec funkcie:

free(s1_dyn);
free(s2_dyn);
free(pom1);
free(pom2);

Díky za upozornenie vitamin.

Nahoru Odpovědět 4.2.2014 9:22
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
vitamin
Člen
Avatar
Odpovídá na Libor Šimo (libcosenior)
vitamin:

Nestačí to dať na koniec funkcie (treba pred každý return) a tým spôsobom si uvoľníš aj to pole ktoré vraciaš...

 
Nahoru Odpovědět 4.2.2014 9:26
Avatar
Odpovídá na vitamin
Libor Šimo (libcosenior):

vitamín, ospravedlňujem sa. S funkciami memory som zatiaľ nepracoval anepoznám ich, preto som použil funkcie pre string.
Tvoja funkcia pracuje správne.

Nahoru Odpovědět 4.2.2014 9:30
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Odpovídá na TsukiRa
Libor Šimo (libcosenior):

Sorry TsukiKo, neuvedomil som si, že sa bude s1 alocovať vo funkcii main(). Aj tvoja funkcia pracuje správne.
Len pokiaľ sa má splniť zadanie, ktoré je v 1. príspevku, funkcie mimo mojej nefungujú.
Pod zadaním myslím:

Např.: strCatA( strCatA( „Dům a“, „n“, 5), „kraji silnice“, 100)  “Dům na kraji silnice“

Nahoru Odpovědět 4.2.2014 9:39
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
vitamin
Člen
Avatar
Odpovídá na Libor Šimo (libcosenior)
vitamin:

V zadanie je napísané toto:
"Uvažujte, že v s1 je alokován dostatečný prostor."

Ten tvoj príklad nespĺňa túto podmienku.

 
Nahoru Odpovědět 4.2.2014 9:46
Avatar
Odpovídá na vitamin
Libor Šimo (libcosenior):

Ako vidíš, v zadaní sú teda dve rôzne podmienky.
Ale mám na teba dotaz.
Ako si myslel, že mám vyprázdniť pamäť pred každým return.
Veď keď to spravím, reťazce sa stratia a teda nevypíšu.

Nahoru Odpovědět 4.2.2014 10:04
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
vitamin
Člen
Avatar
Odpovídá na Libor Šimo (libcosenior)
vitamin:

Reťazce ostanú v pamäti a budu zbytočne uberať pamäť až dokým sa daný proces neukončí. V takýchto programoch ktoré nepotrebujú veľa pamäte a sú spustené krátku dobu to nevadí, ale v reálnych programoch treba pamäť uvoľňovať.

 
Nahoru Odpovědět 4.2.2014 10:13
Avatar
Libor Šimo (libcosenior):

Swixi, toto je posledná verzia, alokuje len potrebné miesto v pamäti a mala by byť univerzálna. Vyskúšaj si ju.

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

char * strcatat(char *s1, const char *s2, int p)
{
    char *s1_dyn, *s2_dyn, *pom1, *pom2;

    // dynamické alokovanie pamäti pre jednotlivé reťazce
    s1_dyn = (char *) malloc(strlen(s1) + strlen(s2) + 2);
    s2_dyn = (char *) malloc(strlen(s2) + 1);
    pom1 = (char *) malloc(strlen(s1) + 1);
    pom2 = (char *) malloc(strlen(s1) + 1);
    // nakopírovanie reťazcov z parametrov funkcie do dynamicky alokovaných reťazcov
    strcpy(s1_dyn, s1);
    strcpy(s2_dyn, s2);
    // vytvoriť prázdne reťazce aby mali na konci znak '\0'
    strcpy(pom1, "");
    strcpy(pom2, "");

    // ak je veľkosť prvého reťazca 0 alebo hodnota p je mínusová
    if (strlen(s1_dyn) < 1 || p < 0) {
        return NULL; // vráti NULL
    }
    else {
        // ak je p väčšie ako veľkosť prvého reťazca
        if (p > strlen(s1_dyn)) {
            strcat(s1_dyn, s2_dyn); // spoja sa s1 a s2 za sebou
            return s1_dyn; // vráti spojený reťazec
        }
        else {
            strncat(pom1, s1_dyn, p - 1); //vloží do pom1 prvých p znakov
            // vloží do pom2 zvyšné znaky, výsledok je otočený
            strncat(pom2, strrev(s1_dyn), strlen(s1_dyn) - 5 + 1);
            strrev(pom2); // otočiť späť
            strcat(strcat(pom1, s2_dyn), pom2); // spojiť reťazce v správnom poradí
            return pom1; // vráti konečný reťazec

        }
    }
    free(s1_dyn);
    free(s2_dyn);
    free(pom1);
    free(pom2);
    free(s1);
}

int main(void){
    char str[300];
    unsigned int i;
    for(i = 0; i < 220; ++i)str[i] = 'a';
    str[219] = '\0';

    printf("%s\n", strcatat(str, "xxx", 6));
    printf("%s\n", strcatat(strcatat("Dom a", "n", 5), " kraji silnice.", 100));
    return 0;
}

Výstup:

Editováno 4.2.2014 11:27
Nahoru Odpovědět 4.2.2014 11:25
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Libor Šimo (libcosenior):

Výstup mi to nevzalo, skúsim znovu:

Nahoru Odpovědět 4.2.2014 11:26
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
TsukiRa
Člen
Avatar
TsukiRa:

libco: Moje funkce nefunguje moc správně, jen za určitých podmínek :D

Paměť je potřeba uvolňovat vždy, "můj program tak dlouho nepoběží", "allocuji málo paměti" apod. neni dobrá výmluva. Nikdy nevíš co s tím udělá uživatel. Navíc, když pak něco takového použiješ v reálné aplikaci tak je to v ......

Nahoru Odpovědět 4.2.2014 11:42
Někdy je lepší zůstat v pondělí v posteli než celý týden ladit pondělní kód.
Avatar
TsukiRa
Člen
Avatar
TsukiRa:

libco: Opravdu se ty free za returnem provedou??

Nahoru Odpovědět 4.2.2014 11:52
Někdy je lepší zůstat v pondělí v posteli než celý týden ladit pondělní kód.
Avatar
Swixi
Neregistrovaný
Avatar
Odpovídá na Libor Šimo (libcosenior)
Swixi:

libco každopádně dík, že mi tu pomáháš já si tu lámu hlavu.. spousta příkazů se doučuji a začínám v tom akorát mít bordel jak jsem se učil moc příkazů najednou .. to s tou pamětí(a pár dalších příkazů) jsme se ještě neučili a tak se to tu snažím pochopit..

 
Nahoru Odpovědět 4.2.2014 12:09
Avatar
Swixi
Neregistrovaný
Avatar
Odpovídá na Libor Šimo (libcosenior)
Swixi:

Každopádně jsem se jen tak mimo ptal dnes učitele jestli je tam potřeba ta paměť a říkal, že to jde i bez ní, že to bude třeba jeden "velký řetězec". Takže to půjde i jednoduše jak psal Tsukira :

do řetězce s1 na pozici p řetězec s2 + v s1 je alokován dostatečný prostor => sypu to přímo do s1 a žádnou další paměť není potřeba

např:

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

char *strcatat(char *s1, const char *s2, int p) {
if (p < 0 || strlen(s2) <= 0)
return NULL;

if (p >= strlen(s1)) {
strcpy(s1, strcat(s1, s2));
} else {
int i = 0;
const int s2_size = strlen(s2);
for (; i < s2_size; i++) {
s1[p+i+s2_size] = s1[p+i]; // posunu původní znak dozadu
s1[p+i] = s2[i]; // vložím jeden znak z s2
}
}
return s1;
}

něco v tom smyslu jsem to myslel akorát jsem to moc nechápal. Každopádně všem co pomáhaj moc děkuji. Byl jsem jinde na fóru (předtim) a tam ochota a slovo pomáhat moc asi neznali..

 
Nahoru Odpovědět 4.2.2014 12:14
Avatar
vitamin
Člen
Avatar
Odpovídá na Swixi
vitamin:

Ved hlucheucho ti tam pomáhal.

 
Nahoru Odpovědět 4.2.2014 12:21
Avatar
Swixi
Neregistrovaný
Avatar
Odpovídá na vitamin
Swixi:

vitamin to taky jel snadnou cestou . (libco každopádně to neber tak, že bych nebyl vděčnej. já se jen to snažím řešit cestou kterou nás učí teď učitel abych nedostal od něj 5 nebo něco podobného.)

vitamin :
char* strcatat(char *s1, const char *s2, int p) {
if(!strlen(s2) || p < 0)return 0;
if(strlen(s1) < p)memcpy(s1+strle­n(s1), s2, strlen(s2)+1);
else{
memmove(s1+p+strl­en(s2), s1+p, strlen(s1)-p+1);
memcpy(s1+p, s2, strlen(s2));
}
return s1;
}

To memmove jsem taky už trochu četl a myslel jsem že pomocí něho to půjde bez te alokace paměti akorát to ještě takle neznám.

 
Nahoru Odpovědět 4.2.2014 12:23
Avatar
Swixi
Neregistrovaný
Avatar
Odpovídá na vitamin
Swixi:

Jo tam jsem to řešil až po tomto co jsem to napsal zde. Ale před tim jsem psal i jiné úlohy jinde na forach než tady nebo na programujte.com ...

 
Nahoru Odpovědět 4.2.2014 12:25
Avatar
TsukiRa
Člen
Avatar
Odpovídá na Swixi
TsukiRa:

To co sem napsal předtím nefunguje moc dobře.

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

char *strcatat(char *s1, const char *s2, int p) {
    // hodnota NULL byl-li s2 prázdný nebo p záporné
    if (p < 0 || strlen(s2) <= 0)
        return NULL;

    // Je-li p větší, než délka s1, připojí s2 na konec s1.
    if (p >= strlen(s1)) {
        strcpy(s1, strcat(s1, s2));

    } else {
        int i;
        const int s2_size = strlen(s2); // strlen nepoužívat uvnitř cyklu!

        // původní část řetězce kopíruji dozadu, aby se uvolnilo
        // místo pro řetězec s2
        for (i = strlen(s1); i >= p; i--)
            s1[i+s2_size] = s1[i]; // kopíruju o délku s2

        // vkládám s2 na určené místo
        for (i = 0; i < s2_size; i++)
            s1[p+i] = s2[i];
    }
    return s1;
}

int main(void) {
    // alokace haldy
    char *tmp = (char *) malloc(100);
    // když alokace selže ukončit program
    if (tmp == NULL)
        return 1; // == ukončení programu s chybovým kódem

    strcpy(tmp, "Lorem sit amet, consectetuer elit.");
    strcatat(tmp, "ipsum dolor ", 6);
    printf("%s\n", tmp);

    // uvolnit alokovanou paměť !!vždy!!
    free(tmp);
    return 0;
}

Tak moc komentářů sem ještě nikdy nepsal :D

Nahoru Odpovědět 4.2.2014 12:33
Někdy je lepší zůstat v pondělí v posteli než celý týden ladit pondělní kód.
Avatar
Swixi
Neregistrovaný
Avatar
Odpovídá na TsukiRa
Swixi:

:O kvůli mě ? děkuji :D :D

 
Nahoru Odpovědět 4.2.2014 12:42
Avatar
TsukiRa
Člen
Avatar
Odpovídá na Swixi
TsukiRa:

Doufám, že neuděláš jen Ctrl+C Ctrl+V a hotovo. :D

Chápeš co a jak sa tam děje?

Nahoru Odpovědět 4.2.2014 12:50
Někdy je lepší zůstat v pondělí v posteli než celý týden ladit pondělní kód.
Avatar
vitamin
Člen
Avatar
Odpovídá na TsukiRa
vitamin:

strlen() vracia size_t čo je unsigned integer. Čiže nemôže vrátiť zápornú hodnotu :)
Čo sa týka strlen(), tak je to špeciálna funkcia ktorá je definovaná priamo v štandarde jazyka C/C++. To znamená že kompilátor môže použiť agresívnejšie optimalizácie ako pri funkciách definovaných mimo štandardu.
gcc, clang aj msvc presunú volanie strlen() mimo cyklus. Samozrejme len ak máš zapnuté optimalizácie.

 
Nahoru Odpovědět 4.2.2014 12:51
Avatar
Swixi
Neregistrovaný
Avatar
Odpovídá na TsukiRa
Swixi:

Z tvého popisování to chápu tak z 80%. neumím ty alokace paměti takže se na ně zaměřím.. určitě si vyhledám ty příkazy, které si tam použil a naučím se je (které neznám) a pak Si k tomu udělám zvlášť své zápisky a budu to dál studovat a pokoušet se to udělat.. Toť můj plán.

 
Nahoru Odpovědět 4.2.2014 12:56
Avatar
Swixi
Neregistrovaný
Avatar
Odpovídá na TsukiRa
Swixi:

Mám 2 dotazy :1 v čem to píšeš (mi musíme v Microsoft Visual Studio)
2 co je tohle ? : "Lorem sit amet, consectetuer elit."

jinak chtěl jsem to zkusit co to tedy děla a hlásí mi to warning s
#include <stdlib.h>
#include <string.h>
a pak eror :Error 3 error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "stdafx.h"' to your source? C:\Users\Swixi\Do­cuments\Visual Studio 2013\Projects\Con­soleApplicati­on4\ConsoleAp­plication4\Con­soleApplicati­on4.cpp 48 1 ConsoleApplication4

Co to sakra je ?

 
Nahoru Odpovědět 4.2.2014 13:22
Avatar
TsukiRa
Člen
Avatar
Odpovídá na Swixi
TsukiRa:

Editor používám Vim a překladač gcc.

Lorem ipsum je testovací text, wikipedie: "Lipsum".

Google radí: Hledej v nastavení projektu "předkompilované hlavičky" a vypni je (Project Options -> Precompiled header).

Nahoru Odpovědět 4.2.2014 13:31
Někdy je lepší zůstat v pondělí v posteli než celý týden ladit pondělní kód.
Avatar
MrPabloz
Člen
Avatar
Odpovídá na Swixi
MrPabloz:

"Lorem sit amet, consectetuer elit." je latinsky a využívá se k vyplnění nějakého textového pole textem, používá se klasicky všude kde chceš natlačit libovolný text, je jedno jaký, a potřebuješ jen vyzkoušet funkčnost všeho okolo a na textu ti nezáleží:)

Nahoru Odpovědět 4.2.2014 13:32
Harmonie těla a duše, to je to, oč se snažím! :)
Avatar
petrph
Člen
Avatar
petrph:

No jo, nejasný zadání a záludnej jazyk C. To se pak těžko píea ladí začátečnickej program. Nakonec jsem - aby ten příklad fungoval vytvořil dost primitivní ale snad bezpečný řešení - třeba se v tom i sám vyznáš :)
*#include <stdio.h>
#include <string.h>

char *strCatA(char *s1, const char *s2, int p) {
if (p < 0 || strlen(s2) == 0)
return NULL;
int i;
int l1=strlen(s1);int l2=strlen(s2);
char *s3=(char *) malloc(l1+l2+1);
if (p >= strlen(s1)) {
strcpy(s3,s1);
strcat(s3,s2);

} else {

for (i=0;i<p;i++)­s3[i]=s1[i];
for (i=0;i<l2;i++­)s3[p+i]=s2[i];
for (i=p;i<l1;i++­)s3[i+l2]=s1[i];
s3[l1+l2]='\0';

}

return s3;
}
int main()
{
char p;
char *q=(char *) malloc(200);
strcpy(q,"123­4589");
p=strCatA(q,"67",5);
printf("%s.\n",p);
p=strCatA(strCa­tA("Dům a","n",5)," kraji silnice", 100);
printf("%s.\n",p);
p=strCatA("1234589"­,"67",5);
printf("%s.\n",p);
p=strCatA("12345","­67",100);
printf("%s.\n",p);
return 0;
}

 
Nahoru Odpovědět 4.2.2014 13:36
Avatar
Odpovídá na TsukiRa
Libor Šimo (libcosenior):

"Opravdu se ty free za returnem provedou??"
Máš pravdu, ale ako to riešiť? Zatiaľ som na to neprišiel.

Máš nejaký nápad?

Nahoru Odpovědět 4.2.2014 13:43
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Swixi
Neregistrovaný
Avatar
Odpovídá na petrph
Swixi:

Přesně tak. Nejasný zadání na to je náš učitel machr.. to od tebe chápu z 80% zhruba též. vlastně jediné co tam nechápu je to strcpy,malloc,strlen koukám že je všichni používáte ale proč nám do háje učitel o nich nic neřekl.. někdy bych takový učitele střílel. dík moc všem

 
Nahoru Odpovědět 4.2.2014 13:54
Avatar
TsukiRa
Člen
Avatar
Odpovídá na Libor Šimo (libcosenior)
TsukiRa:

Podívaj sa na ten kód co sem psal. Alokuje se venku, adresa přijde jako s1 a tam nakonec vkládáš výsledek. Dočasnou paměť, pokud ji potřebuješ, dealokuješ před returnem.

Nahoru Odpovědět 4.2.2014 13:56
Někdy je lepší zůstat v pondělí v posteli než celý týden ladit pondělní kód.
Avatar
Odpovídá na TsukiRa
Libor Šimo (libcosenior):

T tvoje je mi jasné, ale kaď tam zadáš riadok z prvého príspevku:
printf("%s\n", strcatat(strca­tat("Dom a", "n", 5), " kraji silnice.", 100));
nefunguje to, pretože nie je alokovaná pamäť.

Nahoru Odpovědět 4.2.2014 14:00
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
TsukiRa
Člen
Avatar
Odpovídá na Swixi
TsukiRa:

strcpy je speciální funkce na kopírování řetězců
strlen - délka řetězce

  • proč objevovat kolo, když už existuje?

malloc si možeš představit jako speciální vytváření pole. V tomto příkladu můžeš s klidem použít místo

char *tmp = (char *) malloc(100);

tohle:

char tmp[100];

výsledek bude stejný: 100 znaků (char)

Nahoru Odpovědět 4.2.2014 14:02
Někdy je lepší zůstat v pondělí v posteli než celý týden ladit pondělní kód.
Avatar
Swixi
Neregistrovaný
Avatar
Odpovídá na TsukiRa
Swixi:

Jo, takhle to chápu dík. akorát to tmp je ještě co ?

 
Nahoru Odpovědět 4.2.2014 14:08
Avatar
TsukiRa
Člen
Avatar
Odpovídá na Libor Šimo (libcosenior)
TsukiRa:

Přesně, pokud nemáš paměť tak nemáš kde ukládat. V zadání je "Uvažujte, že v s1 je alokován dostatečný prostor." => strCatA( strCatA( „Dům a“, „n“, 5), „kraji silnice“, 100), “Dům na kraji silnice“) je nesprávné použití funkce, nemělo by to funguvat.

Nahoru Odpovědět 4.2.2014 14:09
Někdy je lepší zůstat v pondělí v posteli než celý týden ladit pondělní kód.
Avatar
TsukiRa
Člen
Avatar
Odpovídá na Swixi
TsukiRa:

tmp - temporary - dočasný, prostě název proměnné

Nahoru Odpovědět 4.2.2014 14:11
Někdy je lepší zůstat v pondělí v posteli než celý týden ladit pondělní kód.
Avatar
Swixi
Neregistrovaný
Avatar
Odpovídá na TsukiRa
Swixi:

Aha. ok. dík moc za vysvětlení i pomoc. Já se teď C budu učit asi odtud místo od učitele. : http://www.sallyx.org/sally/c/

 
Nahoru Odpovědět 4.2.2014 14:20
Avatar
Odpovídá na TsukiRa
Libor Šimo (libcosenior):

Viem to vyriešiť ale len čiastočne a to tak, že v podmienkach pred return-om uvoľním tie časti pamäti, ktoré sa returnom nevracajú.
napr.:

// funkcia na uvolnenie pamäti
void free_memory(char *p1, char *p2, char *p3)
{
    free(p1);
    free(p2);
    free(p3);
}

char * strcatat(char *s1, const char *s2, int p)
{
    -
    if (p > strlen(s1_dyn)) {
            strcat(s1_dyn, s2_dyn);
            free_memory(pom1, s2_dyn, pom2); // zmazanie nepotrebných
            return s1_dyn; // tento bohužiaľ ostane v pamäti do konca behu programu
    -
}
[/code
Editováno 4.2.2014 14:24
Nahoru Odpovědět 4.2.2014 14:21
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
coells
Redaktor
Avatar
coells:
char *strCatAt(char *s1, const char *s2, int p)
{
    char *dest = s1;
    while (p-- > 0 && *dest) dest++;
    while ((*dest++ = *s2++));
    return s1;
}
 
Nahoru Odpovědět 4.2.2014 14:29
Avatar
vitamin
Člen
Avatar
Odpovídá na Swixi
vitamin:

Na spravenie toho zadania nepotrebuješ poznať žiadne funkcie (stačí printf/puts ak chceš dáky výstup):

#include <stdio.h>

//zisti dlzku retazca
size_t my_strlen(const char* str){
    size_t i = 0;
    for(; str[i] != '\0'; ++i){}
    return i;
}

//prekopiruje retazec zdroj do retazca ciel
char* my_strcpy(char* ciel, const char* zdroj){
    while(*zdroj != '\0'){
        *ciel = *zdroj;
        ++ciel;
        ++zdroj;
    }
    *ciel = '\0';
    return ciel;
}

//prekopiruje retazec zdroj na koniec retazca ciel
char* my_strcat(char* ciel, const char* zdroj){

    while(*ciel != '\0')ciel++;  //najde koniec retazca
    return my_strcpy(ciel, zdroj);
}

char *strcatat(char *s1, const char *s2, int p) {
    if(p < 0 || my_strlen(s2) == 0)return 0;

    if (p >= my_strlen(s1)){
        my_strcat(s1, s2);
    }
    else{
        int i;
        const int s2_size = my_strlen(s2); // strlen nepoužívat uvnitř cyklu!

        // původní část řetězce kopíruji dozadu, aby se uvolnilo
        // místo pro řetězec s2
        for (i = my_strlen(s1); i >= p; i--)
            s1[i+s2_size] = s1[i]; // kopíruju o délku s2

        // vkládám s2 na určené místo
        for (i = 0; i < s2_size; i++)
            s1[p+i] = s2[i];
    }

    return s1;
}

int main(){

    char str[30]= "Dum a";

    strcatat( strcatat( str, "n", 4), " kraji silnice", 100);
    puts(str);
}
Editováno 4.2.2014 14:34
 
Nahoru Odpovědět 4.2.2014 14:33
Avatar
petrph
Člen
Avatar
Odpovídá na Swixi
petrph:

Aha.:[ Asi takhle nepočítej s tím že tu učitelé při výuce programování naučej úplně všechno. To se předpokládá že jako programátor si najdeš většinu věcí sám v online dokumentaci..Popisy funkcí,jejich parametry, návratové hodnoty atd, obvykle tam jsou i příklady.. Pamatuju dobu když jsem ještě kdysi začínal programoval v céčku, tak jsem měl vedle položenej asi 200 stránkovej manuál s těmahe knihovníma funkcema kde jsem si to hledal.

Ale ten malloc, ten musíš pochopit,jinak je ta práce s řetězci v C dost nebepečná. Jde o to že ty když deklaruješ v C text. řetězec s proměnnou typu char *s tak tím nemáš přiřazený žádný prostor kam by jsi ty znaky v řetězci mohl ukládat, takže jak jsi sám psal by sis mohl přepsat jiné informace. Čili až když napíšeš char *s = (char *) malloc(100);
tak až tím máš zajištěný prostor v proměnné s pro uložení až 100 znaků v text. řetězci..

 
Nahoru Odpovědět 4.2.2014 14:38
Avatar
Odpovídá na coells
Libor Šimo (libcosenior):

Veľmi pekne napísané, ale ešte tam chýba prilepenie odrezanej časti prvého reťazca na koniec reťazca.

Nahoru Odpovědět 4.2.2014 14:47
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
coells
Redaktor
Avatar
Odpovídá na Libor Šimo (libcosenior)
coells:

Díky za upozornění, Libco, ale nechybí. Funkce strcat dělá konkatenaci, nikoliv insert. Stejně tak NULL jako návratová hodnota je z hlediska designu knihovních C funkcí nesmysl.

 
Nahoru Odpovědět 4.2.2014 14:54
Avatar
Swixi
Neregistrovaný
Avatar
Odpovídá na petrph
Swixi:

Dík za vysvětlení :)

 
Nahoru Odpovědět 4.2.2014 15:17
Avatar
Odpovídá na coells
Libor Šimo (libcosenior):

Nemalo byť v kóde return dest; namiesto return s1; ?

Nahoru Odpovědět 4.2.2014 16:19
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 61 zpráv z 61.