/ 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
Substring eller hvad?
Fra : Bjarke Walling Peter~


Dato : 27-10-01 12:33

Jeg er næsten nybegynder i C++... og nu er jeg stødt ind i et par problemer,
da jeg var ved at lave en CPR-nr-checker. Jeg skal nemlig konvertere hvert
ciffer i en streng til int. Jeg kan sagtens få skrevet hvert ciffer ud fra
strengen, men når jeg prøver at parse hvert ciffer til atoi-funktionen
virker det åbenbart ikke (sådan her: atoi(streng[i]) ). Hvad gør jeg galt?
Jeg ville gætte på at jeg skal bruge en function der kan tage en substring
af en string, men hvad hedder den?

Her er koden (ikke cpr-nr-programmet, men noget "debug"-kode jeg har lavet):

#include <iostream.h>
#include <stdlib.h>
#include <string.h>

int main (int argc, char *argv[]){
char streng[40];
int len;
strcpy(streng,"0123456789876543210");
len=strlen(streng);
cout << streng << "\n";
for (int i=0;i<len;i++){
cout << streng[i]; // Denne linie virker ...
}
cout << "\n";
for (int i=0;i<len;i++){
cout << atoi(streng[i]); // ... men det gør denne ikke!
}
cout << "\n\n";
system("PAUSE");
}

.... det er foresten en konsolapplikation, hvilket man nok godt kan se.

- Bjarke Walling Petersen



 
 
Mogens Hansen (27-10-2001)
Kommentar
Fra : Mogens Hansen


Dato : 27-10-01 14:31


"Bjarke Walling Petersen" <bwp@bwp.dk> wrote in message
news:3bda9b49$0$25409$edfadb0f@dspool01.news.tele.dk...

> virker det åbenbart ikke (sådan her: atoi(streng[i]) ). Hvad gør jeg galt?

Compilerer det ?
Du giver den et argument af den forkerte type.
atoi forventer en pointer til en null-termineret string. Du giver den en
char reference (ikke pointer).

> Jeg ville gætte på at jeg skal bruge en function der kan tage en substring
> af en string, men hvad hedder den?

Det er lidt bøvlet, når du bruger char array.
Hvis du brugte streng klassen "std::string" hedder funktionen "substr". Det
er ikke nødvendigvis det hurtigste, men det er sikkert og nemt.

>
> Her er koden (ikke cpr-nr-programmet, men noget "debug"-kode jeg har
lavet):
>
> #include <iostream.h>

Det bør foretrækkes at skrive
#include <iostream>
Det er standard C++

> #include <stdlib.h>
> #include <string.h>
>
> int main (int argc, char *argv[]){
> char streng[40];
> int len;
> strcpy(streng,"0123456789876543210");
> len=strlen(streng);

Foretræk at erklær og initialiser variable samtidig
int len=strlen(streng);

> cout << streng << "\n";
> for (int i=0;i<len;i++){

Foretræk at bruge size_t i stedet for int.
Den er garanteret til at kunne indeksere hele arrayet - det er int ikke.

> for (int i=0;i<len;i++){
> cout << atoi(streng[i]); // ... men det gør denne ikke!

Du _kunne_ skrive
char buffer[2];
buffer[1] = '\0';
for(...) {
buffer[0] = streng[i];
cout << atoi(buffer);

Hvordan checker du for fejl ?
atoi returnerer 0, hvis konverteringen gik galt - men 0 er jo også en gyldig
værdi.

Hvis du _ved_ at tegnene for 0, 1, 2 etc. i dit tegnsæt er fortløbende, og 0
er mindst, kan du skrive
int value = streng[i] - '0';

Det er dog ikke garanteret at det virker alle steder!

Jeg vil umiddelbart anbefale at bruge string klassen og locale
funktionalitet.
String klassen sparer dig for mange pointer bekymringer og locale
funktionaliteten sikrer at tingene bliver konverteret rigtigt i forbindelse
med forskellige tegnsæt.

#include <iostream>
#include <locale>

int main (void)
{
using namespace std;

string str("01a23456789876543210");

for(string::iterator i = str.begin(); str.end() != i; ++i) {
cout << *i;
}

cout << endl;

typedef num_get<string::value_type, string::const_iterator>
num_get_type;
const num_get_type& num_get = use_facet<num_get_type>(cout.getloc());

for(string::iterator i = str.begin(); str.end() != i; ++i) {
unsigned int value;
ios_base::iostate err;
num_get.get(i, i+1, cout, err, value);
if(!(err & ios_base::failbit) && !(err & ios_base::badbit)) {
cout << value;
}
else {
cerr << "\nnot a digit" << endl;
}
}
}

Venlig hilsen

Mogens Hansen



Igor V. Rafienko (27-10-2001)
Kommentar
Fra : Igor V. Rafienko


Dato : 27-10-01 15:37

[ Bjarke Walling Petersen ]

[ snip ]

> Jeg skal nemlig konvertere hvert ciffer i en streng til int. Jeg kan
> sagtens få skrevet hvert ciffer ud fra strengen, men når jeg prøver
> at parse hvert ciffer til atoi-funktionen virker det åbenbart ikke
> (sådan her: atoi(streng[i]) ). Hvad gør jeg galt?


Mogens har forklart hva du har gjort galt. Men det synes meg at
løsningen hans er litt for komplisert til formålet ditt. Under følger
det noen forslag som kunne kanskje være nyttige.

[ snip ]


> int main (int argc, char *argv[]){
> char streng[40];
> int len;
> strcpy(streng,"0123456789876543210");
> len=strlen(streng);


char streng[] = "0123456789876543210";
size_t len = strlen( streng );


> cout << streng << "\n";


char-pekere er ganske onde dyr, og du er mere tjent med å bruke noe
enklere og mer fleksibelt. I dette tilfellet -- en std::string.


> for (int i=0;i<len;i++){
> cout << streng[i]; // Denne linie virker ...
> }
> cout << "\n";
> for (int i=0;i<len;i++){
> cout << atoi(streng[i]); // ... men det gør denne ikke!
> }
> cout << "\n\n";
> system("PAUSE");
> }


Det finnes flere måter å konvertere hvert tegn til et siffer på.

1) Dersom du sitter med 10-tallssystemet, kan du bare substrahere
verdien av tegnet '0' fra det nåværende tegnet:

string s = "0123456789876543210";
for ( string::iterator i = s.begin();
i != s.end();
++i )
if ( isdigit( *i ) )
cout << *i << " is digit " << *i - '0' << "\n";

Det synes meg å være den aller enkleste løsningen.


2) Alternativt, kan man bruke stream_cast (boost.org kaller denne for
lexical_cast):


template <typename To, typename From>
To stream_cast(From const& from) {
std::stringstream stream;
stream << from;
To to;
stream >> to;
return to;
}

string s = "0123456789876543210";
for ( string::iterator i = s.begin();
i != s.end();
   ++i )
cout << *i << " is digit " << stream_cast< int >( *i ) << "\n";


3) Dersom du sitter med et litt mer avansert tallsystem, kunne du
kanskje lage egen funksjon, som konverterer fra det aktuelle
tallsystemet til det du trenger. Det ville dog være direkte uklokt å
ikke bruke en eksisterende funksjon som strtol. strtol gjør _mye_ mer
enn det du trenger, men den takler fint alle mulige grunntall fra 2
til 36:


int
char_to_int( char c, int base )
{
string s = c;
errno = 0;
long tmp = strtol( s.c_str(), NULL, base );
if ( tmp == 0 && errno != 0 )
return -1;

// perfectly safe
return static_cast< int >( tmp );
}


string s = "absdef123456790";
for ( string::size_type i = 0U;
i != s.size();
++i )
cout << s[i] << " is digit " << char_to_int( s[i], 16 ) << "\n";

(grunnen til at dette virker er at c_str() returnerer en C-style
string, noe strtol (og atoi) kan jobbe med).

4) Man kan evt. bruker std::map til å lagre ett sett med mappinger fra
chars til de tilsvarende int'ene, men det blir relativt mye jobb å få
dette skrevet, så kanskje det ikke er verdt bryet før transformasjonen
er tilstrekkelig avansert.





ivr
--
striving to become a programmer... very hungry...
will code for foo^H^H^H^H solar cells...

Bjarke Walling Peter~ (28-10-2001)
Kommentar
Fra : Bjarke Walling Peter~


Dato : 28-10-01 10:17

Mange tak for svarene... det kunne bruges.

Måske skulle jeg bruge strings i stedet for char-arrays, men på det
fjernundervisnings-kursus jeg er ved at tage, er der i alle eksemplerne
brugt char-arrays (hvorfor de gør det, ved jeg ikke).

Jeg synes foresten også at det er ganske smart at en enkelt char bliver
behandlet som en ascii-værdi og man derfor kan trække 48 eller '0' fra, for
at få det som tal-værdi.

- Bjarke Walling Petersen



Mogens Hansen (28-10-2001)
Kommentar
Fra : Mogens Hansen


Dato : 28-10-01 11:04


"Bjarke Walling Petersen" <bwp@bwp.dk> wrote in message
news:3bdbccfd$0$219$edfadb0f@dspool01.news.tele.dk...
> Mange tak for svarene... det kunne bruges.
>

Godt

>
> Måske skulle jeg bruge strings i stedet for char-arrays, men på det
> fjernundervisnings-kursus jeg er ved at tage, er der i alle eksemplerne
> brugt char-arrays (hvorfor de gør det, ved jeg ikke).
>

Det er et faresignal, hvis man lærer om char-arrays før man lærer om
"std::string".
Det er et faresignal, hvis man lærer at skrive <iostream.h> i stedet for
<iostream>.
Det kan muligvis betyde at man ikke lærer moderne C++ - Standard C++.
Pointere og char-array er mere lavniveau koncepter, som ofte er sværere at
håndtere end "std::string".
Hvilket materiale bliver der benyttet til undervisningen ?

Se
http://www.two-sdg.demon.co.uk/curbralan/papers/TheMiseducationOfC++.pdf
for en beskrivelse af hvad jeg mener.
Se også bogen
Accelerated C++, Practical Programming by Example
Andrew Koenig, Barbara E. Moo
ISBN 0-201-70353-X
for en god (den bedste) introduktion til moderne C++.

Tid og mental kapacitet er en sparsom resource - brug dem med omtanke.

Venlig hilsen

Mogens Hansen




Bjarke Walling Peter~ (28-10-2001)
Kommentar
Fra : Bjarke Walling Peter~


Dato : 28-10-01 18:13

Mogens Hansen skrev:
> Det er et faresignal, hvis man lærer om char-arrays før man lærer om
> "std::string".

Det har du nok ret i... jeg prøver lige at skrive til min lærer
Foresten: Hvad er std og hvad betyder dobbeltkolon? - er std en slags class
eller hvad?
Man behøver jo ikke at skrive std:: ...

> Det er et faresignal, hvis man lærer at skrive <iostream.h> i stedet for
> <iostream>.

Jeg kan nu ikke se den store forskel...
Så vidt jeg kan se er det heller ikke alle filer, hvor man kan fjerne .h
(f.eks. stdlib.h) ... men man kan godt skrive .h på alle filer. Så måske gør
de det for simpelhedens skyld ... ?
Hvorfor skal man egentlig skrive .h på nogle filer og behøves ikke på
andre? - betyder det noget bestem om der står .h eller ikke?

> Det kan muligvis betyde at man ikke lærer moderne C++ - Standard C++.
> Pointere og char-array er mere lavniveau koncepter, som ofte er sværere at
> håndtere end "std::string".

Men synes du ikke også at man skal lære om char-arrays og pointere - evt.
efter man har lært om strings.
Jeg vil faktisk postulere at jeg er bedre til Visual Basic nu, fordi jeg
først lærte QBasic (hvis du kender det) - det skal i hvert fald siges at
QBasic er en del mere lavniveau'sk end Visual Basic!

> Hvilket materiale bliver der benyttet til undervisningen ?

Jeg tror det er noget læreren eller måske en fra den skole, selv har skrevet
(det ser det i hvert fald ud til).

[snip]

- Bjarke Walling Petersen



Mogens Hansen (28-10-2001)
Kommentar
Fra : Mogens Hansen


Dato : 28-10-01 23:28


"Bjarke Walling Petersen" <bwp@bwp.dk> wrote in message
news:3bdc3c8a$0$25384$edfadb0f@dspool01.news.tele.dk...
> Mogens Hansen skrev:
> > Det er et faresignal, hvis man lærer om char-arrays før man lærer om
> > "std::string".
>
> Det har du nok ret i... jeg prøver lige at skrive til min lærer
> Foresten: Hvad er std og hvad betyder dobbeltkolon? - er std en slags
class
> eller hvad?

Det er scope resolution operator.
Klassen "string" findes i "namespace std", derfor er dens fulde navn
"std::string". "std::string" er entydigt den streng klasse, der er beskrevet
i C++ Standarden, og som findes i ethvert anstændig C++ Standard Library
(som igen følger med de fleste anstændige C++ compilere).
Der kan potentiel eksistere andre "string" klasser, f.eks. "my_lib::string".

> Man behøver jo ikke at skrive std:: ...
>

Nej, man kan også først skrive
using std::string;
eller
using namespace std;
(eller den kan findes med Koenig lookup)
eller nogen kan have skrevet en "string" klasse som ligger globalt
namespace.
Men bortset fra disse tilfælde, skal man skrive std::string

> > Det er et faresignal, hvis man lærer at skrive <iostream.h> i stedet for
> > <iostream>.
>
> Jeg kan nu ikke se den store forskel...

Forskellen er pre-standard C++ og Standard C++.
C++ blev standardiseret i september 1998, men har været brugt de sidste ca.
20 år i stigende grad.
Man gør sig selv en tjeneste, hvis man lærer Standard C++. Det er
naturligvis udemærket at kende historien.
Der skete en del væsentlige ændringer med I/O klasserne undervejs.
Bl.a. blev de templatiseret for at understøtte andre tegntyper end "char"
(f.eks. "wchar_t"), der blev tilføjet locale (lande specifikke kodning af
f.eks. klokkeslet, datoer, decimal-punkt etc.) og klasserne kom til at ligge
i "namespace std".

> Så vidt jeg kan se er det heller ikke alle filer, hvor man kan fjerne .h
> (f.eks. stdlib.h) ... men man kan godt skrive .h på alle filer. Så måske
gør
> de det for simpelhedens skyld ... ?

I C++ hedder det "include <cstdlib>". "include <stdlib.h>" er C eller
pre-standard C++.
Mange compilere understøtter forsat den gamle form, for at være compatible.
Typisk kommer klasserne til at ligge i globalt namespace, når man bruger
<stdlib.h> formen.

> Hvorfor skal man egentlig skrive .h på nogle filer og behøves ikke på
> andre? - betyder det noget bestem om der står .h eller ikke?
>

På forskellige platforme, var der lidt forskellig tradition for hvad
header-filerne hedder. Nogle kaldte dem ".h" og andre ".hpp". Standarden
fjernede endelserne, og lagde indholdet i "namespace std".

>
> Men synes du ikke også at man skal lære om char-arrays og pointere - evt.
> efter man har lært om strings.

Jo da. Jeg syntes naturligvis at man skal lære det hele! Men det tager tid,
og man kan blive overvældet før man får skrevet brugbare programmer.
Du skrev i dit oprindelige indlæg at du var nybegynder med C++. Derfor er
det bedre at starte med at lære at _bruge_ klassen "std::string", frem for
f.eks.:
* hvordan håndteres pointere
* hvad er en null-termineret streng
* hvad er en klasse
* hvordan _skriver_ man en klasse

Hvis først man vil skrive _robuste_ programmer, bliver det endnu værre.
Se f.eks. Bjarne Stroustrup papir "Learning Standard C++ as a New Language"
http://www.research.att.com/~bs/new_learning.pdf

> Jeg vil faktisk postulere at jeg er bedre til Visual Basic nu, fordi jeg
> først lærte QBasic (hvis du kender det) - det skal i hvert fald siges at
> QBasic er en del mere lavniveau'sk end Visual Basic!
>

Det kan jeg godt forstå. Jo mere man ved om hvad der sker, des bedre kan man
beherske værktøjet.

> > Hvilket materiale bliver der benyttet til undervisningen ?
>
> Jeg tror det er noget læreren eller måske en fra den skole, selv har
skrevet
> (det ser det i hvert fald ud til).

Husk den bog jeg anbefalede.

Venlig hilsen

Mogens Hansen



Igor V. Rafienko (28-10-2001)
Kommentar
Fra : Igor V. Rafienko


Dato : 28-10-01 13:39

[ Bjarke Walling Petersen ]

[ snip ]

> Jeg synes foresten også at det er ganske smart at en enkelt char
> bliver behandlet som en ascii-værdi og man derfor kan trække 48
> eller '0' fra, for at få det som tal-værdi.


Du kan trekke fra '0' og det vil fungere. Derimot kan du _ikke_ trekke
fra 48 og regne med at koden vil fortsatt fungere. '1' - '0' == 1 er
garantert, '1' - 48 == 1 er derimot ikke det.





ivr
--
Ehh... I'll have a McRudolf menu, please.

Bjarke Walling Peter~ (28-10-2001)
Kommentar
Fra : Bjarke Walling Peter~


Dato : 28-10-01 17:53

Igor V. Rafienko skrev:
> Du kan trekke fra '0' og det vil fungere. Derimot kan du _ikke_ trekke
> fra 48 og regne med at koden vil fortsatt fungere. '1' - '0' == 1 er
> garantert, '1' - 48 == 1 er derimot ikke det.

Nå okay... jeg antog bare at det var ascii-værdier. Hvorfor virker '1' - 48
ikke altid?

- Bjarke Walling Petersen



Igor V. Rafienko (28-10-2001)
Kommentar
Fra : Igor V. Rafienko


Dato : 28-10-01 18:12

[ Bjarke Walling Petersen ]

[ snip ]


> Nå okay... jeg antog bare at det var ascii-værdier. Hvorfor virker
> '1' - 48 ikke altid?


SVJV garanterer standaren kun differansen mellom '1' og '0', ikke
_verdien_ av '0' (dvs. en implementasjon står fri til å bruke mer
eller mindre vilkårlige verdier for '0', '1', ... , '9', sålenge
differansen mellom påfølgende siffer er 1. Under ASCII enkoding så har
vel '0' verdien 48. Under andre enkodinger -- ikke nødvendigvis[*].





ivr
[*] argle, vi burde for lengst ha blitt enige om 1 felles språk og en
felles måte å representere glyph'ene i dette språket.
--
Good news everyone: I've taught the toaster to feel love
         Pr. Farnsworth, Futurama

Per Abrahamsen (28-10-2001)
Kommentar
Fra : Per Abrahamsen


Dato : 28-10-01 18:13

"Bjarke Walling Petersen" <bwp@bwp.dk> writes:

> Igor V. Rafienko skrev:
>> Du kan trekke fra '0' og det vil fungere. Derimot kan du _ikke_ trekke
>> fra 48 og regne med at koden vil fortsatt fungere. '1' - '0' == 1 er
>> garantert, '1' - 48 == 1 er derimot ikke det.
>
> Nå okay... jeg antog bare at det var ascii-værdier. Hvorfor virker '1' - 48
> ikke altid?

Fordi C også er implementeret på maskiner der ikke bruger ASCII,
f.eks. IBM's AS/400 serie.

Bjarke Walling Peter~ (28-10-2001)
Kommentar
Fra : Bjarke Walling Peter~


Dato : 28-10-01 18:15

Per Abrahamsen skrev:
> Fordi C også er implementeret på maskiner der ikke bruger ASCII,
> f.eks. IBM's AS/400 serie.

Men så længe man arbejder på en PC'er i Windows... ?

- Bjarke Walling Petersen



Bertel Lund Hansen (28-10-2001)
Kommentar
Fra : Bertel Lund Hansen


Dato : 28-10-01 18:58

Bjarke Walling Petersen skrev:

>Men så længe man arbejder på en PC'er i Windows... ?

I det konkrete tilfælde er der slet ingen grund til at undgå '0'.
Compileren oversætter det såmænd selv til 48. Til gengæld er der
en fordel ved at beholde '0'. Din kode kan også kompileres på en
obskur balinesisk computer med et gammelt styresystem.

Derudover er det faktisk mere meningsfuldt rent (kode)logisk at
trække '0' fra '1' end at trække en eller anden talværdi fra et
bogstav.

--
Bertel
http://lundhansen.dk/bertel/   FIDUSO: http://fiduso.dk/

Bjarke Walling Peter~ (28-10-2001)
Kommentar
Fra : Bjarke Walling Peter~


Dato : 28-10-01 19:08

Bertel Lund Hansen skrev:
> Derudover er det faktisk mere meningsfuldt rent (kode)logisk at
> trække '0' fra '1' end at trække en eller anden talværdi fra et
> bogstav.

Det er da næsten ligeså logisk at trække 48 fra... men det er nok bare mig
der har arbejdet for meget i DOS og QBasic

- Bjarke Walling Petersen



Igor V. Rafienko (28-10-2001)
Kommentar
Fra : Igor V. Rafienko


Dato : 28-10-01 19:30

[ Bjarke Walling Petersen ]

[ snip ]

> Det er da næsten ligeså logisk at trække 48 fra...


Nei, det er det _aldeles_ ikke. Og det er flere grunner til dette. For
det første burde koden gjenspeile det man egentlig forsøker å gjøre,
dvs. se differansen mellom 2 tegn, ikke differansen mellom et tegn og
et tall. Det fommes et uttrykk på engelsk som betegner den type tall
som forekommer i koden -- "magic numbers". Det er _svært_ sjelden lurt
å bruke slike.

For det andre eksisterer standarder for et formål. Dette formålet er å
gjøre livet til utviklere enklere. Når man forsøker å løse et problem,
skal man holde seg innenfor retningslinjene for språket av hensyn til
portabilitet, vedlikeholdbarhet og enkelthet. Naturligvis finnes det
problemområder som ikke er standarisert (fx. nettverkskommunikasjon),
og da er man nødt til å forbigå standarden. Problemet ditt faller
_opplagt_ ikke i en slik kategori.


> men det er nok bare mig der har arbejdet for meget i DOS og QBasic
>


Du har mye å avlære. Jo før du glemmer QBasic (og andre Basic
varianter), desto lettere blir livet ditt i framtiden bak skjermen.





ivr
--
Good news everyone: I've taught the toaster to feel love
         Pr. Farnsworth, Futurama

Bjarke Walling Peter~ (29-10-2001)
Kommentar
Fra : Bjarke Walling Peter~


Dato : 29-10-01 22:57

Igor V. Rafienko skrev:
> For det andre eksisterer standarder for et formål. Dette formålet er å
> gjøre livet til utviklere enklere.

Ja, det er da rigtigt. Men findes der da en C++-standard der siger at
'1'-'0' er mere rigtigt end '1'-48 ?

> Du har mye å avlære. Jo før du glemmer QBasic (og andre Basic
> varianter), desto lettere blir livet ditt i framtiden bak skjermen.

Tja... Jeg vil lige påpege (mest for C++-begyndere) at C++ godt kan være en
smule irritabel, da man langt fra har det samme sikkerhedsnet af (runtime)
fejlmeddelser, som man har i Basic. Jeg har indtil videre oplevet min
computer gå ned utallige gange pga. nogle fejl i mine C++-programmer.
Men jeg er jo som sagt nybegynder... Og dette sikkerhedsnet i Basic giver
også en (meget) langsom eksekvering... så selvfølgelig er C++ langt bedre -
når man kan det!

- Bjarke Walling Petersen



Morten Boysen (29-10-2001)
Kommentar
Fra : Morten Boysen


Dato : 29-10-01 23:21

"Bjarke Walling Petersen" <bwp@bwp.dk> wrote in message
news:3bddd0c2$0$25375$edfadb0f@dspool01.news.tele.dk...
> Igor V. Rafienko skrev:
> > For det andre eksisterer standarder for et formål. Dette formålet
er å
> > gjøre livet til utviklere enklere.
>
> Ja, det er da rigtigt. Men findes der da en C++-standard der siger
at
> '1'-'0' er mere rigtigt end '1'-48 ?

Det er en bedre løsning af flere grunde:

1) Det er portabelt.
2) Det er en standard.
3) Det er nemmere at læse.

1) er en fordel, da dit program kan køre på flere maskiner uden du
skal ændre på koden. Standarden sikrer at denne opførsel vil holde
mange år i fremtiden. Det er meget sjældent, man ikke sikrer fuld
bagudkompatibilitet med ældre standarder. Sidste men ikke mindst
sikrer 3), at en anden programmør kan ændre i din kode, uden at blive
forvirret. Man kan ligesågodt skrive sin kode så tæt på normalt sprog
som muligt. Meningen med '1' - '0' er umiddelbart klar, men det er
'1' - 48. Dette er hele ideen i højniveau sprog og oversættere. Når du
selv sætter '0' = 48, så påtager du dig oversætterens opgave. Er det
dette du ønsker, så kan du ligesågodt skrive assembler. Jeg kan ikke
se én god grund til at vælge '1' - 48 frem for '1' - '0'.


--
Morten Boysen


Igor V. Rafienko (30-10-2001)
Kommentar
Fra : Igor V. Rafienko


Dato : 30-10-01 00:57

[ Bjarke Walling Petersen ]

[ snip ]

> Men findes der da en C++-standard der siger at '1'-'0' er mere
> rigtigt end '1'-48 ?


Ja. Standarden heter ISO/IEC 14882:1998(E). Denne standarden
garanterer at differansen mellom '1' og '0' er 1, men den sier
ingenting om den numeriske verdien av tegnet '0' (eller '1' for den
saks skyld). (For å være helt korrekt -- det er C standarden som
legger det opp slik, men svjv refererer C++ standarden til C
standarden (ISO/IEC 9899:1990 eller 9899:1999) på dette punktet).

En annen ting er at _mennesker_ som leser koden assosierer '0' med
tegnet null mye raskere enn de assosierer tallet 48 først med ASCII
enkoding og så med tegnet null[*]. Koden i seg selv bør fortelle mest
mulig om hva som skjer (kommentarene tatt til side). Dokumentasjons-
(og intensjons-) messig er '0' et _mye_ bedre valg enn 48.

Sagt på en annen måte: hvilken av disse 2 funksjoner ville du ha
foretrukket:

void
foo( unsigned char c )
{
if ( __ctype_mask[c] & 0x00004000 )
   puts( "foo!" );
else
   puts( "bar!" );
}

eller

void
foo( unsigned char c )
{
if ( isalpha( c ) )
   puts( "foo!" );
else
   puts( "bar!" );
}

På en av implementasjonene jeg har adgang til er disse 2 versjoner av
foo semantisk ekvivalente (__ctype_mask er vel en eller annen bisarr
array på 256 bytes). Men jeg tviler ikke et sekund på at samtlige
C(++)-programmerere ville ha foretrukket den andre framfor den første,
da den formidler _hensikten_ mye bedre. Magiske tall à la 48 eller
0x00004000 er komplett _ubrukelige_ for menneskets vedkommende.

[*] Det er derfor jeg synes det finnes en vesentlig forskjell mellom
0, 0U, 0UL, NULL og '\0'. Dersom det ikke er meningsfylt å bruke et
navn for en slik konstant (ok, NULL er unntaket), så skal man iallfall
velge den riktige konstanten (bare så det er sagt: på en rekke
implementasjoner vil alle de overnevnte nullene være ekvivalente i
veldig mange kontekster).

[ snip ]


> Tja... Jeg vil lige påpege (mest for C++-begyndere) at C++ godt kan
> være en smule irritabel, da man langt fra har det samme
> sikkerhedsnet af (runtime) fejlmeddelser, som man har i Basic.


_Det_ stemmer nok. Det betyr ikke at du skal holde på vaner
innarbeidet fra ymse basic varianter.


> Jeg har indtil videre oplevet min computer gå ned utallige gange
> pga. nogle fejl i mine C++-programmer.


Det at din _datamaskin_ går ned som følge av din programmeringsfeil
betyr bare at du sitter på et bedritent OS (eller at du kjører med
superuser/administrator (dvs. alle) privilegiene (noe som ikke er
særlig lurt)). Løsningen da er naturligvis å installere et _skikkelig_
OS som ikke dør på seg, bare fordi en surrer litt med pekere.


> Men jeg er jo som sagt nybegynder... Og dette sikkerhedsnet i Basic
> giver også en (meget) langsom eksekvering... så selvfølgelig er C++
> langt bedre - når man kan det!


C++ har arvet "sikkerhetsnettet" til C (mao. ingenting). Dog, det er
bygd inn et par hjelpeelementer (som fx. std::string, std::vector,
exceptions og deres like) som kan gjøre livet litt enklere. Du kan fx.
la være å bruke arrays inntil videre og bruke utelukkende
std::vector::at, der du ville ellers ha brukt [] på en array. Alt
ettersom hvilken kompilator/omgivelse du bruker, kan det være praktisk
å ta i bruk en (forhåpentligvis grafisk) debugger som finner oftest
pekerfeilene man gjør. Men ja, det _er_ fryktelig synd at man ikke har
noe slikt:

$ python-latest
Python 2.2b1 (#3, Oct 27 2001, 23:34:24)
[GCC 2.95.2 19991024 (release)] on sunos5
Type "help", "copyright", "credits" or "license" for more information.
>>> l = range( 10 ); l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> l[10]
Traceback (most recent call last):
File "<stdin>", line 1, in ?
IndexError: list index out of range
>>>

Og forresten, i opplæringsstadiet har sikkerhetsnettet langt større
betydning enn eksekveringshastighet.

Om du synes det er litt plundrete (hvilket jeg har full forståelse for
selv (personlig vil jeg ha et sikkerhetsnett)), kan du prøve et annet
språk. Eller kan du lære å leve med litt plundrete språk :) Det finnes
dessverre ingen andre enklere oppskrifter.





ivr
--

Mogens Hansen (30-10-2001)
Kommentar
Fra : Mogens Hansen


Dato : 30-10-01 06:42


"Bjarke Walling Petersen" <bwp@bwp.dk> wrote in message
news:3bddd0c2$0$25375$edfadb0f@dspool01.news.tele.dk...

> Jeg har indtil videre oplevet min
> computer gå ned utallige gange pga. nogle fejl i mine C++-programmer.
> Men jeg er jo som sagt nybegynder... Og dette sikkerhedsnet i Basic giver
> også en (meget) langsom eksekvering... så selvfølgelig er C++ langt
bedre -
> når man kan det!

Det vigtige er at blive klar over hvilke fejl man laver, og lære af dem.
Hele tiden spørge: "hvordan kunne denne fejl være opdaget automatisk ?"
(f.eks. ved hjælp af compilerens statiske typecheck, ved hjælp af assert) og
"hvordan man man undgå at lave tilsvarende fejl i fremtiden ?" (f.eks. ved
at designe klare interfaces).
Se f.eks. bogen
Writing Solid Code : Microsoft's Techniques for Developing Bug-Free C
Programs
Steve Maguire
ISBN: 1556155514
den er virkelig god.
Filosifien er noget i retningen af: det er ikke svært - det er et spørgsmål
om håndværk.

Jeg vil anbefale at man bruger værktøjer, der hjælper med at finde klassiske
C og C++ fejl, såsom
buffer-overrun
dangling pointers
memory leak

Personligt har jeg bedst erfaring med CodeGuard, som er en del af Borland
C++Builder V5.0 Professional og Enterprise (www.borland.com).
Desuden er NuMega BoundsChecker (www.numega.com) til Microsoft Visual C++
(især med instrumentering) og Rational Purify (www.rational.com) ganske
glimrende værktøjer.

Man lærer meget når man bruger dem, og det giver en stor tryghed for at ens
program opfører sig pænt - og dermed er stabilt.

Desuden er det næsten en forudsætning for at skrive stabile programmer, at
man bruger klare og letforståelige program konstruktioner - sådan som bl.a.
Igor V. Rafienko har beskrevet i denne tråd (brug std::string, std::vector,
ingen magiske tal, skriv hvad du mener og men hvad du skriver etc.).

Venlig hilsen

Mogens Hansen



Kent Friis (01-11-2001)
Kommentar
Fra : Kent Friis


Dato : 01-11-01 20:18

Den Mon, 29 Oct 2001 22:57:18 +0100 skrev Bjarke Walling Petersen:
>Igor V. Rafienko skrev:
>> For det andre eksisterer standarder for et formål. Dette formålet er å
>> gjøre livet til utviklere enklere.
>
>Ja, det er da rigtigt. Men findes der da en C++-standard der siger at
>'1'-'0' er mere rigtigt end '1'-48 ?
>
>> Du har mye å avlære. Jo før du glemmer QBasic (og andre Basic
>> varianter), desto lettere blir livet ditt i framtiden bak skjermen.
>
>Tja... Jeg vil lige påpege (mest for C++-begyndere) at C++ godt kan være en
>smule irritabel, da man langt fra har det samme sikkerhedsnet af (runtime)
>fejlmeddelser, som man har i Basic. Jeg har indtil videre oplevet min
>computer gå ned utallige gange pga. nogle fejl i mine C++-programmer.
>Men jeg er jo som sagt nybegynder... Og dette sikkerhedsnet i Basic giver
>også en (meget) langsom eksekvering... så selvfølgelig er C++ langt bedre -
>når man kan det!

Sjovt - min computer går aldrig ned pga. C-programmer. De stopper blot
med en fejlmelding, hvis jeg har lavet noget forkert.

Min computer på arbejdet kan derimod sagtens gå ned (eller i hvert fald
blive ustabil / ubrugelig) pga. et Visual Basic program.

Mvh
Kent
--
http://www.celebrityshine.com/~kfr/

Bertel Lund Hansen (28-10-2001)
Kommentar
Fra : Bertel Lund Hansen


Dato : 28-10-01 19:49

Bjarke Walling Petersen skrev:

>Det er da næsten ligeså logisk at trække 48 fra... men det er nok bare mig
>der har arbejdet for meget i DOS og QBasic

Det er 20 år siden jeg begyndte at skrive assemblerprogrammer og
hurtigt lærte ASCII-koderne udenad.

--
Bertel
http://lundhansen.dk/bertel/   FIDUSO: http://fiduso.dk/

Søg
Reklame
Statistik
Spørgsmål : 177501
Tips : 31968
Nyheder : 719565
Indlæg : 6408522
Brugere : 218887

Månedens bedste
Årets bedste
Sidste års bedste