Thread View: pl.comp.lang.c
23 messages
23 total messages
Started by Norbert Cielecki
Tue, 19 Apr 2016 10:23
Rozmiar tablic zawierających łańcuch
Author: Norbert Cielecki
Date: Tue, 19 Apr 2016 10:23
Date: Tue, 19 Apr 2016 10:23
53 lines
2215 bytes
2215 bytes
Witam!
Czy ktoś mógłby mi wyjaśnić, dlaczego rozmiar tablic deklarowanych na
początku niżej przedstawianego programu nie jest brany pod uwagę i mogę
wpisać łańcuchy o dowolnym rozmiarze (akurat o to mi chodziło, ale
dlaczego tak jest)???
#include <stdio.h>
#include <string.h>
char *zaw_lanc(char *wsk_zrodl, char *wsk_wyznacz);
int main()
{
int ind=5;
int ind2=5;
char lancuch1[ind];
char lancuch2[ind2];
char *zancuch1;
char *zancuch2;
char *wsk_zwracany;
zancuch1=&lancuch1[ind];
zancuch2=&lancuch2[ind2];
printf("Podaj lancuch zrodlowy:\n");
scanf("%s", zancuch1);
printf("Podaj lancuch wyznacznikowy:\n");
scanf("%s", zancuch2);
printf("Lancuch zrodlowy to %s, a wyznacznikowy to %s.\n", zancuch1, zancuch2);
wsk_zwracany = zaw_lanc(zancuch1, zancuch2);
printf("Adres poczatku lancucha wyznacznikowego w lancuchu zrodlowym to %p.\n", wsk_zwracany);
return 0;
}
char *zaw_lanc(char *wsk_zrodl, char *wsk_wyznacz)
{
int p = strlen(wsk_zrodl);
int q = strlen(wsk_wyznacz);
char *znajda;
printf("Dlugosc lancucha zrodlowego %d, a wyznacznikowego %d.\n", p, q);
if(p>=q)
znajda = strstr(wsk_zrodl, wsk_wyznacz);
else
znajda = NULL;
return znajda;
}
--
pzdr NTC.
Re: Rozmiar tablic zawierających łańcuch
Author: Tomasz Kaczanowski
Date: Tue, 19 Apr 2016 11:23
Date: Tue, 19 Apr 2016 11:23
60 lines
2614 bytes
2614 bytes
W dniu 2016-04-19 12:23, Norbert Cielecki pisze:
> Witam!
> Czy ktoś mógłby mi wyjaśnić, dlaczego rozmiar tablic deklarowanych na
> początku niżej przedstawianego programu nie jest brany pod uwagę i mogę
> wpisać łańcuchy o dowolnym rozmiarze (akurat o to mi chodziło, ale
> dlaczego tak jest)???
>
>
> #include<stdio.h>
> #include<string.h>
> char *zaw_lanc(char *wsk_zrodl, char *wsk_wyznacz);
>
> int main()
> {
> int ind=5;
> int ind2=5;
> char lancuch1[ind];
> char lancuch2[ind2];
> char *zancuch1;
> char *zancuch2;
> char *wsk_zwracany;
>
> zancuch1=&lancuch1[ind];
> zancuch2=&lancuch2[ind2];
>
> printf("Podaj lancuch zrodlowy:\n");
> scanf("%s", zancuch1);
> printf("Podaj lancuch wyznacznikowy:\n");
> scanf("%s", zancuch2);
> printf("Lancuch zrodlowy to %s, a wyznacznikowy to %s.\n", zancuch1, zancuch2);
> wsk_zwracany = zaw_lanc(zancuch1, zancuch2);
> printf("Adres poczatku lancucha wyznacznikowego w lancuchu zrodlowym to %p.\n", wsk_zwracany);
>
> return 0;
> }
>
> char *zaw_lanc(char *wsk_zrodl, char *wsk_wyznacz)
> {
> int p = strlen(wsk_zrodl);
> int q = strlen(wsk_wyznacz);
> char *znajda;
>
> printf("Dlugosc lancucha zrodlowego %d, a wyznacznikowego %d.\n", p, q);
>
> if(p>=q)
> znajda = strstr(wsk_zrodl, wsk_wyznacz);
> else
> znajda = NULL;
>
> return znajda;
> }
>
Program jeśli działa, to przypadkowo. W C nie masz kontroli zakresów, to
programista ma o to dbac, aby sie zakresy zgadzały.
--
Kaczus
http://kaczus.ppa.pl
Re: Rozmiar tablic zawierających łańcuch
Author: Mateusz Viste
Date: Tue, 19 Apr 2016 11:29
Date: Tue, 19 Apr 2016 11:29
22 lines
2228 bytes
2228 bytes
On 19/04/2016 12:23, Norbert Cielecki wrote: > Czy ktoś mógłby mi wyjaśnić, dlaczego rozmiar tablic deklarowanych na > początku niżej przedstawianego programu nie jest brany pod uwagę i mogę > wpisać łańcuchy o dowolnym rozmiarze rozmiar jak najbardziej jest "brany pod uwagę", i system alokuje na stacku tyle ile podasz (ewentualnie nieznacznie więcej, zależnie od implementacji, wymogów dot. wyrównania danych do WORDa itp). fakt, że możesz zapisać więcej danych pod wskazany adres i je z powrotem odczytać to przypadek. niemniej jednak nadpisujesz coś innego (a co dokładnie, można tylko zgadywać). akurat "szczęśliwie" się złożyło że to co nadpisałeś też należy do twojej aplikacji, ale równie dobrze mógłbyś trafić na adres z zewnątrz, a to poskutkowałoby natychmiastowym segfaultem. słowem (tudzież zdaniem) - system alokuje to co mu każesz, ale to gdzie zapisujesz dane to już twoja odpowiedzialność. zamiast scanf() zalecałbym skorzystanie z fgets(), któremu możesz podać maksymalny rozmiar danych wejściowych, unikając tym samym przykrych sytuacji związanych z buffer overflow. Mateusz
Re: Rozmiar tablic zawierających łańcuch
Author: M.M.
Date: Tue, 19 Apr 2016 12:43
Date: Tue, 19 Apr 2016 12:43
26 lines
2756 bytes
2756 bytes
On Tuesday, April 19, 2016 at 1:29:07 PM UTC+2, Mateusz Viste wrote: > On 19/04/2016 12:23, Norbert Cielecki wrote: > > Czy ktoś mógłby mi wyjaśnić, dlaczego rozmiar tablic deklarowanych na > > początku niżej przedstawianego programu nie jest brany pod uwagę i mogę > > wpisać łańcuchy o dowolnym rozmiarze > > rozmiar jak najbardziej jest "brany pod uwagę", i system alokuje na > stacku tyle ile podasz (ewentualnie nieznacznie więcej, zależnie od > implementacji, wymogów dot. wyrównania danych do WORDa itp). > > fakt, że możesz zapisać więcej danych pod wskazany adres i je z powrotem > odczytać to przypadek. niemniej jednak nadpisujesz coś innego (a co > dokładnie, można tylko zgadywać). akurat "szczęśliwie" się złożyło że to > co nadpisałeś też należy do twojej aplikacji, ale równie dobrze mógłbyś > trafić na adres z zewnątrz, a to poskutkowałoby natychmiastowym segfaultem. > > słowem (tudzież zdaniem) - system alokuje to co mu każesz, ale to gdzie > zapisujesz dane to już twoja odpowiedzialność. zamiast scanf() > zalecałbym skorzystanie z fgets(), któremu możesz podać maksymalny > rozmiar danych wejściowych, unikając tym samym przykrych sytuacji > związanych z buffer overflow. Dawno nie używałem scanf, więc może coś mylę, ale chyba scanf też może pobierać rozmiar łańcuchów. Pozdrawiam
Re: Rozmiar tablic zawierających łańcuch
Author: Mateusz Viste
Date: Tue, 19 Apr 2016 13:25
Date: Tue, 19 Apr 2016 13:25
32 lines
2141 bytes
2141 bytes
On 19/04/2016 14:43, M.M. wrote:
> Dawno nie używałem scanf, więc może coś mylę, ale chyba scanf też może
> pobierać rozmiar łańcuchów.
tak, może, np:
char s[20];
scanf("%19s", s);
nie opisałem tego (choć powinienem był się spodziewać że wywoła to
reakcję) gdyż nie uważam tego za praktykę wartą polecenia. każda zmiana
rozmiaru s wymaga ręcznego dopasowania stringa formatującego scanf
(pamiętając o -1 dla null terminatora). prędzej czy później to się zemści.
przy fgets() sytuacja jest dużo jaśniejsza:
char s[20];
fgets(s, sizeof(s) - 1, stdin);
lub:
#define BUFSZ 20
char *s;
s = malloc(BUFSZ);
if (s != NULL) fgets(s, BUFZ - 1, stdin);
w obu przypadkach jakiekolwiek dopasowanie wielkości bufora ma z
automatu wpływ na ilość danych którą będzie tolerował fgets(). przy
scanf() nie sądzę by była taka możliwość, standard nie przewidział
bowiem istnienia czegoś w stylu snscanf().
Mateusz
Re: Rozmiar tablic zawierających łańcuch
Author: M.M.
Date: Tue, 19 Apr 2016 13:34
Date: Tue, 19 Apr 2016 13:34
16 lines
1973 bytes
1973 bytes
On Tuesday, April 19, 2016 at 3:26:01 PM UTC+2, Mateusz Viste wrote:
> On 19/04/2016 14:43, M.M. wrote:
> > Dawno nie używałem scanf, więc może coś mylę, ale chyba scanf też może
> > pobierać rozmiar łańcuchów.
>
> tak, może, np:
>
> char s[20];
> scanf("%19s", s);
>
> ....prędzej czy później to się zemści.
By się dało zrobić bezpieczniej, ale w czasach gdy w każdej bibliotece
jest pełno strumieni i dynamicznych łańcuchów, też nie uważam aby było
warto się rozpisywać.
Pozdrawiam
Re: Rozmiar tablic zawierających łańcuch
Author: PawelS cbrbob(at)wbcd(dot)pl
Date: Sun, 24 Apr 2016 17:28
Date: Sun, 24 Apr 2016 17:28
27 lines
1705 bytes
1705 bytes
Mateusz Viste pisze:
> On 19/04/2016 14:43, M.M. wrote:
>> Dawno nie używałem scanf, więc może coś mylę, ale chyba scanf też może
>> pobierać rozmiar łańcuchów.
>
> tak, może, np:
>
> char s[20];
> scanf("%19s", s);
Brzydkie to, ale w przypadku scanf
też można podobnie ograniczyć rozmiar łańcucha:
#define BUFSZ "19"
char s[atoi(BUFSZ)+1]; /* warning: ISO C90 forbids variable-size array 's' */
scanf("%"BUFSZ"s", s);
> przy fgets() sytuacja jest dużo jaśniejsza:
>
> char s[20];
> fgets(s, sizeof(s) - 1, stdin);
>
> lub:
>
> #define BUFSZ 20
> char *s;
> s = malloc(BUFSZ);
> if (s != NULL) fgets(s, BUFZ - 1, stdin);
Re: Rozmiar tablic zawierających łańcuch
Author: M.M.
Date: Sun, 24 Apr 2016 21:52
Date: Sun, 24 Apr 2016 21:52
35 lines
2369 bytes
2369 bytes
On Sunday, April 24, 2016 at 7:28:48 PM UTC+2, PawelS cbrbob(at)wbcd(dot)pl wrote:
> Mateusz Viste pisze:
> > On 19/04/2016 14:43, M.M. wrote:
> >> Dawno nie używałem scanf, więc może coś mylę, ale chyba scanf też może
> >> pobierać rozmiar łańcuchów.
> >
> > tak, może, np:
> >
> > char s[20];
> > scanf("%19s", s);
>
> Brzydkie to, ale w przypadku scanf
> też można podobnie ograniczyć rozmiar łańcucha:
> #define BUFSZ "19"
> char s[atoi(BUFSZ)+1]; /* warning: ISO C90 forbids variable-size array 's' */
> scanf("%"BUFSZ"s", s);
>
> > przy fgets() sytuacja jest dużo jaśniejsza:
> >
> > char s[20];
> > fgets(s, sizeof(s) - 1, stdin);
> >
> > lub:
> >
> > #define BUFSZ 20
> > char *s;
> > s = malloc(BUFSZ);
> > if (s != NULL) fgets(s, BUFZ - 1, stdin);
#define BUFSZ 20
char s1[20];
char s2[BUFSZ];
sprintf(s1,"%%%ds",BUFSZ-1);
scanf( s1, s2 );
s2[BUFSZ-1] = 0;
Re: Rozmiar tablic zawierających łańcuch
Author: Dawid Bautsch
Date: Tue, 26 Apr 2016 08:48
Date: Tue, 26 Apr 2016 08:48
11 lines
2084 bytes
2084 bytes
>fakt, że możesz zapisać więcej danych pod wskazany adres i je z powrotem odczytać to przypadek. niemniej jednak nadpisujesz coś innego (a co dokładnie, można tylko zgadywać). akurat "szczęśliwie" się złożyło że to co nadpisałeś też należy do twojej aplikacji, ale równie dobrze mógłbyś trafić na adres z zewnątrz, a to poskutkowałoby natychmiastowym segfaultem. To co napisałeś to bzdury. Polecam zapoznać się z tematem wirtualnej przestrzeni adresowej. Potem ludzie czytają takie wpisy i wierzą a tacy jak Ty śmiecą internet. Taka sytuacja mogłaby mieć miejsce tylko w trybie rzeczywistym (MS-DOS i podobne). W Windows nie nastąpiłby segfault tylko raczej access-violation. Naruszenie dostępu.
Re: Rozmiar tablic zawierających łańcuch
Author: Mateusz Viste
Date: Tue, 26 Apr 2016 09:49
Date: Tue, 26 Apr 2016 09:49
20 lines
1804 bytes
1804 bytes
Czyżby powrót "profesora"? Od dłuższego czasu grupa nie zaznała tej przyjemności. On 26/04/2016 10:48, Dawid Bautsch wrote: > Polecam zapoznać się z tematem wirtualnej przestrzeni adresowej. To czy przestrzeń adresowa jest wirtualna nie ma najmniejszego znaczenia w omawianym kontekście. Adres należy do aplikacji lub nie. > Taka sytuacja mogłaby mieć miejsce tylko w trybie rzeczywistym (MS-DOS i podobne). Tryb rzeczywisty to dokładnie sytuacja w której naruszenie dostępu nigdy nie nastąpi. > W Windows nie nastąpiłby segfault tylko raczej access-violation. Naruszenie dostępu. segfault, access-violation, naruszenie dostępu czy też "NOP", to wszystko różne określenia tego samego. Mateusz
Re: Rozmiar tablic zawierających łańcuch
Author: Dawid Bautsch
Date: Tue, 26 Apr 2016 12:29
Date: Tue, 26 Apr 2016 12:29
3 lines
1607 bytes
1607 bytes
W modelu flat cała przestrzeń adresowa należy do aplikacji, nie możesz naruszyć innego programu pisząc po pamięci. W trybie rzeczywistym, pamięć jest współdzielona przez wszystkie programy, dlatego zmieniając randomowo jej zawartość możesz wpłynąć na działanie innego programu.
Re: Rozmiar tablic zawierających łańcuch
Author: Mateusz Viste
Date: Tue, 26 Apr 2016 13:50
Date: Tue, 26 Apr 2016 13:50
20 lines
2120 bytes
2120 bytes
On 26/04/2016 14:29, Dawid Bautsch wrote: > W modelu flat cała przestrzeń adresowa należy do aplikacji, nie możesz naruszyć innego programu pisząc po pamięci. to dość naciągnięte - i nieprawdziwe - uproszczenie. najwyraźniej mylisz model flat z pamięcią wirtualną. "flat" oznacza tyle co "linearna przestrzeń adresowa". wbrew temu co myślisz, nie wszystko jest VAX'em. > W trybie rzeczywistym, pamięć jest współdzielona przez wszystkie programy, dlatego zmieniając randomowo jej zawartość możesz wpłynąć na działanie innego programu. nikt w tym wątku nie twierdził inaczej. zastanawiam się tylko w jaki sposób ma to pomóc OP? kilka godzin temu odważnie skomentowałeś moją wypowiedź jako "bzdury" - chętnie dowiem się na czym te bzdury polegają, bo dotychczas wykazałeś się jedynie brakiem umiejętności czytania ze zrozumieniem i chamstwem. dodam, że to grupa dot. języka C, a nie jakiejś-tam szczególnej implementacji. Mateusz
Re: Rozmiar tablic zawierających łańcuch
Author: Dawid Bautsch
Date: Wed, 27 Apr 2016 12:39
Date: Wed, 27 Apr 2016 12:39
3 lines
1521 bytes
1521 bytes
Wypowiedzi w tym temacie zakończyłem. Powiedz mi jeszcze tylko gdzie te chamstwo? Boli Cię tylko co najwyżej urażona duma i będziesz teraz próbował mi udowodnić jak to bardzo się mylę a Twoja wiedza przerasta moją. EOT.
Re: Rozmiar tablic zawierających łańcuch
Author: (fir)
Date: Wed, 27 Apr 2016 18:08
Date: Wed, 27 Apr 2016 18:08
24 lines
2825 bytes
2825 bytes
W dniu wtorek, 26 kwietnia 2016 11:49:07 UTC+2 użytkownik Mateusz Viste napisał: > Czyżby powrót "profesora"? Od dłuższego czasu grupa nie zaznała tej > przyjemności. > zgadza sie, od około roku, moze troche wiecej i szczerze mowiac moj 'powrot' tutaj jest nieco watpliwy, wynika to z tego ze sie wszystkiego nauczylem i nie ma o czym gadac troche zartuje ale faktycznie to co mnie teraz interesuje to bylaby bardziej grafika/fizyka/mechanika w gamedevia a tu nie ma z kim pogadac ntt; wogole w necie ciezko znalezc kogokoliwiek do pogadania na te tematy - bardzo niedobrze ale co poradzic - pisalem zreszta o tym nie raz ale nic sie wlasnie nie zmiania, Ktos chetny do pogadania na nieco glebszym poziomie na tematy procedur graficznych, fizyki, mechaniki, fabuly w grach? bardzo chętnie - ale nikogo nie ma na forach dla gamedevu obracane są lamerskie tematy wlasnie paradoksalnie jakby nie z tego co wymienilem i te fora tez sie nie nadają (zwlaszcza ze jako admini siedzą tam typowe buraki z niodpartą potrzebą zbanowania wszystkich madrzejszych od siebie) takie zycie jak ktos zna jakies naprawde dobre forum gdzie mozna podniesc wiedze zwlaszcza z tych tematów od poziomu sredniozaawansowanego wzwyź to chetnie tam dołacze (ten post wyglada troche na 'dlugi post o niczym' ale chcialem napisac czemu tu nie pisuje - jak mowie o gamedevie i na poziomie chętnie - tylko gdzie takie forum ;CC)
Re: Rozmiar tablic zawierających łańcuch
Author: Sebastian Biały
Date: Wed, 27 Apr 2016 18:47
Date: Wed, 27 Apr 2016 18:47
12 lines
1656 bytes
1656 bytes
On 2016-04-26 14:29, Dawid Bautsch wrote: > W modelu flat cała przestrzeń adresowa należy do aplikacji, nie możesz naruszyć innego programu pisząc po pamięci. To nie ma nic do rzeczy w omawianym przypadku. Tutaj chodzi o to że istnieją fragemnty *Twojej* pamięci wirtualnej do których masz zakazany dostęp. Pomijając standardowy GPF, jest to nawet użyteczne w debugu: https://pl.wikipedia.org/wiki/Electric_Fence Natomiast ponieważ strony są zazwyczaj dośc spore to małe wyjścia poza zakres walidnej pamięci bywaja przeoczone. Sugeruje zapoznac się z valgrindem który robi to dokładniej niż hardware cpu.
Re: Rozmiar tablic zawierających łańcuch
Author: M.M.
Date: Thu, 28 Apr 2016 06:34
Date: Thu, 28 Apr 2016 06:34
60 lines
3748 bytes
3748 bytes
On Wednesday, April 27, 2016 at 8:49:24 PM UTC+2, Sebastian Biały wrote:
> On 2016-04-26 14:29, Dawid Bautsch wrote:
> > W modelu flat cała przestrzeń adresowa należy do aplikacji, nie możesz naruszyć innego programu pisząc po pamięci.
>
> To nie ma nic do rzeczy w omawianym przypadku. Tutaj chodzi o to że
> istnieją fragemnty *Twojej* pamięci wirtualnej do których masz zakazany
> dostęp. Pomijając standardowy GPF, jest to nawet użyteczne w debugu:
>
> https://pl.wikipedia.org/wiki/Electric_Fence
>
> Natomiast ponieważ strony są zazwyczaj dośc spore to małe wyjścia poza
> zakres walidnej pamięci bywaja przeoczone. Sugeruje zapoznac się z
> valgrindem który robi to dokładniej niż hardware cpu.
Kiedyś napisałem se szablon-tablicę z sumą kontrolną.
Każde wywołanie metody odczytującej (czyli metody const)
sprawdza, czy suma jest poprawna. Każde wywołanie metody
zapisującej (nie const), podobnie jak w przypadku metody
odczytującej też sprawdza czy suma jest poprawna, potem
modyfikuje dane i oblicza sumę ponowne. Czyli taki
std::vector z sumą kontrolną.
Niby to jest wygodne, bo są przedefiniowane operatory, niby to
jest wydajne, bo zrealizowane jako szablon C++. Jednak w praktyce
gdy tego używałem to nabierałem wstrętu z dwóch powodów. Po
pierwsze, składnia szablonów w C++ jest okropna, bardzo długie
definicje typów, jeden i ten znaczek, zależnie od kontekstu,
pełni 50 różnych ról. Po drugie, o ile się nie mylę, nie można
obsłużyć operatora indeksowania [] (lub operatora wywołania
funkcji () którego można użyć jako operatora indeksowania) po
modyfikacji danych. Gdy ten operator jest const, to taka potrzeba
nie zachodzi, natomiast gdy jest nie-const, to brakuje takiej
możliwości (albo ja jej nie znam):
class X {
public:
typ& operator[] ( const int i ) nie-const {
printf("yestem operator[]\n");
return tablica[i];
}
after typ& operator[] (const int i ) {
printf("yestem after-operator[]\n");
this->sum = 0;
for( int i=0 ; i<size() ; i++ )
this->sum ^= tablica[i];
}
};
X<int> x( size );
x[ 13 ] = 4;
Da wynik:
// yestem operator[]
// yestem after-operator[]
Można to jakoś wygodnie obsłużyć, bez wywoływania dodatkowej funkcji
po każdym operatorze[] nie-const?
Pozdrawiam
Re: Rozmiar tablic zawierających łańcuch
Author: Maciej Sobczak
Date: Thu, 28 Apr 2016 11:45
Date: Thu, 28 Apr 2016 11:45
22 lines
2437 bytes
2437 bytes
> Po > pierwsze, składnia szablonów w C++ jest okropna Chyba nie ma języka, w którym składnia szablonów byłaby satysfakcjonująca we wszystkich użyciach. Oczywiście mówimy o szablonach o możliwościach porównywalnych z C++. > pełni 50 różnych ról. Po drugie, o ile się nie mylę, nie można > obsłużyć operatora indeksowania [] (lub operatora wywołania > funkcji () którego można użyć jako operatora indeksowania) po > modyfikacji danych. Nie takie rzeczy się da. Zamiast typ& zwróć obiekt innego typu (nazwijmy to proxy), na którym przeciążysz operator przypisania. Ten obiekt proxy oczywiście musi pamiętać na jakim wektorze pracuje (i na którym indeksie), ale w operatorze przypisania tego pośredniego typu można sobie zrobić dowolną akcję na taką okoliczność: > X<int> x( size ); > x[ 13 ] = 4; > > Da wynik: > > // yestem operator[] > // yestem after-operator[] -- Maciej Sobczak * http://www.inspirel.com
Re: Rozmiar tablic zawierających łańcuch
Author: M.M.
Date: Thu, 28 Apr 2016 12:00
Date: Thu, 28 Apr 2016 12:00
36 lines
3157 bytes
3157 bytes
On Thursday, April 28, 2016 at 1:45:20 PM UTC+2, Maciej Sobczak wrote: > > Po > > pierwsze, składnia szablonów w C++ jest okropna > > Chyba nie ma języka, w którym składnia szablonów byłaby satysfakcjonująca we wszystkich użyciach. Oczywiście mówimy o szablonach o możliwościach porównywalnych z C++. Chyba masz rację, póki co nie spotkałem się nigdy z ładnym rozwiązaniem szablonów, tzn z elegancką i zwartą składnią. Może to tak musi być. > > > pełni 50 różnych ról. Po drugie, o ile się nie mylę, nie można > > obsłużyć operatora indeksowania [] (lub operatora wywołania > > funkcji () którego można użyć jako operatora indeksowania) po > > modyfikacji danych. > > Nie takie rzeczy się da. Zamiast typ& zwróć obiekt innego typu (nazwijmy to proxy), na którym przeciążysz operator przypisania. Ten obiekt proxy oczywiście musi pamiętać na jakim wektorze pracuje (i na którym indeksie), ale w operatorze przypisania tego pośredniego typu można sobie zrobić dowolną akcję na taką okoliczność: Tak, o tym to nawet myślałem :) Ale to kolejny szablon w szablonie i odpuściłem sobie. Wywaliłem operatory indeksowania i dałem metody get i set. Jednak gdy tablica zawiera obiekty, a nie proste typy, to się ciężko robi. Trzeba dać: T t = tbl.get( i ); t.metoda(); tbl.set( i , t ); zamiast zwartego: tbl[ i ].metoda(); Czy obiekt 'proxy' spełniłby swoją rolę gdy się wywołuje metody? Może by spełnił... musiałby nadpisywać wszystkie metody typu T... Hmmmm muszę podtrzymać to co pisałem wyżej, 'after[]' byłby wygodniejszy. Pozdrawiam
Re: Rozmiar tablic zawierających łańcuch
Author: m.labanowicz
Date: Thu, 28 Apr 2016 16:24
Date: Thu, 28 Apr 2016 16:24
28 lines
2021 bytes
2021 bytes
> #define BUFSZ 20
> char s1[20];
> char s2[BUFSZ];
> sprintf(s1,"%%%ds",BUFSZ-1);
> scanf( s1, s2 );
> s2[BUFSZ-1] = 0;
Wykorzystanie preprocesora:
--{beg:foo.c}------------------------
#include <stdio.h>
#include <stdlib.h>
#define DEF2STR(x) DEF2STR_(x)
#define DEF2STR_(x) #x
int main(void)
{
#define BUFSZ 20
char s[BUFSZ + 1];
scanf(s, "%" DEF2STR(BUFSZ) "s");
s[BUFSZ] = '\0';
return EXIT_SUCCESS;
}
--{end:foo.c}------------------------
Pozdrawiam
--
Maciek
Re: Rozmiar tablic zawierających łańcuch
Author: M.M.
Date: Thu, 28 Apr 2016 17:05
Date: Thu, 28 Apr 2016 17:05
32 lines
2261 bytes
2261 bytes
On Thursday, April 28, 2016 at 6:24:27 PM UTC+2, m.laba...@gmail.com wrote:
> > #define BUFSZ 20
> > char s1[20];
> > char s2[BUFSZ];
> > sprintf(s1,"%%%ds",BUFSZ-1);
> > scanf( s1, s2 );
> > s2[BUFSZ-1] = 0;
>
> Wykorzystanie preprocesora:
>
> --{beg:foo.c}------------------------
> #include <stdio.h>
> #include <stdlib.h>
> #define DEF2STR(x) DEF2STR_(x)
> #define DEF2STR_(x) #x
> int main(void)
> {
> #define BUFSZ 20
> char s[BUFSZ + 1];
> scanf(s, "%" DEF2STR(BUFSZ) "s");
> s[BUFSZ] = '\0';
> return EXIT_SUCCESS;
> }
> --{end:foo.c}------------------------
>
> Pozdrawiam
>
> --
> Maciek
Można i tak jak napisałeś.
Pozdrawiam
Re: Rozmiar tablic zawierających łańcuch
Author: Maciej Sobczak
Date: Fri, 29 Apr 2016 11:02
Date: Fri, 29 Apr 2016 11:02
30 lines
3228 bytes
3228 bytes
On Thursday, April 28, 2016 at 2:00:37 PM UTC+2, M.M. wrote: > Czy obiekt 'proxy' spełniłby swoją rolę gdy się wywołuje metody? Może > by spełnił... musiałby nadpisywać wszystkie metody typu T... Hmmmm > muszę podtrzymać to co pisałem wyżej, 'after[]' byłby wygodniejszy. A można jeszcze inaczej. Zamiast zmuszać vector, żeby udostępnił obiekt *na zewnątrz*, można zrobić tak, że vector przyjmie "operację" (czytaj: funktor, lambda, itp.), którą wykona *wewnątrz*, na wskazanym obiekcie. Wtedy, mając kontrolę nad tym kiedy to się robi (a robi się cały czas w jakiejś funkcji vectora), może sobie otoczyć tą operację dowolnymi wstawiami przed albo po. Czyli zamiast mówić "daj mi obiekt", mówisz "zrób to coś na tamtym czymś". Czyli zamiast: T t = tbl.get(i); cośtamcośtam(t); tbl.set(i, t); robisz tak: tbl.update(i, cośtamcośtam); gdzie cośtamcośtam to funktor, lambda, itp., który zostanie zaaplikowany na obiekcie na wskazanej pozycji, *po czym* funkcja update może zrobić cokolwiek jeszcze potrzeba. Ciekawostka: tak właśnie działały kontenery w Adzie zanim, po dekadzie ciężkiego drapania się po głowie, wymyślono w końcu jak zrobić ładny operator indeksowania ale tak, żeby nie było możliwości wycieknąć na zewnątrz referencji do wskazanego obiektu. Przykład jest tutaj: http://wiki.ada-dk.org/ada.containers.vectors#vectorsupdate_element Pomyśl, że operacja Update_Element może zrobić cokolwiek przed i po zaaplikowaniu przekazanej operacji Process. Można to samo zrobić w C++. -- Maciej Sobczak * http://www.inspirel.com
Re: Rozmiar tablic zawierających łańcuch
Author: Adam Wysocki
Date: Fri, 29 Apr 2016 13:42
Date: Fri, 29 Apr 2016 13:42
20 lines
1659 bytes
1659 bytes
Dawid Bautsch <attezione@gmail.com> wrote: > To co napisałeś to bzdury. Polecam zapoznać się z tematem wirtualnej > przestrzeni adresowej. Potem ludzie czytają takie wpisy i wierzą a tacy > jak Ty śmiecą internet. Ale wiesz, co to jest segfault, prawda? > Taka sytuacja mogłaby mieć miejsce tylko w trybie rzeczywistym (MS-DOS i podobne). Bzdura, w trybie rzeczywistym nie ma ochrony pamięci i nie wystąpi segfault. > W Windows nie nastąpiłby segfault tylko raczej access-violation. Naruszenie dostępu. 1. Nikt nie mówi o Windows ani o konkretnej platformie. 2. Doczytaj czym jest segfault, zanim zaczniesz zaśmiecać Internet. -- http://www.chmurka.net/
Re: Rozmiar tablic zawierających łańcuch
Author: M.M.
Date: Fri, 29 Apr 2016 13:46
Date: Fri, 29 Apr 2016 13:46
128 lines
5676 bytes
5676 bytes
On Friday, April 29, 2016 at 1:02:12 PM UTC+2, Maciej Sobczak wrote:
> On Thursday, April 28, 2016 at 2:00:37 PM UTC+2, M.M. wrote:
>
> > Czy obiekt 'proxy' spełniłby swoją rolę gdy się wywołuje metody? Może
> > by spełnił... musiałby nadpisywać wszystkie metody typu T... Hmmmm
> > muszę podtrzymać to co pisałem wyżej, 'after[]' byłby wygodniejszy.
>
> A można jeszcze inaczej. Zamiast zmuszać vector, żeby udostępnił obiekt *na zewnątrz*, można zrobić tak, że vector przyjmie "operację" (czytaj: funktor, lambda, itp.), którą wykona *wewnątrz*, na wskazanym obiekcie. Wtedy, mając kontrolę nad tym kiedy to się robi (a robi się cały czas w jakiejś funkcji vectora), może sobie otoczyć tą operację dowolnymi wstawiami przed albo po.
>
> Czyli zamiast mówić "daj mi obiekt", mówisz "zrób to coś na tamtym czymś".
>
> Czyli zamiast:
>
> T t = tbl.get(i);
> cośtamcośtam(t);
> tbl.set(i, t);
>
> robisz tak:
>
> tbl.update(i, cośtamcośtam);
>
> gdzie cośtamcośtam to funktor, lambda, itp., który zostanie zaaplikowany na obiekcie na wskazanej pozycji, *po czym* funkcja update może zrobić cokolwiek jeszcze potrzeba.
Przyznaję, że o takiej możliwości nie pomyślałem. Do kontenera można
przekazać parę:
1) indeks obiektu,
2) wskaźnik na metodę składową nie-const.
Kontener wywoła metodę na rzecz obiektu, a potem wykona swój 'after update'.
Nie znam perfekcyjnie wszystkich zawiłości szablonów.
Nie używam C++11, więc lambdy odpadają. Czy można ten cel osiągnąć
bez nadmiernej pisaniny? Można napisać (w miarę) uniwersalny
szablon który pobierze 'każdy' wskaźnik na składową?
Kolejna sprawa, czy kod napisany w ten sposób będzie wydajny?
Czy kompilator zauważy że przekazuje się wskaźnik na konkretną
metodę i wygeneruje zwykły call?
Hmmm o lambdach kiedyś czytałem, jakiś programik napisałem z ich
użyciem, a teraz nawet składni nie znam na pamięć. Czy składnia z
użyciem lambdy rozwiąze ten problem w miarę elegancko i bez nadmiernej
ilości kodu? Hmmm może powinienem używać C++11...
Poniższy kod nawet (wydaje się że) działa. Czy jest elegancki?
Moim zdaniem nie jest elegancki, ale od biedy można wytrzymać.
class MyT {
int x;
public:
MyT() : x(0) {
}
int value() const { return x; }
void add( const int v ) { x += v; }
void add( const int v[] , const int size ) {
for( int i=0 ; i<size ; i++ )
x += v[i];
}
};
int mkCrc( const void *data , int size ) {
return 0; // poprawny kod crc
}
template<typename T, int SIZE>
class MyVector {
private:
T data[SIZE];
int crc;
private:
int mkCrc() const {
return ::mkCrc( data , sizeof(data) );
}
void test() const {
if( crc != mkCrc() ) abort();
}
void test( const int i ) const {
test();
if( i < 0 ) abort();
if( i >= SIZE ) abort();
}
void update() {
crc = mkCrc();
}
public:
MyVector() {
update();
}
const T& operator[] (const int i) const {
test( i );
return data[i];
}
void set( const int i , const T &t ) {
test(i);
data[i] = t;
update();
}
void operator()( const int i , void (T::*f)(const int) , const int v) {
test(i);
(data[i].*f)(v);
update();
}
void operator()( const int i , void (T::*f)(const int[],const int) , const int tab[] , const int size) {
test(i);
(data[i].*f)(tab,size);
update();
}
};
int main(int argc, char *argv[])
{
MyVector<MyT,4> v;
v( 1 , &MyT::add , 3 );
const int tab[3] = {1,2,3};
v( 2 , &MyT::add , tab , sizeof(tab)/sizeof(tab[0]) );
return 0;
}
Pozdrawiam
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads