🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

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
#308467
Author: Norbert Cielecki
Date: Tue, 19 Apr 2016 10:23
53 lines
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
#308468
Author: Tomasz Kaczanowski
Date: Tue, 19 Apr 2016 11:23
60 lines
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
#308469
Author: Mateusz Viste
Date: Tue, 19 Apr 2016 11:29
22 lines
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
#308470
Author: M.M.
Date: Tue, 19 Apr 2016 12:43
26 lines
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
#308471
Author: Mateusz Viste
Date: Tue, 19 Apr 2016 13:25
32 lines
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
#308472
Author: M.M.
Date: Tue, 19 Apr 2016 13:34
16 lines
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
#308473
Author: PawelS cbrbob(at)wbcd(dot)pl
Date: Sun, 24 Apr 2016 17:28
27 lines
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
#308474
Author: M.M.
Date: Sun, 24 Apr 2016 21:52
35 lines
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
#308477
Author: Dawid Bautsch
Date: Tue, 26 Apr 2016 08:48
11 lines
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
#308478
Author: Mateusz Viste
Date: Tue, 26 Apr 2016 09:49
20 lines
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
#308481
Author: Dawid Bautsch
Date: Tue, 26 Apr 2016 12:29
3 lines
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
#308482
Author: Mateusz Viste
Date: Tue, 26 Apr 2016 13:50
20 lines
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
#308489
Author: Dawid Bautsch
Date: Wed, 27 Apr 2016 12:39
3 lines
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
#308479
Author: (fir)
Date: Wed, 27 Apr 2016 18:08
24 lines
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
#308483
Author: Sebastian Biały
Date: Wed, 27 Apr 2016 18:47
12 lines
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
#308484
Author: M.M.
Date: Thu, 28 Apr 2016 06:34
60 lines
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
#308485
Author: Maciej Sobczak
Date: Thu, 28 Apr 2016 11:45
22 lines
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
#308486
Author: M.M.
Date: Thu, 28 Apr 2016 12:00
36 lines
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
#308475
Author: m.labanowicz
Date: Thu, 28 Apr 2016 16:24
28 lines
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
#308476
Author: M.M.
Date: Thu, 28 Apr 2016 17:05
32 lines
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
#308487
Author: Maciej Sobczak
Date: Fri, 29 Apr 2016 11:02
30 lines
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
#308480
Author: Adam Wysocki
Date: Fri, 29 Apr 2016 13:42
20 lines
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
#308488
Author: M.M.
Date: Fri, 29 Apr 2016 13:46
128 lines
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