|
| Problem med... ææ... Fra : Henrik Koksby Hansen |
Dato : 09-06-02 16:02 |
|
Hej.
Så er jeg her igen.
Jeg har endnu et - synes jeg - underligt problem. Og jeg håber
selvfølgelig, at der er nogle af jer, der kan gennemskue dets årsag.
Her er noget kode:
---- klip ----
void archive::reg() {
char last[30];
char first[20];
char number[8];
char ad[40];
char e[20];
if (testbetingelse == true){
fflush(stdin); // flush input buffer
cout << "Enter last name : "; cin.getline(last, 31);
cout << "Enter first name: "; cin.getline(first, 21);
cout << "Enter phonenumber: "; cin.getline(number, 9);
cout << "Enter address: "; cin.getline(ad, 41);
cout << "Enter e-mail: "; cin.getline(e, 21);
doReg(n, last, first, atoi(number), ad, e);
}
else cout << "Error: Already registered.\n";
}
---- klip ----
void archive::doReg(int const n, char *last, char *first, int number,
char *ad, char *e) {
strcpy(Students[n]->lastName,last);
strcpy(Students[n]->firstName,first);
Students[n]->phoneNumber=number;
strcpy(Students[n]->address,ad);
strcpy(Students[n]->eMail,e);
}
---- klip slut ----
- Det er meningen, at der skal indlæses information fra brugeren,
hvorefter funktionen reg() kaldes, med de indlæste værdier, som
parametre.
Det sjove er så, at fornavnet ikke bliver registreret, hvis
telefonnummeret er 8+ cifre. Alle andre værdier bliver overført
perfekt...
- Men hvorfor? Og hvorfor lige fornavnet?
MVH
Henrik
| |
Claus Rasmussen (09-06-2002)
| Kommentar Fra : Claus Rasmussen |
Dato : 09-06-02 16:13 |
|
Henrik Koksby Hansen wrote:
> - Men hvorfor? Og hvorfor lige fornavnet?
Umiddelbart laver du den fejl, at underdimensionere alle dine char arrays.
F.eks
char number[8];
...
cin.getline(number, 9);
Dit 'number' array består af 8 char, men du tillader indlæsning af
9. Gør i stedet sådan:
char number[8 + 1];
Der gør det tydeligt, at 'number' har plads til 8 _tegn_ plus een
nul-terminator. Du kan så også ændre din getline til
cin.getline(number, sizeof(number));
Så du kan nøjes med at angive længen af 'number' eet sted. Det
virker dog kun hvis erklæringen af 'number' er i scope, når du
bruger 'sizeof', så det kan være, at du i stedet skal gøre sådan:
const int NUMBER_SIZE = 8;
...
char number[NUMBER_SIZE + 1];
...
cin.getline(number, NUMBER_SIZE + 1);
Desuden mangler du at tjekke for fejl efter hver læseoperation.
Det gør du sådan:
if (cin.getline(number, NUMBER_SIZE + 1))
// ok
else
// fejl
MVH
-Claus
| |
Henrik Koksby Hansen (09-06-2002)
| Kommentar Fra : Henrik Koksby Hansen |
Dato : 09-06-02 16:39 |
|
>Umiddelbart laver du den fejl, at underdimensionere alle dine char arrays.
>F.eks
>
> char number[8];
>
> ...
>
> cin.getline(number, 9);
>
>Dit 'number' array består af 8 char, men du tillader indlæsning af
>9. Gør i stedet sådan:
>
> char number[8 + 1];
>
[...]
Jeg ved så ikke om jeg har forstået det korrekt, men
cin.getline(number, n)
indlæser n-1 tegn.
Men hvad jeg ikke forstår er, hvorfor arrayet så nødvendigvis må være
array[n] og ikke array[n-1] ...
I alle andre tilfælde (hvor getline ikke benyttes) laver man da
array[n] hvis det skal indeholde n tegn. ?
(eller array[n-1] hvis det skal indeholde n-1 tegn ??)
MVH
Henrik
| |
Claus Rasmussen (09-06-2002)
| Kommentar Fra : Claus Rasmussen |
Dato : 09-06-02 16:49 |
|
Henrik Koksby Hansen wrote:
> Jeg ved så ikke om jeg har forstået det korrekt, men
>
> cin.getline(number, n)
>
> indlæser n-1 tegn.
Nemlig. 'cin.getlinge(number, n)' indlæser 'n-1' tegn og tilføjer
derefter ikke-tegnet 0, der bruges som afslutter af strengen. Dvs.
i alt 'n' chars.
Her er et eksempel:
char s[] = "Hej";
Dette array er faktisk på 4 chars:
Char : H e j \0
Index : 0 1 2 3
Du kan også skrive det på denne måde:
char s[4] = "Hej\0";
> Men hvad jeg ikke forstår er, hvorfor arrayet så nødvendigvis må være
> array[n] og ikke array[n-1] ...
>
> I alle andre tilfælde (hvor getline ikke benyttes) laver man da
> array[n] hvis det skal indeholde n tegn. ?
Nej. Du laver altid array[n+1], hvis det er en streng, der skal rumme
n tegn. Der skal altid være plads til nul-terminatoren for at gøre et
array til en streng.
En streng er et specielt array, hvor man er blevet enige om, at det
sidste tegn altid skal være nul-terminatoren.
-Claus
| |
Henrik Koksby Hansen (09-06-2002)
| Kommentar Fra : Henrik Koksby Hansen |
Dato : 09-06-02 17:09 |
|
>Dette array er faktisk på 4 chars:
>
> Char : H e j \0
> Index : 0 1 2 3
>
>Du kan også skrive det på denne måde:
>
> char s[4] = "Hej\0";
[...]
Ad... Så er jeg helt gal på den. Jeg havde fået ind i mit hoved, at
char s[4]
allokerer plads til 4 tegn + nultermineringen.
Altså, hvor de 4 tegn ligger på plads 0-3 og termineringen på plads
4...
Det sjove er så, at min bog også er uenig med mig. Damn. :)
- Bruger man ikke det nogle andre steder. - Så kan jeg da i det
mindste sige, at jeg har forvekslet de to.
MVH
Henrik
| |
Claus Rasmussen (09-06-2002)
| Kommentar Fra : Claus Rasmussen |
Dato : 09-06-02 17:16 |
|
Henrik Koksby Hansen wrote:
> - Bruger man ikke det nogle andre steder. - Så kan jeg da i det
> mindste sige, at jeg har forvekslet de to.
Du har måske forvekslet det med almindelige arrays, hvor f.eks
'int a[4]' skaber plads til fire elementer, der også kan bruges.
-Claus
| |
Henrik Koksby Hansen (09-06-2002)
| Kommentar Fra : Henrik Koksby Hansen |
Dato : 09-06-02 17:26 |
|
>Du har måske forvekslet det med almindelige arrays, hvor f.eks
>'int a[4]' skaber plads til fire elementer, der også kan bruges.
[...]
Jeg tror det er det. Der bruger man plads 0-3 jo... Der er så bare
ingen terminering... Puha... Jeg tror jeg skal have en pause væk fra
skærmen.
MVH
Henrik
| |
Henrik Koksby Hansen (09-06-2002)
| Kommentar Fra : Henrik Koksby Hansen |
Dato : 09-06-02 17:31 |
|
On Sun, 09 Jun 2002 18:26:00 +0200, Henrik Koksby Hansen
<koksby@elektronik.dk> wrote:
>>Du har måske forvekslet det med almindelige arrays, hvor f.eks
>>'int a[4]' skaber plads til fire elementer, der også kan bruges.
>[...]
>
>Jeg tror det er det. Der bruger man plads 0-3 jo... Der er så bare
>ingen terminering...
[..]
Til gengæld burde det slet ikke være muligt at benytte plads 4+ i et
array[4] f.eks.... Men der er jo ikke andet for, end at holde tungen
lige i munden... :)
MVH
Henrik
| |
Bertel Lund Hansen (09-06-2002)
| Kommentar Fra : Bertel Lund Hansen |
Dato : 09-06-02 17:56 |
|
Henrik Koksby Hansen skrev:
>Til gengæld burde det slet ikke være muligt at benytte plads 4+ i et
>array[4] f.eks...
Det kommer an på hvad du mener.
I Java, som er en sikkerhedsmæssig kravlegård, får man slet ikke
lov til at benytte array[4]. Det giver en OutofBounds-fejl.
I C(++) får man lov at rode og regere uhæmmet - på eget ansvar.
Man bygger sit eget lille minefelt ved at bruge array[4]. Måske
går det godt, måske ikke ... men det er en logisk fejl for
pladsen er ikke reserveret - ikke til array i hvert fald.
--
Bertel
http://lundhansen.dk/bertel/ FIDUSO: http://fiduso.dk/
| |
Byrial Jensen (09-06-2002)
| Kommentar Fra : Byrial Jensen |
Dato : 09-06-02 21:19 |
|
Bertel Lund Hansen <nospam@lundhansen.dk> skrev:
> Henrik Koksby Hansen skrev:
>
>>Til gengæld burde det slet ikke være muligt at benytte plads 4+ i et
>>array[4] f.eks...
>
> Det kommer an på hvad du mener.
>
> I Java, som er en sikkerhedsmæssig kravlegård, får man slet ikke
> lov til at benytte array[4]. Det giver en OutofBounds-fejl.
>
> I C(++) får man lov at rode og regere uhæmmet - på eget ansvar.
> Man bygger sit eget lille minefelt ved at bruge array[4]. Måske
> går det godt, måske ikke ... men det er en logisk fejl for
> pladsen er ikke reserveret - ikke til array i hvert fald.
Man har lov til (i hvert fald i C) at tage adressen på array[4] og
tildele den til en pointer. Denne pointer må dog ikke derefereres,
men kun bruges til pointer-aritmetik sammen med pointere til
elementer i array.
| |
Ivan Johansen (09-06-2002)
| Kommentar Fra : Ivan Johansen |
Dato : 09-06-02 21:44 |
|
Byrial Jensen wrote:
> Man har lov til (i hvert fald i C) at tage adressen på array[4] og
> tildele den til en pointer. Denne pointer må dog ikke derefereres,
> men kun bruges til pointer-aritmetik sammen med pointere til
> elementer i array.
Det tror jeg nu ikke. I C++ giver følgende i hvert fald undefined behavior:
char array[4];
char *p = &array[4];
I stedet skriver man således:
char array[4];
char *p = &array[0] + 4;
Ivan Johansen
| |
Byrial Jensen (09-06-2002)
| Kommentar Fra : Byrial Jensen |
Dato : 09-06-02 22:24 |
|
Ivan Johansen <NG@Padowan.dk> skrev:
> Byrial Jensen wrote:
>
>> Man har lov til (i hvert fald i C) at tage adressen på array[4] og
>> tildele den til en pointer. Denne pointer må dog ikke derefereres,
>> men kun bruges til pointer-aritmetik sammen med pointere til
>> elementer i array.
>
>
> Det tror jeg nu ikke. I C++ giver følgende i hvert fald undefined behavior:
> char array[4];
> char *p = &array[4];
Ovenstående er tilladt i C.
&array[4]
er identisk med ("syntaktisk sukker for")
&(*(array + 4))
Dvs. plus-operatoren skal anvendes først, og her siger standarden:
If the result points one past the last element of the array
object, it shall not be used as the operand of a unary * operator
that is evaluated. (Fra C99, afsnit 6.5.6#8).
Bemærk at det er afgørende for korrektheden om *-operatoren
evalueres. Det bliver den ikke, for den så at sige ophæves af
&-operatoren uden at nogen af dem bliver evalueret:
The unary & operator returns the address of its operand. If the
operand has type ``type'', the result has type ``pointer to
type''. If the operand is the result of a unary * operator,
neither that operator nor the & operator is evaluated and the
result is as if both were omitted, except that the constraints on
the operators still apply and the result is not an lvalue.
Similarly, if the operand is the result of a [] operator, neither
the & operator nor the unary * that is implied by the [] is
evaluated and the result is as if the & operator were removed and
the [] operator were changed to a + operator. Otherwise, the
result is a pointer to the object or function designated by its
operand. (C99 afsnit 6.5.3.2#3).
Konklusionen er at
char array[4];
char *p = &array[4];
er korrekt C-kode med samme betydning som:
char array[4];
char *p = array + 4;
Men jeg skal ikke kunne afvise at det giver udefineret adfærd i C++.
Det ved jeg ikke noget om.
| |
Mogens Hansen (10-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 10-06-02 07:16 |
|
"Ivan Johansen" <NG@Padowan.dk> wrote
> Det tror jeg nu ikke. I C++ giver følgende i hvert fald undefined
behavior:
> char array[4];
> char *p = &array[4];
>
Kan du angive en reference til hvor det står at det er undefined behaviour ?
Jeg kunne ikke umiddelbart finde noget, men jeg vil klart forvente at det er
tilladt, så længe pointeren ikke bliver derefereret.
Opførslen må være den samme som i C89.
Venlig hilsen
Mogens Hansen
| |
Ivan Johansen (10-06-2002)
| Kommentar Fra : Ivan Johansen |
Dato : 10-06-02 17:50 |
|
Mogens Hansen wrote:
> Kan du angive en reference til hvor det står at det er undefined behaviour ?
Jeg mener bestemt at jeg har læst det et sted, men jeg kan ikke finde
det i standarden, så jeg husker sikkert forkert.
> Jeg kunne ikke umiddelbart finde noget, men jeg vil klart forvente at det er
> tilladt, så længe pointeren ikke bliver derefereret.
> Opførslen må være den samme som i C89.
Nu henviser Byrial til C99, men hvis det også er tilladt i C89, er det
højst sandsynligt også i C++.
Hvad nu hvis det ikke er et char array, men et array af en klasse:
class C;
C c[4];
Hvis du nu bruger &c[4], kalder du c[4].operator&() hvorved du altså
derefererer et objekt uden for array'et, hvilket må give undefined
behaviour. Men det kan godt være at det forholder sig anderledes med
indbyggede typer.
Ivan Johansen
| |
Anders Wegge Jakobse~ (10-06-2002)
| Kommentar Fra : Anders Wegge Jakobse~ |
Dato : 10-06-02 18:12 |
|
"Ivan" == Ivan Johansen <NG@Padowan.dk> writes:
> Hvad nu hvis det ikke er et char array, men et array af en klasse:
> class C;
> C c[4];
> Hvis du nu bruger &c[4], kalder du c[4].operator&() hvorved du altså
> derefererer et objekt uden for array'et, hvilket må give undefined
> behaviour. Men det kan godt være at det forholder sig anderledes med
> indbyggede typer.
Nu har jeg min ISO C99 liggende inde på arbejdet, så jeg kan ikke
give dig en eksakt reference, men i både C89 og C99 er resultatet af
at evaluere adressen af det i-te element i et array med i elementer,
dvs. elementet umiddelbart efter arrayet, veldefineret. Dette gælder
uanset hvilken type arrayet er af.
Hvordan det forholde sig med C++ er jeg ikke lige klar over, men jeg
ville blive meget overrasket hvis der var en væsentlig forskel på
dette punkt.
--
/Wegge
| |
Mogens Hansen (10-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 10-06-02 21:21 |
|
"Ivan Johansen" <NG@Padowan.dk> wrote
> Mogens Hansen wrote:
>
> > Kan du angive en reference til hvor det står at det er undefined
behaviour ?
>
>
> Jeg mener bestemt at jeg har læst det et sted, men jeg kan ikke finde
> det i standarden, så jeg husker sikkert forkert.
>
Jeg fandt et troværdigt sted, hvor det meget tydeligt står at det er
garanteret at det virker:
The C++ Programming Language, Special Edition
Bjarne Stroustrup
ISBN 0-201-70073-5
kapitel 5.3, side 91-92
[snip]
> Hvad nu hvis det ikke er et char array, men et array af en klasse:
> class C;
> C c[4];
>
> Hvis du nu bruger &c[4], kalder du c[4].operator&() hvorved du altså
> derefererer et objekt uden for array'et, hvilket må give undefined
> behaviour. Men det kan godt være at det forholder sig anderledes med
> indbyggede typer.
>
Ifølge C++ Standarden §5.2.1, er E1[E2] per definition det samme som
*((E1)+(E2)), hvilket må betyde at
&c[4]
per definition er det samme som
&*(c+4)
Jeg tør ikke lige sige hvad der sker, hvis C har overloaded operator&, men
jeg er ret sikker på at &c[4] er veldefineret hvis operator& ikke er
overloaded.
Venlig hilsen
Mogens Hansen
| |
Ivan Johansen (10-06-2002)
| Kommentar Fra : Ivan Johansen |
Dato : 10-06-02 22:10 |
|
Mogens Hansen wrote:
> Jeg fandt et troværdigt sted, hvor det meget tydeligt står at det er
> garanteret at det virker:
> The C++ Programming Language, Special Edition
> Bjarne Stroustrup
> ISBN 0-201-70073-5
> kapitel 5.3, side 91-92
Det vil jeg lige kigge på, når jeg kan komme til den i morgen.
> Ifølge C++ Standarden §5.2.1, er E1[E2] per definition det samme som
> *((E1)+(E2)), hvilket må betyde at
Der har vi det jo. Der står:
"A postfix expression followed by an expression in square brackets is a
postfix expression. One of the expressions shall have the type "pointer
to T" and the other shall have enumeration or integral type. The result
is an lvalue of type "T." The type "T" shall be a completely defined
object type.56) The expression E1[E2] is identical (by definition) to
*((E1)+(E2)).
56) This is true even if the subscript operator is used in the following
common idiom: &x[0]."
Jeg er i tvivl om hvordan "completely defined object type" skal forstås.
Skal det forstås som at objektet skal eksistere, så du ikke må indeksere
ud over enden på et array, eller som at den klasse objektet er en
instans af skal være fuldt ud defineret?
Ivan Johansen
| |
Anders J. Munch (10-06-2002)
| Kommentar Fra : Anders J. Munch |
Dato : 10-06-02 22:21 |
|
"Ivan Johansen" <NG@Padowan.dk> skrev:
> Der har vi det jo. Der står:
> "A postfix expression followed by an expression in square brackets is a
> postfix expression. One of the expressions shall have the type "pointer
> to T" and the other shall have enumeration or integral type. The result
> is an lvalue of type "T." The type "T" shall be a completely defined
> object type.56) The expression E1[E2] is identical (by definition) to
> *((E1)+(E2)).
>
> 56) This is true even if the subscript operator is used in the following
> common idiom: &x[0]."
>
> Jeg er i tvivl om hvordan "completely defined object type" skal forstås.
> Skal det forstås som at objektet skal eksistere, så du ikke må indeksere
> ud over enden på et array, eller som at den klasse objektet er en
> instans af skal være fuldt ud defineret?
Det sidste. Det er _typen_ der tales om. Pointen er at selv om man har lov
til at skrive:
struct X;
extern X x;
X* xp = &x;
så må man ikke skrive:
X* x0 = &xp[0];
så længe X er ufuldstændig.
- Anders
| |
Mogens Hansen (11-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 11-06-02 05:52 |
|
"Ivan Johansen" <NG@Padowan.dk> wrote in message
news:3D0515AE.3020104@Padowan.dk...
[snip]
> Jeg er i tvivl om hvordan "completely defined object type" skal forstås.
> Skal det forstås som at objektet skal eksistere, så du ikke må indeksere
> ud over enden på et array, eller som at den klasse objektet er en
> instans af skal være fuldt ud defineret?
"completely defined object type" betyder at typen er fuld kendt, ikke bare
en forward erklæring, men den fulde erklæring så compileren kender
størrelsen.
Venlig hilsen
Mogens Hansen
| |
Ivan Johansen (11-06-2002)
| Kommentar Fra : Ivan Johansen |
Dato : 11-06-02 07:10 |
|
"Mogens Hansen" <mogens_h@dk-online.dk> wrote in message
news:ae31fe$2nql$1@news.cybercity.dk...
> Jeg fandt et troværdigt sted, hvor det meget tydeligt står at det er
> garanteret at det virker:
> The C++ Programming Language, Special Edition
> Bjarne Stroustrup
> ISBN 0-201-70073-5
> kapitel 5.3, side 91-92
Du har ret. Der er endda et fint eksempel, og da Bjarne jo nok ved hvad han
gør, så må det vel være tilladt.
Ivan Johansen
| |
Mogens Hansen (11-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 11-06-02 08:25 |
|
"Ivan Johansen" <NG@Padowan.dk> wrote
> "Mogens Hansen" <mogens_h@dk-online.dk> wrote
> > Jeg fandt et troværdigt sted, hvor det meget tydeligt står at det er
> > garanteret at det virker:
> > The C++ Programming Language, Special Edition
> > Bjarne Stroustrup
> > ISBN 0-201-70073-5
> > kapitel 5.3, side 91-92
>
> Du har ret. Der er endda et fint eksempel, og da Bjarne jo nok ved hvad
han
> gør, så må det vel være tilladt.
>
Ja, men er der alligevel ikke et problem for typer, hvor "operator&" er
overloaded, sådan som du har været inde på ?
Alle de compilere jeg har prøvet på (Borland C++Builder 6, Intel C++ V6,
Microsoft Visual C++ 7 på MS-Windows), kalder ihvertfald "operator&" på et
udgyldigt objekt i følgende eksempel:
#include <iostream>
using namespace std;
class foo
{
public:
foo()
{ cout << "foo constructor, this == " << this << endl; }
~foo()
{ cout << "foo destructor, this == " << this << endl; }
foo(const foo&)
{ cout << "foo copy constr, this == " << this << endl; }
foo* operator&()
{
cout << "foo operator&, this == " << this << endl;
return this;
}
};
int main()
{
foo foos[4];
foo* fp = &foos[4];
cout << "&foos[4]: " << fp << endl;
fp = &*(foos+4);
cout << "&*(foos+4): " << fp << endl;
fp = foos + 4;
cout << "foos + 4: " << fp << endl;
}
giver et output som:
foo constructor, this == 0012FE88
foo constructor, this == 0012FE89
foo constructor, this == 0012FE8A
foo constructor, this == 0012FE8B
foo operator&, this == 0012FE8C
&foos[4]: 0012FE8C
foo operator&, this == 0012FE8C
&*(foos+4): 0012FE8C
foos + 4: 0012FE8C
foo destructor, this == 0012FE8B
foo destructor, this == 0012FE8A
foo destructor, this == 0012FE89
foo destructor, this == 0012FE88
hvor "foo: erator&" er kaldt for et objekt på 0012FE8C som aldrig er
blevet oprettet.
Hvis "operator&" ikke er overloaded, ser der ikke ud til at være noget
problem.
En eller anden "tilfældig" compiler implementering beviser naturligvis ikke
at det ene eller det andet er gyldigt.
Jeg vil prøve at søge på andre nyhedsgrupper og eventuelt spørge på
comp.std.c++.
Venlig hilsen
Mogens Hansen
| |
Ivan Johansen (11-06-2002)
| Kommentar Fra : Ivan Johansen |
Dato : 11-06-02 18:26 |
|
Mogens Hansen wrote:
> Ja, men er der alligevel ikke et problem for typer, hvor "operator&" er
> overloaded, sådan som du har været inde på ?
Jo, det kan der i hvert fald være. Det var derfor jeg forventede at det
måske kun gjaldt indbyggede typer eller typer hvor operator& ikke er
overloaded. Men jeg kan ikke finde det præciseret i standarden på samme
måde som det er i C99 standarden.
>Jeg vil prøve at søge på andre nyhedsgrupper og eventuelt spørge på
comp.std.c++.
Det vil være fint. Jeg er meget interesseret i konklusionen.
Ivan Johansen
| |
Mogens Hansen (11-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 11-06-02 20:20 |
|
"Ivan Johansen" <NG@Padowan.dk> wrote
Prøv at kigge på:
http://www.research.att.com/~bs/3rd_issues.html
hvor der bl.a. står
pg 42 I use
char vc2[200];
copy(&vc1[0],&vc1[200],&vc2[200]);
The issue is whether taking the address of one-past-the-last element of an
array is conforming C and C++. I could make the example clearly conforming
by a simple rewrite:
copy(vc1,vc1+200,vc2+200);
However, I don't want to introduce addition to pointers at this point of the
book. It is a surprise to most experienced C and C++ programmers that
&vc2[200] isn't completely equivalent to vc2+200. In fact, it was a surprise
to the C committee also and I expect it to be fixed in the upcoming revision
of the standard. (resolved for C9x - bs 10/13/98). (this means that the
example was ok in K&R C, in ARM C++, an error in C89 and ISO C++, and ok in
C9x - a thorny issue).
(Koden i ovenstående citat er ikke fuldstændig magen til hvad der står i min
Special Edition - men det er ligegyldigt for denne diskution)
Så må overload af "operator&" blive afklaret senere.
Venlig hilsen
Mogens Hansen
| |
Ivan Johansen (11-06-2002)
| Kommentar Fra : Ivan Johansen |
Dato : 11-06-02 22:09 |
|
Mogens Hansen wrote:
> (this means that the
> example was ok in K&R C, in ARM C++, an error in C89 and ISO C++, and ok in
> C9x - a thorny issue).
Det vil sige at det ikke er tilladt at tage adressen på elementet efter
enden i C++, men det er i C99. Så ved jeg det. Tak for linket.
Ivan Johansen
| |
Anders J. Munch (12-06-2002)
| Kommentar Fra : Anders J. Munch |
Dato : 12-06-02 14:11 |
|
"Mogens Hansen" <mogens_h@dk-online.dk> wrote:
>
> Så må overload af "operator&" blive afklaret senere.
En overloaded operator& er blot et almindeligt metodekald med en speciel
syntaks.
&array[4] med overloaded operator& er ikke mere lovligt end array[4].foo().
- Anders
| |
Mogens Hansen (12-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 12-06-02 15:07 |
|
"Anders J. Munch" <andersjm@dancontrol.dk> wrote
> "Mogens Hansen" <mogens_h@dk-online.dk> wrote:
> >
> > Så må overload af "operator&" blive afklaret senere.
>
> En overloaded operator& er blot et almindeligt metodekald med en speciel
> syntaks.
>
> &array[4] med overloaded operator& er ikke mere lovligt end
array[4].foo().
>
Så vidt jeg kan se af denne diskution er
T array[4];
T* pt = &array[4];
lovligt i C99 og ulovligt i C89 og ISO C++ uanset typen af T, og uanset om T
har overloaded operator& eller ej.
T* pt = &array[4];
er per definiton det samme som
T* pt = &*(array+4);
og i C99 er det, ifølge det citat Byrial Jensen skrev, det samme som
T* pt = array+4;
for enhver type.
Hvis C++ havde en tilsvarende regel (hvad C++ ikke har) ville det betyde at
operator& ikke ville blive kaldt hvis den var overloaded.
Venlig hilsen
Mogens Hansen
| |
Anders J. Munch (10-06-2002)
| Kommentar Fra : Anders J. Munch |
Dato : 10-06-02 20:32 |
|
"Mogens Hansen" <mogens_h@dk-online.dk> skrev:
> "Ivan Johansen" <NG@Padowan.dk> wrote
>
> > Det tror jeg nu ikke. I C++ giver følgende i hvert fald undefined
> behavior:
> > char array[4];
> > char *p = &array[4];
> >
>
> Kan du angive en reference til hvor det står at det er undefined behaviour
?
Kan du angive en reference til at det er defineret? array+4 peger
ikke på et objekt, så *(array+4) er som udgangspunkt udefineret.
Åbenbart gør C en særlig undtagelse for dette almindelige idiom,
hvilket giver god mening, for C. Om det er en god idé for C++ er mere
diskutabelt, da det dårligt lader sig generalisere til klasser og
iterators.
--
Anders Munch, softwareudvikler
Stadig forvirret men på et højere niveau. Fjern fra min emailadresse.
| |
Mogens Hansen (10-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 10-06-02 20:49 |
|
"Anders J. Munch" <andersjm@inbound.dk> wrote
> "Mogens Hansen" <mogens_h@dk-online.dk> skrev:
> > "Ivan Johansen" <NG@Padowan.dk> wrote
> >
> > > Det tror jeg nu ikke. I C++ giver følgende i hvert fald undefined
> > behavior:
> > > char array[4];
> > > char *p = &array[4];
> > >
> >
> > Kan du angive en reference til hvor det står at det er undefined
behaviour
> ?
>
> Kan du angive en reference til at det er defineret?
The C++ Programming Language, Special Edition
Bjarne Stroustrup
ISBN 0-201-70073-5
kapitel 5.3, side 91-92
Venlig hilsen
Mogens Hansen
| |
Anders J. Munch (10-06-2002)
| Kommentar Fra : Anders J. Munch |
Dato : 10-06-02 22:10 |
|
"Ivan Johansen" <NG@Padowan.dk> wrote
> Det tror jeg nu ikke. I C++ giver følgende i hvert fald undefined
> behavior:
> char array[4];
> char *p = &array[4];
"Mogens Hansen" <mogens_h@dk-online.dk> skrev:
> Kan du angive en reference til hvor det står at det er undefined
> behaviour?
"Anders J. Munch" <andersjm@inbound.dk> wrote
> Kan du angive en reference til at det er defineret?
"Mogens Hansen" <mogens_h@dk-online.dk> skrev:
> The C++ Programming Language, Special Edition
> Bjarne Stroustrup
> ISBN 0-201-70073-5
> kapitel 5.3, side 91-92
Det var naturligvis en _autoritativ_ reference jeg mente, ikke bare en
tilfældig lærebogsforfatters personlige mening ... [1]
C++98, §5.3.1/1: The unary * operator performs _indirection_ [...] and
the result is an lvalue refererring to the object or function to which
the expression points.
array+4 peger ikke på noget objekt.
- Anders
[1] med al respekt ;)
| |
Mogens Hansen (11-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 11-06-02 05:55 |
|
"Ivan Johansen" <NG@Padowan.dk> wrote
> I stedet skriver man således:
> char array[4];
> char *p = &array[0] + 4;
Vil det garanteret virke, hvis arrayet indeholder typer, der har overloaded
operator& ?
Bør det ikke være
T array[4];
T* p = array + 4;
?
Venlig hilsen
Mogens Hansen
| |
Ivan Johansen (11-06-2002)
| Kommentar Fra : Ivan Johansen |
Dato : 11-06-02 18:39 |
|
Mogens Hansen wrote:
> "Ivan Johansen" <NG@Padowan.dk> wrote
>>I stedet skriver man således:
>>char array[4];
>>char *p = &array[0] + 4;
>>
> Vil det garanteret virke, hvis arrayet indeholder typer, der har overloaded
> operator& ?
Det afhænger af hvad funktionen gør og returnerer, men et kort svar må
være nej.
> Bør det ikke være
>
> T array[4];
> T* p = array + 4;
Det er i hvert fald garanteret at virke. Jeg plejer bare at skrive som
jeg gjorde, fordi det også virker hvis der var tale om en std::vector i
stedet for et array.
Ivan Johansen
| |
Henrik Koksby Hansen (10-06-2002)
| Kommentar Fra : Henrik Koksby Hansen |
Dato : 10-06-02 21:38 |
|
>> I Java, som er en sikkerhedsmæssig kravlegård, får man slet ikke
>> lov til at benytte array[4]. Det giver en OutofBounds-fejl.
>>
>> I C(++) får man lov at rode og regere uhæmmet - på eget ansvar.
>> Man bygger sit eget lille minefelt ved at bruge array[4]. Måske
>> går det godt, måske ikke ... men det er en logisk fejl for
>> pladsen er ikke reserveret - ikke til array i hvert fald.
>
>Man har lov til (i hvert fald i C) at tage adressen på array[4] og
>tildele den til en pointer. Denne pointer må dog ikke derefereres,
>men kun bruges til pointer-aritmetik sammen med pointere til
>elementer i array.
[...]
Jeg er ikke eksperten (endnu:), men det er da interessant, at plads n
rent faktisk _kan_ bruges (?)...
Har det noget at sige, at denne kode:
--- klip ---
int const SIZE = 4;
char array[SIZE] = {0};
for(int i = 0; i <= SIZE*5; i++) {
cout << "\"" << &array[i] << "\"" << endl;
array[i] = '0';
}
--- klip slut ---
giver følgende udskrift:
--- klip ---
""
""
""
""
"?"
Press any key to continue
--- klip slut---
Men, udkommenterer man array[i] = '0' fra koden, udskrives 20
"adresser" ...
MVH
Henrik
| |
Kent Friis (09-06-2002)
| Kommentar Fra : Kent Friis |
Dato : 09-06-02 17:13 |
|
Den Sun, 09 Jun 2002 18:08:46 +0200 skrev Henrik Koksby Hansen:
>>Dette array er faktisk på 4 chars:
>>
>> Char : H e j \0
>> Index : 0 1 2 3
>>
>>Du kan også skrive det på denne måde:
>>
>> char s[4] = "Hej\0";
>[...]
>
>Ad... Så er jeg helt gal på den. Jeg havde fået ind i mit hoved, at
>
> char s[4]
>
>allokerer plads til 4 tegn + nultermineringen.
>Altså, hvor de 4 tegn ligger på plads 0-3 og termineringen på plads
>4...
>Det sjove er så, at min bog også er uenig med mig. Damn. :)
>
>- Bruger man ikke det nogle andre steder. - Så kan jeg da i det
>mindste sige, at jeg har forvekslet de to.
Visual Basic, måske
Mvh
Kent
--
Those who write "Optimized for Netscape" og "Best viewed with MSIE"
never figured out the difference between the WWW and a
Word Perfect 4.2 Document.
| |
Ivan Johansen (09-06-2002)
| Kommentar Fra : Ivan Johansen |
Dato : 09-06-02 18:45 |
|
Claus Rasmussen wrote:
> Du kan også skrive det på denne måde:
>
> char s[4] = "Hej\0";
Nej, det er 5 tegn:
Char : H e j \0 \0
Index : 0 1 2 3 4
Hvis du vil vise termineringen eksplicit skal det gøres således:
char s[4] = {'H', 'e', 'j', '\0'};
Ivan Johansen
| |
Claus Rasmussen (09-06-2002)
| Kommentar Fra : Claus Rasmussen |
Dato : 09-06-02 18:48 |
|
Ivan Johansen wrote:
> Claus Rasmussen wrote:
>
>> Du kan også skrive det på denne måde:
>>
>> char s[4] = "Hej\0";
>
> Nej, det er 5 tegn:
D' sgu' rigtigt
-Claus
| |
Bertel Lund Hansen (09-06-2002)
| Kommentar Fra : Bertel Lund Hansen |
Dato : 09-06-02 20:26 |
|
Ivan Johansen skrev:
>> char s[4] = "Hej\0";
>Nej, det er 5 tegn:
> Char : H e j \0 \0
> Index : 0 1 2 3 4
Såh? Her er et lille testprogram:
#include <stdio.h>
int main () {
char s[20]="Teststreng\0Hej";
printf("%s har længden %d og ender med %c.\n\n",s,strlen(s),s[strlen(s)-1]);
return 0;
}
Udskrift:
Teststreng har lµngden 10 og ender med g.
--
Bertel
http://lundhansen.dk/bertel/ FIDUSO: http://fiduso.dk/
| |
Anders Melchiorsen (09-06-2002)
| Kommentar Fra : Anders Melchiorsen |
Dato : 09-06-02 20:36 |
|
Bertel Lund Hansen <nospam@lundhansen.dk> skrev:
> Såh? Her er et lille testprogram:
Man kan ikke bevise med et testprogram.
Anders.
--
Min adresse er gyldig i en uge.
Derefter skal (kun) delen '.dJJJ-YY' fjernes.
| |
Claus Rasmussen (09-06-2002)
| Kommentar Fra : Claus Rasmussen |
Dato : 09-06-02 20:39 |
|
Bertel Lund Hansen wrote:
> int main () {
> char s[20]="Teststreng\0Hej";
> printf("%s har længden %d og ender med
> %c.\n\n",s,strlen(s),s[strlen(s)-1]); return 0;
> }
Nej. Du lader dig snyde af, at alle strenghåndteringsrutinerne stopper
når de rammer det første nul i din tekst "Teststreng\0Hej". Prøv i
stedet flg.:
int main() {
char s[20]="Teststreng\0Hej";
for (int i = 0; i < 14; ++i)
printf("s[%d] = '%c'\n", i, s[i]);
}
Resultat:
s[0] = 'T'
s[1] = 'e'
s[2] = 's'
s[3] = 't'
s[4] = 's'
s[5] = 't'
s[6] = 'r'
s[7] = 'e'
s[8] = 'n'
s[9] = 'g'
s[10] = '' <- Vores ekstra nul
s[11] = 'H'
s[12] = 'e'
s[13] = 'j'
MVH
-Claus
| |
Martin Dyring (09-06-2002)
| Kommentar Fra : Martin Dyring |
Dato : 09-06-02 20:42 |
|
"Bertel Lund Hansen" <nospam@lundhansen.dk> wrote in message
news:4oa7guo2e5754k3jrjpe0jcpnlgm1d1ag2@sunsite.auc.dk...
> Såh? Her er et lille testprogram:
>
> #include <stdio.h>
>
> int main () {
> char s[20]="Teststreng\0Hej";
> printf("%s har længden %d og ender med
%c.\n\n",s,strlen(s),s[strlen(s)-1]);
> return 0;
> }
>
> Udskrift:
> Teststreng har lµngden 10 og ender med g.
Du kopierer 15 chars ("Teststreng" + terminering + "Hej" + terminering) over
i dit char array. strlen() returnerer det antal chars der forekommer før
termineringen i strengen.
Oversætteren sørger selv for at tilføje den korrekte terminering til
strenge. Alt afhængig af hvordan man vender og drejer det kopierer du i
virkeligheden to nul-terminerede strenge ind i et char array. Den første
streng begynder i s[0] og den anden i s[11].
--
Mvh,
Martin Dyring
| |
Byrial Jensen (09-06-2002)
| Kommentar Fra : Byrial Jensen |
Dato : 09-06-02 21:32 |
|
Martin Dyring <mda@image.dk> skrev:
> Oversætteren sørger selv for at tilføje den korrekte terminering til
> strenge.
Kun hvis man afsætter plads nok, eller overlader det til
oversætteren at udregne pladsforbruget.
char s[3] = "Lang tekst";
Her vil s indeholde de 3 tegn 'L', 'a', 'n' uden nogen form for
terminering. Det betyder at man ikke må give s til funktioner som
forventer en nul-terminering - det ville medføre udefineret adfærd
når de ville forsøge at tilgå det ikke-eksisterende 4. tegn.
| |
Martin Dyring (09-06-2002)
| Kommentar Fra : Martin Dyring |
Dato : 09-06-02 21:53 |
|
"Byrial Jensen" <bjensen@nospam.dk> wrote in message
news:slrnag7eps.18u.bjensen@ask.ask...
> Martin Dyring <mda@image.dk> skrev:
> > Oversætteren sørger selv for at tilføje den korrekte terminering til
> > strenge.
>
> Kun hvis man afsætter plads nok, eller overlader det til
> oversætteren at udregne pladsforbruget.
> [...]
Yeps, skulle jeg nok havde præciseret. :)
Uden at have sat mig helt ind i det gætter jeg på at oversætteren sørger for
at lave strengen om til et nul-termineret array uanset hvad. = operatoren
sørger så for at ikke at kopiere mere end sizeof(venstre siden) tegn? Det
står nok nærmere beskrevet et sted. Personligt holder jeg mig fra
"C"-strenge, synes std::string fungerer fint for mig. Og så kan man jo også
have \0 i strengen uden de store krumspring<tm>.
--
Mvh,
Martin Dyring
| |
Byrial Jensen (09-06-2002)
| Kommentar Fra : Byrial Jensen |
Dato : 09-06-02 22:40 |
|
Martin Dyring <mda@image.dk> skrev:
> "Byrial Jensen" <bjensen@nospam.dk> wrote in message
>> Martin Dyring <mda@image.dk> skrev:
>> > Oversætteren sørger selv for at tilføje den korrekte terminering til
>> > strenge.
>>
>> Kun hvis man afsætter plads nok, eller overlader det til
>> oversætteren at udregne pladsforbruget.
>> [...]
>
> Yeps, skulle jeg nok havde præciseret. :)
>
> Uden at have sat mig helt ind i det gætter jeg på at oversætteren sørger for
> at lave strengen om til et nul-termineret array uanset hvad.
Det gør en C-oversætter ikke. Der er ingen regel som siger at et
array af char nødvendigvis skal indeholde tegnet '\0'.
Jeg kender ikke C++ så godt som C, men jeg ville blive meget
overrasket hvis der er en sådan regel i C++.
>= operatoren
> sørger så for at ikke at kopiere mere end sizeof(venstre siden) tegn?
Tegnet "=" betegner her ikke en operator, men markerer en
initialisering af et objekt (objekt brugt i C-betydningen af ordet).
Man kan af naturlige årsager ikke initialisere flere array-elementer,
end der er. Og antallet af elementer afgøres ufravigeligt af en
eksplicit angivelse.
| |
Mogens Hansen (10-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 10-06-02 08:25 |
|
"Byrial Jensen" <bjensen@nospam.dk> wrote
> Kun hvis man afsætter plads nok, eller overlader det til
> oversætteren at udregne pladsforbruget.
>
> char s[3] = "Lang tekst";
>
> Her vil s indeholde de 3 tegn 'L', 'a', 'n' uden nogen form for
> terminering. Det betyder at man ikke må give s til funktioner som
> forventer en nul-terminering - det ville medføre udefineret adfærd
> når de ville forsøge at tilgå det ikke-eksisterende 4. tegn.
I C++ er ovenstående ill-formed: §8.5.2-2.
Venlig hilsen
Mogens Hansen
| |
Mogens Hansen (09-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 09-06-02 21:20 |
|
"Bertel Lund Hansen" <nospam@lundhansen.dk> wrote
> Såh? Her er et lille testprogram:
>
> #include <stdio.h>
>
> int main () {
> char s[20]="Teststreng\0Hej";
> printf("%s har længden %d og ender med
%c.\n\n",s,strlen(s),s[strlen(s)-1]);
> return 0;
> }
>
> Udskrift:
> Teststreng har lµngden 10 og ender med g.
Det viser blot at din printf og strlen virker i dette tilfælde.
De finder det første '\0' og stopper der
Prøv i stedet:
#include <iostream>
int main()
{
char s1[] = "Tekststreng\0Hej";
char s2[] = "Hej\0";
std::cout << sizeof(s1) << " " << sizeof(s2) << std::endl;
}
Det burde udskrive:
16 5
Venlig hilsen
Mogens Hansen
| |
Byrial Jensen (09-06-2002)
| Kommentar Fra : Byrial Jensen |
Dato : 09-06-02 21:19 |
|
Ivan Johansen <NG@Padowan.dk> skrev:
> Claus Rasmussen wrote:
>
>> Du kan også skrive det på denne måde:
>>
>> char s[4] = "Hej\0";
>
>
> Nej, det er 5 tegn:
> Char : H e j \0 \0
> Index : 0 1 2 3 4
Hvis man i C eksplicit angiver en længde af et array, får arrayet
altid den angivne længde. Når man som i eksemplet her forsøger at
initialisere det med en streng som ganske rigtig er på 5 tegn,
bruges kun de første 4 af dem til initialiseringen. Se f.eks. C99,
afsnit 6.7.8#14.
$ cat stri.c
#include <stdio.h>
int main()
{
char s[4] = "Hej\0";
printf ("s fylder %zu tegn.\n", sizeof s);
return 0;
}
$ gcc -W -Wall stri.c -o stri
$ ./stri
s fylder 4 tegn.
$
| |
Ivan Johansen (09-06-2002)
| Kommentar Fra : Ivan Johansen |
Dato : 09-06-02 22:04 |
|
Byrial Jensen wrote:
> Hvis man i C eksplicit angiver en længde af et array, får arrayet
> altid den angivne længde. Når man som i eksemplet her forsøger at
> initialisere det med en streng som ganske rigtig er på 5 tegn,
> bruges kun de første 4 af dem til initialiseringen. Se f.eks. C99,
> afsnit 6.7.8#14.
Ja, det er rigtigt. Det er derfor jeg normalt ikke skriver størrelsen,
men lader kompileren finde den. Det kan nemt forvirre, når man forsøger
at initialisere med mere end der er plads til, selv om kompileren kun
bruger det der er plads til.
Ivan Johansen
| |
Robert Bauck Hamar (09-06-2002)
| Kommentar Fra : Robert Bauck Hamar |
Dato : 09-06-02 16:55 |
|
Henrik Koksby Hansen <henrik@koksby.dk>:
| >Umiddelbart laver du den fejl, at underdimensionere alle dine char arrays.
| >F.eks
| >
| > char number[8];
| >
| > ...
| >
| > cin.getline(number, 9);
| >
| >Dit 'number' array består af 8 char, men du tillader indlæsning af
| >9. Gør i stedet sådan:
| >
| > char number[8 + 1];
| >
| [...]
|
| Jeg ved så ikke om jeg har forstået det korrekt, men
|
| cin.getline(number, n)
|
| indlæser n-1 tegn.
Det leser *maksimalt* n-1 tegn. cin.getline(char*, streamsize) stopper
innlesning når neste tegn i strømmen er '\n', og dette tegnet blir
slettet fra strømmen. Så blir det slengt på en '\0' før getline
avslutter.
|
| Men hvad jeg ikke forstår er, hvorfor arrayet så nødvendigvis må være
| array[n] og ikke array[n-1] ...
char number[9]
betyr definer number som en array av char med plass til 9 elementer. Det
niende og siste (number[8], ikke number[9]!) trengs for å inneholde en
nullterminator, dersom den ikke finnes tidligere.
|
| I alle andre tilfælde (hvor getline ikke benyttes) laver man da
| array[n] hvis det skal indeholde n tegn. ?
| (eller array[n-1] hvis det skal indeholde n-1 tegn ??)
Ja. Pass på at det skal være plass til nullterminatoren.
Får jeg anbefale deg å bruke std::string istedet:
#include <iostream>
#include <string> //std::string og std::getline
int main()
{
std::string number;
if (std::getline(std::cin, number))
std::cout << "Du tastet " << number << std::endl;
}
--
Robert Bauck Hamar
| |
Bertel Lund Hansen (09-06-2002)
| Kommentar Fra : Bertel Lund Hansen |
Dato : 09-06-02 17:38 |
|
Henrik Koksby Hansen skrev:
>Jeg ved så ikke om jeg har forstået det korrekt, men
>cin.getline(number, n)
>indlæser n-1 tegn.
Tja, den henter n-1 tegn fra tastaturet og tilføjer et 0: i alt n
tegn. Det er en hyppig fejlkilde i C(++)-programmer.
Strenge i C er nultermineret. Det giver fordele og ulemper. I
Pascal angiver 0-byten længden, og så er man fri for at spekulere
på den, og ydermere kan man have et 0 som et almindeligt tegn i
en streng. Til gengæld er der en grænse for hvor lang en streng
kan være.
I C termineres (afsluttes) strengen med et 0. Den kan derfor være
lige så lang det skal være. Til gengæld er der et tegn mere end
man lige regner med, og 0 kan ikke optræde som element. Hvis man
planter et 0 midt i en streng, så er den pludselig blevet
afkortet.
Hvis blot man husker det, er det ikke noget problem.
--
Bertel
http://lundhansen.dk/bertel/ FIDUSO: http://fiduso.dk/
| |
Mogens Hansen (09-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 09-06-02 17:00 |
|
"Henrik Koksby Hansen" <henrik@koksby.dk> wrote
Generelt vil jeg anbefale at du undgår at bruge char array, hvis du ikke har
brug for det.
Foretræk klassen std::string i stedet. Du slipper for overvejelser om hvor
store de skal være.
>
> Her er noget kode:
>
>
> ---- klip ----
> void archive::reg() {
>
> char last[30];
string last;
> char first[20];
string first;
> char number[8];
int number;
^^
_ikke_ string
> char ad[40];
string ad;
> char e[20];
string e;
>
> if (testbetingelse == true){
>
> fflush(stdin); // flush input buffer
>
Hvorfor blande C og C++ stream ?
Det virker, men kan det ikke virke forvirrende ?
Du kan f.eks. (ligesom forleden) bruge
cin.ignore(cin.rdbuf()->in_avail());
> cout << "Enter last name : "; cin.getline(last, 31);
cout << "Enter last name: ";
if(!getline(cin, last)) {
throw some_exception();
}
> cout << "Enter first name: "; cin.getline(first, 21);
igen
> cout << "Enter phonenumber: "; cin.getline(number, 9);
igen
> cout << "Enter address: "; cin.getline(ad, 41);
igen
> cout << "Enter e-mail: "; cin.getline(e, 21);
igen
>
> doReg(n, last, first, atoi(number), ad, e);
doReg(n, last, first, atoi, ad, e);
> }
> else cout << "Error: Already registered.\n";
> }
>
> ---- klip ----
>
> void archive::doReg(int const n, char *last, char *first, int number,
> char *ad, char *e) {
void archive:doReg(int n, const string& last, const string& first, int
number, const string& ad, const char& e)
{
>
> strcpy(Students[n]->lastName,last);
Hvis "Students[n]->lastName" også laves om til at være et string objekt:
Strudents[n]->lastName = last;
> strcpy(Students[n]->firstName,first);
igen
> Students[n]->phoneNumber=number;
igen
> strcpy(Students[n]->address,ad);
igen
> strcpy(Students[n]->eMail,e);
igen
Eller lav Student om til en klasse, hvor du ikke har adgang til
datamedlemmerne, og istedet overfører parametrene til constructoren:
Students[n] = Student(last, first, number, ad, e);
Venlig hilsen
Mogens Hansen
| |
Henrik Koksby Hansen (09-06-2002)
| Kommentar Fra : Henrik Koksby Hansen |
Dato : 09-06-02 18:35 |
|
>> fflush(stdin); // flush input buffer
>>
>Hvorfor blande C og C++ stream ?
>Det virker, men kan det ikke virke forvirrende ?
>Du kan f.eks. (ligesom forleden) bruge
> cin.ignore(cin.rdbuf()->in_avail());
[...]
- Taget til efterretning.
Jeg går ud fra, at cin.ignore() er en funktion af cin, som får cin til
at ignorere den parameter, man nu måtte kalde den med.
I dette tilfælde kaldes den med cin.rdbuf(), som jeg går ud fra er den
aktuelle læsebuffer. Men hvad er ->in_avail() ?
Det må vel være en del af rdbuf() eftersom du bruger 'this pointer'
til at kalde den.. (?)
Der står ikke en pind i den - forældede? - bog, som jeg har;
C++ How to Program (3rd edition) af Deitel og Deitel.
- En ret kedelig bog, efter min mening. (Man kommer let til at springe
noget vigtigt over, eftersom de starter helt fra bunden, hver gang der
kommer et nyt emne.)
>Eller lav Student om til en klasse, hvor du ikke har adgang til
>datamedlemmerne, og istedet overfører parametrene til constructoren:
> Students[n] = Student(last, first, number, ad, e);
[...]
Sådan er det allerede opbygget. Jeg ville bare "simplificere" det her.
Lidt et 3. spørgsmål:
Hvor kan jeg forresten læse lidt mere om, hvornår const gør hvad. Jeg
er nemlig lidt i tvivl om, hvornår const skal stå før datatypen, før
variablen osv. osv...
MVH
Henrik
| |
Mogens Hansen (09-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 09-06-02 19:25 |
|
"Henrik Koksby Hansen" <koksby@elektronik.dk> wrote in message
news:ok37guo2ol2jpuhdd6m65vlkqretjda4n1@4ax.com...
> >> fflush(stdin); // flush input buffer
> >>
> >Hvorfor blande C og C++ stream ?
> >Det virker, men kan det ikke virke forvirrende ?
> >Du kan f.eks. (ligesom forleden) bruge
> > cin.ignore(cin.rdbuf()->in_avail());
> [...]
>
> - Taget til efterretning.
>
> Jeg går ud fra, at cin.ignore() er en funktion af cin, som får cin til
> at ignorere den parameter, man nu måtte kalde den med.
>
Nej, "cin.ignore" beder cin om at tage det antal tegn der er angivet som
parameter ud af streamen, og smide dem væk.
> I dette tilfælde kaldes den med cin.rdbuf(), som jeg går ud fra er den
> aktuelle læsebuffer.
Ja, det er læsebufferen, som har typen "streambuf" (som er en typedef af
basic_streambuf<char> - men det er ligegyldigt i denne sammenhæng)
> Men hvad er ->in_avail() ?
"cin.rdbuf()->in_avail()" returnerer hvor mange tegn der ligger parat i
cin's læse-buffer.
> Det må vel være en del af rdbuf() eftersom du bruger 'this pointer'
> til at kalde den.. (?)
>
Ja.
"cin.ignore(cin.rdbuf()->in_avail());" tømmer altså læsebufferen.
> Der står ikke en pind i den - forældede? - bog, som jeg har;
Nej, det kan man ikke sige på den baggrund.
Det er ikke ofte man har brug for at tømme læsebufferen før man læser.
Det står i
Standard C++ IOStreams and Locales
Angelika Langer and Klaus Kreft
ISBN 0-201-18395-1
[snip]
> Lidt et 3. spørgsmål:
> Hvor kan jeg forresten læse lidt mere om, hvornår const gør hvad. Jeg
> er nemlig lidt i tvivl om, hvornår const skal stå før datatypen, før
> variablen osv. osv...
>
I bogen
Accelerated C++
Andrew König, Barbara Moo
ISBN 0-201-70353-X
står såvel reference som const reference forklaret meget pragmatisk og
anvendeligt på side 54-55.
"const" i sig selv står forklaret på side 13, og const member funktioner
står beskrevet på side 159.
Jeg tror ikke at den rækkefølge er helt almindelig, men det forekommer mig
at være velvalgt.
Venlig hilsen
Mogens Hansen
| |
|
|