/ Forside / Teknologi / Udvikling / C/C++ / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
C/C++
#NavnPoint
BertelBra.. 2425
pmbruun 695
Master_of.. 501
jdjespers.. 500
kyllekylle 500
Bech_bb 500
scootergr.. 300
gibson 300
molokyle 287
10  strarup 270
[newbie] bogstav-vars?
Fra : CHRistian


Dato : 11-04-01 19:20

Hmm, hvordan pokker får man lettest bogstavdata til at være i en
var? Der findes jo ingen spec. var.type til ikke-tal (Borland Turbo
C++ 3, DOS).
Ok, der er åbenbart char-typen velegnet (1byte), men når den skal
erklæres, så _skal_ den åbenbart have en str. på arr., men hvad hvis
man ikke ved, hvor meget tekst, der er?

Og hvad, hvis man godt kunne tænke sig at lave et array af
tekst-vars. Det virker ikke
char tt[10][2];
tt[10][1] = "rr"; // fejl: cannot convert 'char *' to 'char'
tt[10][2] = "ss"; // do

- har jeg overset noget, eller er det ikke lidt bøvlet med tekst i
c?

--
Bruger du Opera? Vil du være med til at teste den danske version
af Opera 5 (win32)? Dvs: installere .lng-fil + par andre i Opera,
se gennem for stavefejl, mindre heldige oversættelser osv. og så melde
tilbage? ---> Hvis så, så send en mail til mig, nospam@direkte.org

 
 
Stephan Henningsen (12-04-2001)
Kommentar
Fra : Stephan Henningsen


Dato : 12-04-01 00:03

On Wed, 11 Apr 2001 20:20:02 +0200, CHRistian wrote:
>Ok, der er åbenbart char-typen velegnet (1byte), men når den skal
>erklæres, så _skal_ den åbenbart have en str. på arr., men hvad hvis
>man ikke ved, hvor meget tekst, der er?

Så må man allokerer plads til dem dynamisk =). Det gøres
vha. en char-pointer (char*) og noget hukommelses-allokering.
Char-pointeren peger så dertil, hvor pladsen starter.


int
main()
{
   char*         buf = 0;
   unsigned long int   bufsize,
            i;


   cout << "Hvor meget hukommelse ønkes allokeret? (bytes): ";
   cin >> bufsize;

   buf = new char [bufsize];   // Prøv at allokerer hukommelse.

   if ( !buf ) {         // Gik det? buf = 0 ved fejl.
      cerr << "Øv, du havde ikke hukommelse nok." << endl;
      return -1;
   }

   cout << "Labert!" << endl;

   for ( i = 0 ; i < bufsize ; i++ )
      buf[i] = 'a' ;      // Fyld buf på med a'er.

   delete buf;         // Frigør hukommelse igen.

   cout << "Farveller." << endl;

   return 0;
}

Hvis du bruger standard C, så skal du i stedet kigge på
funktionerne malloc og free.


>char tt[10][2];
>tt[10][1] = "rr"; // fejl: cannot convert 'char *' to 'char'
>tt[10][2] = "ss"; // do

For det første opretter du 10 strenge af længeden 2. Men de
kan kun indeholde en strenge på længeden 1, idet strenge
altid skal afsluttes af en null-terminering ('\0'). Du skal
altså gøre plads til et tegn ekstra.

Du kan ikke bare sætte et array lig med noget (=); du er nød
til at bruge streng-kopierings-funktionerne til dette:


#include <string.h>

char   tt[10][3];

strcpy( tt[1] , "rr" );
strcpy( tt[2] , "ss" );



Og her har vi så grundlaget for nok en af de hyppigste
programmerings-fejl. Nemlig buffer-overflows. Fordi i
princippet kan du godt allokerer 5 bytes of kopiere 8GB
ind i den. Kig også på strncpy-funktionen, som sætter en
begrænsning på, hvormeget der kopieres.


>har jeg overset noget, eller er det ikke lidt bøvlet med tekst i
>c?

Det er ikke helt så nemt, som i pascal med strings; man skal
specielt tænke sig lidt om mht. buffer-størrelser.
Men tilgengæld kan du lave så mange andre labre ting, når
først du har lidt styr på pointere.

Der findes i øvrigt også string-typer i C++ i stil med dem fra
pascal, men jeg har ikke brugt dem så meget. Men de bruge
omtrent sådan:

string   str1;
string   str2("init");

str1 = "abekat";
str2 = "hundeprut";

str1 = str1 + ¨ og " + str2;

--
Stephan Henningsen /
/ http://tisprut.dk


Igor V. Rafienko (12-04-2001)
Kommentar
Fra : Igor V. Rafienko


Dato : 12-04-01 00:07



| Så må man allokerer plads til dem dynamisk =). Det gøres
| vha. en char-pointer (char*) og noget hukommelses-allokering.


.... hvilket er et _meget_ dårlig råd i C++.

[snip]


|   buf = new char [bufsize];   // Prøv at allokerer hukommelse.
|
|   if ( !buf ) {         // Gik det? buf = 0 ved fejl.
                   ~~~~~~~~~~~~~~~~~

Nei, det stemmer ikke. 'new' returnerer _aldri_ 0 i formen over (det
finnes en nothrow variant, men det er ikke den som er brukt i
eksempelet ditt).


|      cerr << "Øv, du havde ikke hukommelse nok." << endl;
|      return -1;
|   }


Denne testen vil _aldri_ slå til. Det er ikke noe vits i å ha død
kode.


|   for ( i = 0 ; i < bufsize ; i++ )
|      buf[i] = 'a' ;      // Fyld buf på med a'er.


std::fill_n( buf, buf + bufsize, 'a' );

;)


|   delete buf;         // Frigør hukommelse igen.


Nei, dette er også feil, da new[] skal frigjøres med delete[]. new
derimot skal frigjøres med delete. See the difference?

[snip]


| Der findes i øvrigt også string-typer i C++ i stil med dem fra
| pascal, men jeg har ikke brugt dem så meget. Men de bruge omtrent
| sådan:
|
| string   str1;
| string   str2("init");
|
| str1 = "abekat";
| str2 = "hundeprut";
|
| str1 = str1 + ¨ og " + str2;


strings kan også masse annet som er _veldig_ kronglete med char*. Jo
før man går over til de som standard valg i C++, jo bedre.





ivr
--

Stephan Henningsen (12-04-2001)
Kommentar
Fra : Stephan Henningsen


Dato : 12-04-01 23:06

On 12 Apr 2001 01:07:13 +0200, Igor V. Rafienko wrote:
>
>
>| Så må man allokerer plads til dem dynamisk =). Det gøres
>| vha. en char-pointer (char*) og noget hukommelses-allokering.
>
>
>... hvilket er et _meget_ dårlig råd i C++.

Jeg forstår ikke hvad du mener, uddyb venligst.


>|   buf = new char [bufsize];   // Prøv at allokerer hukommelse.
>|
>|   if ( !buf ) {         // Gik det? buf = 0 ved fejl.
>                   ~~~~~~~~~~~~~~~~~
>
>Nei, det stemmer ikke. 'new' returnerer _aldri_ 0 i formen over (det
>finnes en nothrow variant, men det er ikke den som er brukt i
>eksempelet ditt).

Så er jeg atter fejlinformeret gennem bøgerne. Hvad
returnerer new, hvis den ikke kan allokerer den ønskede
mængde?


>|      cerr << "Øv, du havde ikke hukommelse nok." << endl;
>|      return -1;
>|   }
>
>
>Denne testen vil _aldri_ slå til. Det er ikke noe vits i å ha død
>kode.

Et job hos Microsoft kan det vel altid blive til..


>|   for ( i = 0 ; i < bufsize ; i++ )
>|      buf[i] = 'a' ;      // Fyld buf på med a'er.
>
>
>std::fill_n( buf, buf + bufsize, 'a' );
>
>;)

Ved jeg, men jeg ville demonsterer at bufferen kunne
indekseres som "normalt".


>|   delete buf;         // Frigør hukommelse igen.
>
>
>Nei, dette er også feil, da new[] skal frigjøres med delete[]. new
>derimot skal frigjøres med delete. See the difference?

I min bog står det, at delete[] er en gammel notation, og
delete har erstattet den.


>strings kan også masse annet som er _veldig_ kronglete med char*. Jo
>før man går over til de som standard valg i C++, jo bedre.

Jeg synes altid jeg har problemer med strings, men jeg har
heller ikke studeret dem så nøje..



--
Stephan Henningsen /
/ http://tisprut.dk


Mogens Hansen (12-04-2001)
Kommentar
Fra : Mogens Hansen


Dato : 12-04-01 22:39


"Stephan Henningsen" <stephan@sanxion.tisprut.dk> wrote in message
news:slrn9dc9m1.2lb.stephan@sanxion.tisprut.dk...
> On 12 Apr 2001 01:07:13 +0200, Igor V. Rafienko wrote:
>
> Så er jeg atter fejlinformeret gennem bøgerne. Hvad

Hvilken bøger ?

> returnerer new, hvis den ikke kan allokerer den ønskede
> mængde?

Hvis vi snakker ISO C++ (og det gør vi vel), så kaster operator new en
exception af typen "std::bad_alloc" hvis der ikke kunne allokeres den
ønskede mængde hukommelse.

>
> Et job hos Microsoft kan det vel altid blive til..

Formodentlig - Microsoft Visual C++ V6.0 smider _ikke_ en std::bad_alloc
exception men returnerer 0, hvis allokeringen fejlede.
Microsoft Visual C++ .NET beta 1 er blevet Standard Compliant på dette
område.

> >
> >Nei, dette er også feil, da new[] skal frigjøres med delete[]. new
> >derimot skal frigjøres med delete. See the difference?
>
> I min bog står det, at delete[] er en gammel notation, og
> delete har erstattet den.

Hvilken bog ?
Den tager i hvert fald fejl.
I C++ Standarden §5.3.5,2 står der at det er "undefined behavior".

>
>
> >strings kan også masse annet som er _veldig_ kronglete med char*. Jo
> >før man går over til de som standard valg i C++, jo bedre.
>
> Jeg synes altid jeg har problemer med strings, men jeg har
> heller ikke studeret dem så nøje..
>

"std::string" klassen ?
Jeg tror du kan få glæde og gavn af at læse "Accelerated C++, Practical
Programming by Example" af Andrew Koenig og Barbara E. Moo (ISBN
0-201-70353-X)

Venlig hilsen

Mogens Hansen



Stephan Henningsen (13-04-2001)
Kommentar
Fra : Stephan Henningsen


Dato : 13-04-01 01:01

On Thu, 12 Apr 2001 23:38:39 +0200, Mogens Hansen wrote:
>
>"Stephan Henningsen" <stephan@sanxion.tisprut.dk> wrote in message
>news:slrn9dc9m1.2lb.stephan@sanxion.tisprut.dk...
>> Så er jeg atter fejlinformeret gennem bøgerne. Hvad
>
>Hvilken bøger ?

Herbert Schildt, "C++ from the groud up" (1st ed. går jeg ud
fra) side 226 samt min underviser.


>> returnerer new, hvis den ikke kan allokerer den ønskede
>> mængde?
>
>Hvis vi snakker ISO C++ (og det gør vi vel), så kaster operator new en
>exception af typen "std::bad_alloc" hvis der ikke kunne allokeres den
>ønskede mængde hukommelse.

Jeg synes exception-handling er så bøvlet når jeg jo bare
lige vil se om noget gik godt eller ej.


>> >Nei, dette er også feil, da new[] skal frigjøres med delete[]. new
>> >derimot skal frigjøres med delete. See the difference?
>>
>> I min bog står det, at delete[] er en gammel notation, og
>> delete har erstattet den.
>
>Hvilken bog ?
>Den tager i hvert fald fejl.
>I C++ Standarden §5.3.5,2 står der at det er "undefined behavior".

Ah, jeg tog fejl. Det der står i min bog er, at i gamle
compilere, kam man være nødsaget til også at angive længden
at bufferen, når man deleter. Der skal være klammer under
alle omstændigheder.

   delete[] buf;
   delete[bufsize] buf;


>> Jeg synes altid jeg har problemer med strings, men jeg har
>> heller ikke studeret dem så nøje..
>
>"std::string" klassen ?
>Jeg tror du kan få glæde og gavn af at læse "Accelerated C++, Practical
>Programming by Example" af Andrew Koenig og Barbara E. Moo (ISBN
>0-201-70353-X)

Tak. Den er hermed skrevet på ønskelisten =).


--
Stephan Henningsen /
/ http://tisprut.dk


Mogens Hansen (13-04-2001)
Kommentar
Fra : Mogens Hansen


Dato : 13-04-01 07:00

Hej Stephan,
"Stephan Henningsen" <stephan@sanxion.tisprut.dk> wrote in message
news:slrn9dcgei.36v.stephan@sanxion.tisprut.dk...
> On Thu, 12 Apr 2001 23:38:39 +0200, Mogens Hansen wrote:

> >Hvis vi snakker ISO C++ (og det gør vi vel), så kaster operator new en
> >exception af typen "std::bad_alloc" hvis der ikke kunne allokeres den
> >ønskede mængde hukommelse.
>
> Jeg synes exception-handling er så bøvlet når jeg jo bare
> lige vil se om noget gik godt eller ej.
>

Når man har arbejdet lidt med det, syntes jeg det viser sig at
exception-handling er en ren og rimelig nem måde at lave fejlhåndtering på.
Det er ikke exception-handling der er svært - det er fejlhåndtering
generelt. Exceptions hjælper til at man faktisk får håndteret
fejlsituationer rigtigt, samtidig med at den primære kode ikke bliver
forplumret.
Hvor ofte fejler "operator new" faktisk, og hvor tit får du testet
fejlhåndterings koden ?
Hvis du f.eks. har en C (_ikke_ C++) funktion der skal allokerer 3 resource
(f.eks. åbne en fil og allokere 2 memory-blokke), og den sidste allokering
fejl, får du så frigivet alle de hidtidigt allokeret resourcer inden der
returneres en fejlkode.
Hvis man kombinerer exception handling med
resource-aquisition-is-initialization (se "The C++ Programming Language,
Special Edition" (eller Third Edition det er samme indhold i de oplagene fra
begyndelsen af år 2000 - papirkvalitet, indbindingen og priser er
anderledes), Bjarne Stroustrup, ISBN 0-201-70073-5, side 366) så får man en
relativ simpel og robust fejlhåndtering.
Se også Appendix E "Standard Library Exception Safety" i "The C++
Programming Language", som ligeledes kan findes på
http://www.research.att.com/~bs/3rd_safe0.html
Se også "Exceptional C++", Herb Sutter, ISBN 0-201-61562-2 som bl.a.
beskæftiger sig med korrekt exception håndtering. Herb Sutter har bidraget
væsentlig til forståelsen af exception i C++.

Venlig hilsen

Mogens Hansen



Mogens Hansen (13-04-2001)
Kommentar
Fra : Mogens Hansen


Dato : 13-04-01 11:15

Hej Stephan,
"Stephan Henningsen" <stephan@sanxion.tisprut.dk> wrote in message
news:slrn9dcgei.36v.stephan@sanxion.tisprut.dk...
> On Thu, 12 Apr 2001 23:38:39 +0200, Mogens Hansen wrote:
> >> Jeg synes altid jeg har problemer med strings, men jeg har
> >> heller ikke studeret dem så nøje..
> >
> >"std::string" klassen ?
> >Jeg tror du kan få glæde og gavn af at læse "Accelerated C++, Practical
> >Programming by Example" af Andrew Koenig og Barbara E. Moo (ISBN
> >0-201-70353-X)
>
> Tak. Den er hermed skrevet på ønskelisten =).

Du kan få en lille smagsprøve, som netop handling om anvendelse af
"std::string" på

http://www.joopmag.com/html/from_pages/article.asp?id=2877&mon=4&yr=2001


Venlig hilsen

Mogens Hansen



Igor V. Rafienko (13-04-2001)
Kommentar
Fra : Igor V. Rafienko


Dato : 13-04-01 15:44

* Stephan Henningsen

[snip]

> >| Så må man allokerer plads til dem dynamisk =). Det gøres
> >| vha. en char-pointer (char*) og noget hukommelses-allokering.
> >
> >... hvilket er et _meget_ dårlig råd i C++.
>
> Jeg forstår ikke hvad du mener, uddyb venligst.


Den største designtabben som Bjarne Stroustrup har imvho gjort er å
arve memory modellen til C. Som en konsekvens av dette, endte C++ med
et ganske ødelagt tekstbegrep i form av char*'ere.

Men noen kom på at det ville være en god ide å rette på jævelskapet og
lagde std::string. Heller ikke den er perfekt (bl.a. fordi typen til
"flabba" er fremdeles en const char[7] heller enn const std::string),
men den er adskillig bedre enn char*, da std::string kan økes dynamisk
uten for mye strev og ikke har _komplett idiotiske_ begrensninger à la
betydningen av '\0' i en C string. I utgangspunktet bør standardvalget
være std::string. Om dens operasjoner og/eller størrelse viser seg å
være upassende for programmet, kun da er det aktuelt å bytte tilbake
til char*.

Hovedideen er å slippe å flikke og mekke på det søppelet som char*'ere
virkelig er og bruke heller std::string, der man slipper å huske
antall bytes allokert, exception-safety garantier o.l. fjas som
egentlig ikke har noe med den egentlige problemstilligen å gjøre.


> >Nei, det stemmer ikke. 'new' returnerer _aldri_ 0 i formen over
> >(det finnes en nothrow variant, men det er ikke den som er brukt i
> >eksempelet ditt).
>
> Så er jeg atter fejlinformeret gennem bøgerne.


Bytt til en ordentlig bok, så blir det den siste gangen sånt skjer.


> Hvad returnerer new, hvis den ikke kan allokerer den ønskede mængde?


En liten kommentar til det Mogens Hansen skrev. Det finnes også en
variant som returnerer NULL pointeren, dersom new ikke greier å
allokere nok hukommelse (aka nothrow-variant):

int *p = new (nothrow) int[ 1 << 20UL ];
if ( !p ) {
cerr << "failed\n";
exit( 1 );
}

(den heter nok

int *p = new (std::nothrow) int[ 1 << 20UL ];

dersom man skal være pedantisk korrekt).


Kompilatorne som jeg har adgang til har faktisk implementert dette
riktig:

$ cat foo.cpp
#include <iostream>
#include <new>


int main()
{
using namespace std;

for ( ; ; ) {
int *p = new (nothrow) int[ 1 << 20UL ];
if ( !p ) {
cerr << "out of memory\n";
exit( 1 );
}
}
}
$ g++ foo.cpp
$ ./a.out
out of memory
$ cat bar.cpp
#include <iostream>
#include <new>


int main()
{
using namespace std;

try {
for ( ; ; )
int *p = new int[ 1 << 20UL ];
}
catch ( bad_alloc &ba ) {
cerr << "out of memory\n";
exit( 1 );
}
}
$ CC bar.cpp
$ ./a.out
out of memory
$

(bonus question: begge kompilatorne har implementert noe annet feil.
Hva er det?)


> >|   for ( i = 0 ; i < bufsize ; i++ )
> >|      buf[i] = 'a' ;      // Fyld buf på med a'er.
> >
> >
> >std::fill_n( buf, buf + bufsize, 'a' );
> >
> >;)
>
> Ved jeg, men jeg ville demonsterer at bufferen kunne
> indekseres som "normalt".


Som en kuriøsitet kan det nevnes at g++-2.95.2 kjører noen løkker
raskere dersom man bruker en versjon fra <algorithm> heller enn den
håndskrevne varianten. Forskjellene er ganske små, men dog.


> >|   delete buf;         // Frigør hukommelse igen.
> >
> >
> >Nei, dette er også feil, da new[] skal frigjøres med delete[]. new
> >derimot skal frigjøres med delete. See the difference?
>
> I min bog står det, at delete[] er en gammel notation, og
> delete har erstattet den.


Som sagt, <URL:http://www.accu.org/> er neste stopp. Synes ikke du at
det er smule pussig at det ikke finnes en _eneste_ bok av H. Schildt
som har fått en noenlunde positiv tilbakemelding?


> >strings kan også masse annet som er _veldig_ kronglete med char*.
> >Jo før man går over til de som standard valg i C++, jo bedre.
>
> Jeg synes altid jeg har problemer med strings, men jeg har heller
> ikke studeret dem så nøje..


Gjør det, så slipper du å tenke på en rekke helt unødvendige ting.
Kopiering/konkatenering av C-strings alene er så vondt at det ikke er
til å tro. Den første tingen man kommer på er "there's got to be a
better way".





ivr
--
"making it suck less, one module at a time..."
John Bode on comp.lang.c (comment on program development)

Igor V. Rafienko (12-04-2001)
Kommentar
Fra : Igor V. Rafienko


Dato : 12-04-01 00:00


| Hmm, hvordan pokker får man lettest bogstavdata til at være i en
| var?


std::string er veien å gå i C++ (det er den kompilatoren du bruker,
tross alt).

[snip]


| - har jeg overset noget, eller er det ikke lidt bøvlet med tekst i
| c?


I C er det litt verre med tekster, så din venn er malloc + char
pekere. Masse fjasing...





ivr
--

CHRistian (13-04-2001)
Kommentar
Fra : CHRistian


Dato : 13-04-01 00:41

igorr@ifi.uio.no (Igor V. Rafienko)'s posting:

>| Hmm, hvordan pokker får man lettest bogstavdata til at være i en
>| var?
>std::string er veien å gå i C++ (det er den kompilatoren du bruker,

Kan du give et eks.? Jeg er altså ikke helt med på, hvordan du
mener.

--
Bruger du Opera? Vil du være med til at teste den danske version
af Opera 5 (win32)? Dvs: installere .lng-fil + par andre i Opera,
se gennem for stavefejl, mindre heldige oversættelser osv. og så melde
tilbage? ---> Hvis så, så send en mail til mig, nospam@direkte.org

Claus Brinch Jensen (13-04-2001)
Kommentar
Fra : Claus Brinch Jensen


Dato : 13-04-01 01:22


"CHRistian" <nospam@direkte.org> wrote in message
news:jrecdt8bhl18bc78eivfnjhsgk18acoola@TnEwS.inet.tele.dk...
> igorr@ifi.uio.no (Igor V. Rafienko)'s posting:
>
> >| Hmm, hvordan pokker får man lettest bogstavdata til at være i en
> >| var?
> >std::string er veien å gå i C++ (det er den kompilatoren du bruker,
>
> Kan du give et eks.? Jeg er altså ikke helt med på, hvordan du
> mener.

Der findes i C++ en type "std::string" der netop er beregnet til at
indeholde strenge (eller bogstav-variable om du vil).

Se nedenfor.

Mvh.
Claus

---code---
#include <iostream>
#include <string>
using std::string;
using std::cout;
using std::endl;

int main(int argc, char ** argv)
{
string en_streng;
en_streng = "noget tekst ";
for(int i = 0; i < 10; i++) {
en_streng += "og noget mere tekst ";
}
cout << en_streng << endl;
return 0;
}
---code---
Output:
noget tekst og noget mere tekst og noget mere tekst og noget mere tekst og
noget mere tekst og noget mere tekst og noget mere tekst og noget mere tekst
og noget mere tekst og noget mere tekst og noget mere tekst





Stephan Henningsen (13-04-2001)
Kommentar
Fra : Stephan Henningsen


Dato : 13-04-01 04:12

On Fri, 13 Apr 2001 02:22:00 +0200, Claus Brinch Jensen wrote:
>---code---
>#include <iostream>
>#include <string>
>using std::string;
>using std::cout;
>using std::endl;

Hvad er det helt præcist de sidste tre linier gør godt for?
Jeg har lært, at der skal stå "using namespace std;" men ved
ikke rigtigt hvorfor. Og det er da noget helt andet, der
står dér.


--
Stephan Henningsen /
/ http://tisprut.dk


Claus Brinch Jensen (13-04-2001)
Kommentar
Fra : Claus Brinch Jensen


Dato : 13-04-01 03:01

"Stephan Henningsen" <stephan@sanxion.tisprut.dk> wrote in message
news:slrn9dcrjd.4pb.stephan@sanxion.tisprut.dk...
> On Fri, 13 Apr 2001 02:22:00 +0200, Claus Brinch Jensen wrote:
> >---code---
> >#include <iostream>
> >#include <string>
> >using std::string;
> >using std::cout;
> >using std::endl;
>
> Hvad er det helt præcist de sidste tre linier gør godt for?
> Jeg har lært, at der skal stå "using namespace std;" men ved
> ikke rigtigt hvorfor. Og det er da noget helt andet, der
> står dér.

Det betyder såmænd blot at du, i stedet for at hive hele standard library
med ind i programmets scope/virkefelt (som du gør med "using namespace
std;", kun tager dem med som du rent faktisk bruger, i dette tilfælde
std::string, std::cout, std::endl. Det er efter min mening en pænere måde at
gøre tingene på, dels hvad angår læsbarheden af koden og dels mhp. at undgå
navne sammenfald med andre "identifiers".

Mvh.
Claus



Ulrik Magnusson (17-04-2001)
Kommentar
Fra : Ulrik Magnusson


Dato : 17-04-01 02:47

Stephan Henningsen wrote:

> On Fri, 13 Apr 2001 02:22:00 +0200, Claus Brinch Jensen wrote:
> >---code---
> >#include <iostream>
> >#include <string>
> >using std::string;
> >using std::cout;
> >using std::endl;
> Hvad er det helt præcist de sidste tre linier gør godt for?
> Jeg har lært, at der skal stå "using namespace std;" men ved
> ikke rigtigt hvorfor. Og det er da noget helt andet, der
> står dér.

Han skriver sådan for ikke at skulle referere til fx "std::cout", men
kan nøjes med "cout". "using" ændrer scope for erklæringer,
således at navne i det namespace man bruger, lader til at være
erklærede på det sted, hvor "using" er placeret. I ovenstående er
det bare enkelte variabler i std, der ændrer scope, og ikke hele
std namespace't.

Man kan også definere sit eget namespace, evt. for at sikre sig
mod navnekonflikter, og hvis man vil være rigtig irriterende kan
man introducere kode som dette:

#include <iostream>
using std::cout;
using std::endl;
class UlrikOut
{
public:
UlrikOut& operator<<( const char* str )
{
cout << "Ulrik says: '" << str << "'" << endl;
return *this;
}
};
namespace Ulrik
{
UlrikOut cout;
}
using Ulrik::cout;
int main( int argc, const char* args[] )
{
cout << "Hello" << "Bye";
return 0;
}

Og da jeg normalt ikke bruger C++ er der nok tusindevis af
fejl og dårlige vaner i ovenstående, men dem må I så kommentere..

Eksemplet virker dog med djgpp.

Ulrik Magnusson

--
"our hope's with you
rider in the blue"
Mike Oldfield - "Five Miles Out", do 1981
Visit my home page: http://www.geocities.com/ulrikm



CHRistian (14-04-2001)
Kommentar
Fra : CHRistian


Dato : 14-04-01 17:34

"Claus Brinch Jensen" <cbj@email.dk>'s posting:

>Der findes i C++ en type "std::string" der netop er beregnet til at
>indeholde strenge (eller bogstav-variable om du vil).
---klip---
>---code---
>#include <iostream>
>#include <string>

Min compiler (Turbo C++ 3.0) vil altså godt nok have ".h" på.

Og den kan - åbenbart - ikke finde ud af noget af dette eks.
(indsat linjenr. i koden for at kunne vise det her).

>4: using std::string;
>5: using std::cout;
>6: using std::endl;

Compiling O-LNG.CPP:
Error O-LNG.CPP 4: Declaration syntax error
Error O-LNG.CPP 5: Variable 'using' is initialized more than once
Error O-LNG.CPP 5: Declaration syntax error
Error O-LNG.CPP 6: Variable 'using' is initialized more than once
Error O-LNG.CPP 6: Declaration syntax error

>8: int main(int argc, char ** argv)
>9: {
>10: string en_streng;
> 11: en_streng = "noget tekst ";

Error O-LNG.CPP 10: Undefined symbol 'string'
Error O-LNG.CPP 10: Statement missing ;
Error O-LNG.CPP 11: Undefined symbol 'en_streng'

---klip løkken, gad ikke at indskrive den---
>11: cout << en_streng << endl;
>12: }

Warning O-LNG.CPP 12: Parameter 'argc' is never used
Warning O-LNG.CPP 12: Parameter 'argv' is never used

--
Bruger du Opera? Vil du være med til at teste den danske version
af Opera 5 (win32)? Dvs: installere .lng-fil + par andre i Opera,
se gennem for stavefejl, mindre heldige oversættelser osv. og så melde
tilbage? ---> Hvis så, så send en mail til mig, nospam@direkte.org

Igor V. Rafienko (14-04-2001)
Kommentar
Fra : Igor V. Rafienko


Dato : 14-04-01 17:52

* nospam@direkte.org

> >#include <iostream>
> >#include <string>
>
> Min compiler (Turbo C++ 3.0) vil altså godt nok have ".h" på.


Herregud...

Ok, bytt kompilatoren til noe annet litt mer "up-to-date". Borland gir
5.02 (eller var det 5.5?) gratis (kun kommandolinjekompilator, ikke noe IDE);
eller kan du prøve DJGPP.


> Compiling O-LNG.CPP:
> Error O-LNG.CPP 4: Declaration syntax error
> Error O-LNG.CPP 5: Variable 'using' is initialized more than once
> Error O-LNG.CPP 5: Declaration syntax error
> Error O-LNG.CPP 6: Variable 'using' is initialized more than once
> Error O-LNG.CPP 6: Declaration syntax error


Dropp kompilatoren til fordel for noe som er litt mer i samsvar med
standarden.

[snip]





ivr
--
"making it suck less, one module at a time..."
John Bode on comp.lang.c (comment on program development)

CHRistian (14-04-2001)
Kommentar
Fra : CHRistian


Dato : 14-04-01 19:55

igorr@ifi.uio.no (Igor V. Rafienko)'s posting:

>> Min compiler (Turbo C++ 3.0) vil altså godt nok have ".h" på.
>Herregud...

Den er da kun ca. 10 år gammel

>Ok, bytt kompilatoren til noe annet litt mer "up-to-date". Borland gir
>5.02 (eller var det 5.5?) gratis (kun kommandolinjekompilator, ikke noe IDE);

Problemet er, at Borlands 5.5 (er det vist) er for krævende, synes
jeg, til mit system, der ikke er ret hurtigt.
Nåmen, jeg fandt en anden (ny), der virker ok (lidt stor måske):
Dev-C++ 4 (inkl, IDE). Bruger Mingw (version MSCVRT 2.95.2-1) el.
evt. Cygwin, hvis det skulle sige nogen noget.

--
Bruger du Opera? Vil du være med til at teste den danske version
af Opera 5 (win32)? Dvs: installere .lng-fil + par andre i Opera,
se gennem for stavefejl, mindre heldige oversættelser osv. og så melde
tilbage? ---> Hvis så, så send en mail til mig, nospam@direkte.org

Kent Friis (14-04-2001)
Kommentar
Fra : Kent Friis


Dato : 14-04-01 17:55

Den Sat, 14 Apr 2001 18:33:50 +0200 skrev CHRistian:
>"Claus Brinch Jensen" <cbj@email.dk>'s posting:
>
>>Der findes i C++ en type "std::string" der netop er beregnet til at
>>indeholde strenge (eller bogstav-variable om du vil).
>---klip---
>>---code---
>>#include <iostream>
>>#include <string>
>
>Min compiler (Turbo C++ 3.0) vil altså godt nok have ".h" på.
>
>>4: using std::string;
>>5: using std::cout;
>>6: using std::endl;
>
> Compiling O-LNG.CPP:
> Error O-LNG.CPP 4: Declaration syntax error
> Error O-LNG.CPP 5: Variable 'using' is initialized more than once
> Error O-LNG.CPP 5: Declaration syntax error
> Error O-LNG.CPP 6: Variable 'using' is initialized more than once
> Error O-LNG.CPP 6: Declaration syntax error
>
> Error O-LNG.CPP 10: Undefined symbol 'string'
> Error O-LNG.CPP 10: Statement missing ;
> Error O-LNG.CPP 11: Undefined symbol 'en_streng'

Prøv at få en nyere compiler.

Mvh
Kent
--
http://www.celebrityshine.com/~kfr - sidste billede: planets.png

Igor V. Rafienko (13-04-2001)
Kommentar
Fra : Igor V. Rafienko


Dato : 13-04-01 16:48

* nospam@direkte.org

> >| Hmm, hvordan pokker får man lettest bogstavdata til at være i en
> >| var?
> >
> >std::string er veien å gå i C++ (det er den kompilatoren du bruker,
>
> Kan du give et eks.? Jeg er altså ikke helt med på, hvordan du
> mener.


Jeg prøvde for en stund tilbake å lage et lite skriv om strings. Det
ble dessverre aldri helt bra (men du kan godt få den i mail, hvis du
vil), men jeg kan jo prøve å ta et par eksempler derifra:





Eksempel 1. Word-counter i Dietmar Kuehl[0] stil:

int
main()
{
using namespace std;

cout << "the input had "
    << distance( istream_iterator< string >( cin ),
       istream_iterator< string >() )
    << " words\n";
}   

Dette illustrerer dog mer hvordan hele rammeverket sitter sammen
heller enn string bruken som sådan (istream_iterator er en slags
pekepinne til en input bytestream (fx. en fil). I dette eksempelet
deler den input i cin i string-elementer vha. op>> som hører til
klassen string. I og med at denne oppfatter whitespace som
meningsbærende, får vi en pekepinne til en input bytestream der
elementene er ord. distance regner bare differansen mellom siste og
første pekepinne).





Eksempel 2. Frequency-counter fra B. Stroustrup:

map< string, unsigned int > m;


void
mark_word( const string &s )
{
m[s]++;
}


for_each( istream_iterator< string >( cin ),
    istream_iterator< string >(),
    mark_word );


for ( map< string, unsigned int > :: iterator i = m.begin();
i != m.end();
++i )
cout << (*i).first << " -> " << (*i).second << " times\n";





Eksempel 3. Lese /etc/passwd filen der man plukker ut uname og det ekte navnet
og vise resultatet.

For ikke-unix mennesker: /etc/passwd består av et ukjent antall linjer
der en linje beskriver en bruker vha. flere felt. Feltene er adskilt
av ':' og en typisk entry ser slik ut:

flabba:passwd:47662:1296:Flabba User:/microsoft/sucks/home/flabba:/local/gnu/bin/bash

Vi er interessert i det første (flabba) og det femte (Flabba User)
feltene.

I dette tilfellet kan man plassere alle uname, realname par i en
vector (det spiller strengt tatt ingen rolle her).


#include <iostream>
#include <vector>
#include <utility>
#include <string>


int
main()
{
using namespace std;

string next_line;
vector< pair< string, string > > all_entries;


while ( getline( cin, next_line ) ) {
   // let's pick out uname
   string::size_type i = next_line.find_first_of( ':' );
   string uname = next_line.substr( 0, i );

   // ... and the real name, 5th field
   // First we skip the first 3
   for ( int j = 0; j != 3; ++j )
    i = next_line.find_first_of( ':', i+1 );

   // ... and i constains the lower limit of the realname
   // another find_first_of finds the upper limit.
   string realname = next_line.substr( i + 1,
                next_line.find_first_of( ':', i+1 ) - ( i + 1 ) );
   
   // and now store the next entry
all_entries.push_back( make_pair( uname, realname ) );
}

// and let's output
cout << "There are " << all_entries.size()
<< " entries in the password file.\n"
    << "The uname -> real map is here:\n";

for ( vector< pair< string, string > > :: size_type i = 0;
    i != all_entries.size();
    ++i )
   cout << all_entries[i].first << " -> " << all_entries[i].second << "\n";
}


Man kan naturligvis lage en funksjon, find_ith, som finner den i'te
substrengen som tilfredstiller en betingelse.





ivr
[0] Diemar Kuehl er en _meget_ kyndig person, når det gjelder spesielt
IO-delen av C++ stdlib.
--
"making it suck less, one module at a time..."
John Bode on comp.lang.c (comment on program development)

CHRistian (14-04-2001)
Kommentar
Fra : CHRistian


Dato : 14-04-01 17:34

igorr@ifi.uio.no (Igor V. Rafienko)'s posting:

>> Kan du give et eks.? Jeg er altså ikke helt med på, hvordan du
>Jeg prøvde for en stund tilbake å lage et lite skriv om strings. Det
>ble dessverre aldri helt bra (men du kan godt få den i mail, hvis du

Ja tak, det vil jeg gerne have. Mine nospam-adresse, jeg poster
under virker.

>Eksempel 1. Word-counter i Dietmar Kuehl[0] stil:
---klip---

Takker, der er liige lidt at se på...

--
Bruger du Opera? Vil du være med til at teste den danske version
af Opera 5 (win32)? Dvs: installere .lng-fil + par andre i Opera,
se gennem for stavefejl, mindre heldige oversættelser osv. og så melde
tilbage? ---> Hvis så, så send en mail til mig, nospam@direkte.org

Jesper Louis Anderse~ (15-11-2001)
Kommentar
Fra : Jesper Louis Anderse~


Dato : 15-11-01 01:54

On Wed, 11 Apr 2001 20:20:02 +0200, CHRistian <nospam@direkte.org> wrote:
> Hmm, hvordan pokker får man lettest bogstavdata til at være i en
> var? Der findes jo ingen spec. var.type til ikke-tal (Borland Turbo
> C++ 3, DOS).
> Ok, der er åbenbart char-typen velegnet (1byte), men når den skal
> erklæres, så _skal_ den åbenbart have en str. på arr., men hvad hvis
> man ikke ved, hvor meget tekst, der er?

Du har overset dynamisk allokering. malloc() samt free() (i C) og
``new'' samt ``delete'' (I C++) gør nok underværker i dit tilfælde

--
Jesper

Søg
Reklame
Statistik
Spørgsmål : 177558
Tips : 31968
Nyheder : 719565
Indlæg : 6408926
Brugere : 218888

Månedens bedste
Årets bedste
Sidste års bedste