NOVINKA: Získej 40 hodin praktických dovedností s AI – ZDARMA ke každému akreditovanému kurzu!
Avatar
Swixi
Neregistrovaný
Avatar
Swixi:3.2.2014 15:30

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
Lukáš Hruda
Tvůrce
Avatar
Odpovídá na
Lukáš Hruda:3.2.2014 15:45

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
Swixi:3.2.2014 16:01

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
Lukáš Hruda
Tvůrce
Avatar
Odpovídá na
Lukáš Hruda:3.2.2014 16:09

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
Swixi:3.2.2014 16:45

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
Lukáš Hruda
Tvůrce
Avatar
Odpovídá na
Lukáš Hruda:3.2.2014 16:54

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
Swixi:3.2.2014 17:09

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
Lukáš Hruda
Tvůrce
Avatar
Odpovídá na
Lukáš Hruda:3.2.2014 17:15

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:3.2.2014 17:16

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:3.2.2014 18:08

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):3.2.2014 20:42

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:3.2.2014 23:37

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

Člen
Avatar
:4.2.2014 1:59

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
Avatar
Odpovídá na
Libor Šimo (libcosenior):4.2.2014 5:42

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:4.2.2014 8:10

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:4.2.2014 8:33

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):4.2.2014 9:06

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:4.2.2014 9:21

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
Libor Šimo (libcosenior):4.2.2014 9:22

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:4.2.2014 9:26

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):4.2.2014 9:30

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
Libor Šimo (libcosenior):4.2.2014 9:39

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:4.2.2014 9:46

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):4.2.2014 10:04

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:4.2.2014 10:13

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):4.2.2014 11:25

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):4.2.2014 11:26

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

Člen
Avatar
:4.2.2014 11:42

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
Avatar

Člen
Avatar
:4.2.2014 11:52

libco: Opravdu se ty free za returnem provedou??

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

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:4.2.2014 12:14

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
vitamin:4.2.2014 12:21

Ved hlucheucho ti tam pomáhal.

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

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:4.2.2014 12:25

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

Člen
Avatar
Odpovídá na
:4.2.2014 12:33

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
Avatar
Swixi
Neregistrovaný
Avatar
Odpovídá na
Swixi:4.2.2014 12:42

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

 
Nahoru Odpovědět
4.2.2014 12:42
Avatar

Člen
Avatar
Odpovídá na
:4.2.2014 12:50

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
Avatar
vitamin
Člen
Avatar
Odpovídá na
vitamin:4.2.2014 12:51

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
Swixi:4.2.2014 12:56

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
Swixi:4.2.2014 13:22

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

Člen
Avatar
Odpovídá na
:4.2.2014 13:31

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
Avatar
MrPabloz
Člen
Avatar
Odpovídá na
MrPabloz:4.2.2014 13:32

"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:4.2.2014 13:36

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
Libor Šimo (libcosenior):4.2.2014 13:43

"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:4.2.2014 13:54

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

Člen
Avatar
Odpovídá na Libor Šimo (libcosenior)
:4.2.2014 13:56

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
Avatar
Odpovídá na
Libor Šimo (libcosenior):4.2.2014 14:00

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

Člen
Avatar
Odpovídá na
:4.2.2014 14:02

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
Avatar
Swixi
Neregistrovaný
Avatar
Odpovídá na
Swixi:4.2.2014 14:08

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

 
Nahoru Odpovědět
4.2.2014 14:08
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 50 zpráv z 61.