/ 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
????
Fra : Anders Jensen


Dato : 31-07-01 08:34

Der skulle vel ikke være nogen, der kan svare på følgende spørgmål ang.
nedenstående prg-stump...

double a,b;
............................
x=0;ofstream t_fil("TEMPUS FUGI.DAT,ios::trunc");
while (x!=10){ cin>>a>>b;if (cin.fail()){x=10;}
else {t_fil.write((char *)&a,sizeof(ab));
t_fil.write((char *)&b,sizeof(ab));}
}cout<<" slut "<<endl;cin.clear();

1 ) Der er intet problem første gang stumpen kaldes - men anden gang
fungerer den ikke
Jeg formoder - at det skyldes, at cin.fail() sætter en fejlbit. Men
hvordan fjernes den igen ??
Jeg har forsøg med cin.clear() - men det virker ikke.

2 ) Ved datainput cin>>a>>b skiftes der linie ved hvert enter, hvorledes
undgårs det ???

--
LINUS
linus@post2.tele.dk








 
 
Igor V. Rafienko (31-07-2001)
Kommentar
Fra : Igor V. Rafienko


Dato : 31-07-01 14:33

[ Anders Jensen ]

> Der skulle vel ikke være nogen, der kan svare på følgende spørgmål
> ang. nedenstående prg-stump...


Tips #1: prøv å få koden til å se litt mindre jævlig ut

[omformatert for lesbarhet]

> double a,b;
> ...........................
> x=0;
> ofstream t_fil("TEMPUS FUGI.DAT,ios::trunc");
^^            ^^    ^^         

Dette vil ikke kompilere engang.

std::ofstream t_fil( "TEMPUS FUGI.DAT", std::ios_base::trunc );
if ( !t_fil ) {
std::cerr << "failed to open file\n";
exit( 1 );
}


> while (x!=10) {
> cin>>a>>b;
>
> if ( cin.fail() ) {
> x=10;
> }
> else {
> t_fil.write((char *)&a,sizeof(ab));
               ^^

skal dette gi mening?


> t_fil.write((char *)&b,sizeof(ab));
> }
> }
>
> cout<<" slut "<<endl;
> cin.clear();


Jeg forstår ikke hvorfor du trenger en _heltalls_variabel for å
avbryte løkken og dertil på en såpass klønete måte.

while ( std::cin >> a >> b )
t_fil.write( (char*)&a, sizeof a );
t_fil.write( (char*)&b, sizeof b );
}

std::cin.clear();
std::cout << "done\n";


> 1 ) Der er intet problem første gang stumpen kaldes - men anden gang
> fungerer den ikke
> Jeg formoder - at det skyldes, at cin.fail() sætter en fejlbit. Men
> hvordan fjernes den igen ??


kallet på fail() setter _aldri_ noen feilbit (kallet på fail()
returnerer true dersom failbit eller badbit er satt). Hvis du vil lese
så lenge begge disse betingelsene:

1) det er noe å lese igjen
2) det er ikke oppstått feil under innlesing av elementene

er oppfylt, så er det basic_ios:erator!()/basic_ios:erator
void*() man bruker, slik jeg antydet over.


> Jeg har forsøg med cin.clear() - men det virker ikke.


Det er vanskelig å svare når du ikke engang har forklart hva du vil
oppnå. Det at koden kan _umulig_ kompileres gjør ikke saken enklere.
Hva er det du vil oppnå? Hva er det som _faktisk_ skjer? Hvordan er
disse to forskjellige fra hverandre?

$ g++ bar.cpp
$ ./a.out
2.2 1.3
^D
end of input
conversion failed or read past EOF
done
$ ./a.out
foo bar
conversion failed or read past EOF
done
$ cat bar.cpp
#include <iostream>
#include <fstream>


int
main()
{
using namespace std;
double a, b;

ofstream ofs( "foo", ios_base::trunc );
if ( !ofs )
exit( 1 );

while ( cin >> a >> b ) {
ofs.write( (char*)&a, sizeof a );
ofs.write( (char*)&b, sizeof b );
}
ofs.close();

if ( cin.eof() )
cerr << "end of input\n";
if ( cin.fail() )
cerr << "conversion failed or read past EOF\n";
if ( cin.bad() )
cerr << "something is very wrong\n";
cin.clear();
cout << "done\n";
}
$


Legg merke til forskjellen i output'en når man avslutter input'en
"normalt" eller forer inn gale data (i første tilfellet er fail satt
pga. "read past EOF" mens i det andre tilfellet er det konverteringen
som gikk galt).


> 2 ) Ved datainput cin>>a>>b skiftes der linie ved hvert enter, hvorledes
> undgårs det ???


Portabelt? Du gjør ikke det. Relativt portabelt? Alt ettersom -- fx.
ncurses. Det finnes neppe en enkel oppskrift. Hvorfor vil du ha det?





ivr
--
Amy: Psst... look what life was like before genetic engeneering.
Leela: Those poor 20th century women...
-- Futurama, "Why must I be a Crustacean in love?"

Anders Jensen (31-07-2001)
Kommentar
Fra : Anders Jensen


Dato : 31-07-01 16:05


> Tips #1: prøv å få koden til å se litt mindre jævlig ut > [omformatert for
lesbarhet]

Hm! - Det er jo blot QD-programering.

> > double a,b;
> > ...........................
> > x=0;
> > ofstream t_fil("TEMPUS FUGI.DAT,ios::trunc");
> ^^ ^^ ^^
> Dette vil ikke kompilere engang.

Det kompiles fint under VC++ 6.0
Hele fuktionen er: (Undskyld skrivemåden)

void SKRIV_EN_FIL(void)
{int x ;double a,b,ab;ab=5;
x=0;ofstream t_fil("TEMPUS FUGI.DAT,ios::trunc");
while (x!=10){ cin>>a>>b;if (cin.fail()){x=10;cout<<x;}
else {t_fil.write((char *)&a,sizeof(ab));
t_fil.write((char *)&b,sizeof(ab));}
}cout<<" slut "<<endl;cin.clear(0);}

> skal dette gi mening?

Ja - Faktisk
Når man kommer ind i løkken kan man indskrive double-værdier i filen .Indtil
der indtastes f.eks et bogstav, hvorefter
man springer ud . Det fungere fint - Problemet er at funktionen kun virker
en gang - Formodenligt pga
cin.fail()

> kallet på fail() setter _aldri_ noen feilbit (kallet på fail()
> returnerer true dersom failbit eller badbit er satt). Hvis du vil lese
> så lenge begge disse betingelsene:
>
> 1) det er noe å lese igjen
> 2) det er ikke oppstått feil under innlesing av elementene

> er oppfylt, så er det basic_ios:erator!()/basic_ios:erator
> void*() man bruker, slik jeg antydet over.

Men det er jo netop meningen, at det skal opstår en fejl under
indlæsning -så løkken brydes-Problemet opstår først når man vender tilbage
for, at genbruge funktionen.

> Det er vanskelig å svare når du ikke engang har forklart hva du vil oppnå.
Det at koden kan _umulig_ kompileres gjør ikke saken enklere.

Det kan den altså........

> > 2 ) Ved datainput cin>>a>>b skiftes der linie ved hvert enter, hvorledes
> > undgårs det ???
.. Hvorfor vil du ha det?

Tro det eller lad være - Men det var for at få udskriften til "å se litt
mindre jævlig ut "

--
LINUS
linus@post2.tele.dk



Igor V. Rafienko (31-07-2001)
Kommentar
Fra : Igor V. Rafienko


Dato : 31-07-01 18:08

[ Anders Jensen ]

[ snip ]

> > > ofstream t_fil("TEMPUS FUGI.DAT,ios::trunc");
> > ^^           ^^ ^^
> > Dette vil ikke kompilere engang.
>
> Det kompiles fint under VC++ 6.0


Ah, riktig, så du *vil* lage en fil med navnet:

TEMPUS FUGI.DAT,ios::trunc

i tillegg til å ignorere std::. Beklager, jeg antok at du ville
trunkere filen dersom den fantes fra før av.


> Hele fuktionen er: (Undskyld skrivemåden)


Er det _så_ vanskelig å omformattere koden litegrann? Sånn at de
vanlige dødelige kan lese denne IOCCC kandidaten?


> void SKRIV_EN_FIL(void)
> {int x ;double a,b,ab;ab=5;


Definisjonen av ab var *ikke* med i den opprinnelige artikkelen.
Forstår du hvorfor det er viktig å formattere koden noenlunde
akseptabelt?


> x=0;ofstream t_fil("TEMPUS FUGI.DAT,ios::trunc");
> while (x!=10){ cin>>a>>b;if (cin.fail()){x=10;cout<<x;}
> else {t_fil.write((char *)&a,sizeof(ab));
> t_fil.write((char *)&b,sizeof(ab));}


Hvorfor oppgir du størrelsen av et annet objekt enn det du faktisk
skriver ut?


> }cout<<" slut "<<endl;cin.clear(0);}


For de mistroiske:

$ g++ bar.cpp
bar.cpp: In function `void SKRIV_EN_FIL()':
bar.cpp:7: `ofstream' undeclared (first use this function)
bar.cpp:7: (Each undeclared identifier is reported only once for each function
it appears in.)
bar.cpp:7: parse error before `(' token
bar.cpp:8: `cin' undeclared (first use this function)
bar.cpp:8: `cout' undeclared (first use this function)
bar.cpp:9: `t_fil' undeclared (first use this function)
bar.cpp:11: `endl' undeclared (first use this function)

Hvorfor nekter folk for det opplagte? Og dertil har du rettet opp noen
av feilene i den opprinnelige artikkelen. Nei, snutten kompileres ikke
(hva VC++ måtte akseptere får være dens sak. Heller ikke kompilatoren
var spesifisert i den opprinnelige artikkelen (ikke at det har noe å
si for svaret)).

[snip min kommentar til "t_fil.write((char *)&a,sizeof(ab)"]


> > skal dette gi mening?
>
> Ja - Faktisk
> Når man kommer ind i løkken kan man indskrive double-værdier i
> filen.


Ja, det er nå så. Men hvorfor kan ikke du skrive:

t_fil.write( (char *)&a, sizeof a );

heller enn å bruke størrelsen på en variabel som ikke har noe med a å
gjøre? Hva er vitsen med å ha variabelen ab som ikke skal brukes i
koden?


> Indtil der indtastes f.eks et bogstav, hvorefter man springer ud .
> Det fungere fint - Problemet er at funktionen kun virker en gang -
> Formodenligt pga cin.


Delvis, ja. Generelt: streams i C++ er ikke akkurat det jeg ville
kalle "enkelt". En meget omstendig og bra bok som forklarer hvordan
alt henger sammen er denne:

<URL:http://www.langer.camelot.de/iostreams.htm>

Ta en titt.


> > kallet på fail() setter _aldri_ noen feilbit (kallet på fail()
> > returnerer true dersom failbit eller badbit er satt). Hvis du vil lese
> > så lenge begge disse betingelsene:
> >
> > 1) det er noe å lese igjen
> > 2) det er ikke oppstått feil under innlesing av elementene
>
> > er oppfylt, så er det basic_ios:erator!()/basic_ios:erator
> > void*() man bruker, slik jeg antydet over.
>
> Men det er jo netop meningen, at det skal opstår en fejl under
> indlæsning -så løkken brydes-Problemet opstår først når man vender
> tilbage for, at genbruge funktionen.


Ah, greit. Jeg gikk glipp av at funksjonen skulle kunne kalles flere
ganger.

Idet en man prøver å lese det første tegnet fra en stream og man
prøver å konvertere det tegnet til en double og det ikke går, settes
tilstanden til "fail" og tegnet forblir i input-bufferet. Neste gang
funksjonen kalles skjer nøyaktig det samme, da den feilaktige input'en
ikke ble fjernet (det "feilaktige" tegnet vil fremdeles være det som
leses først ved neste forsøk). Dersom man har linjevis input (hvilket
skjer ofte ved bruken av std::cin) går det an å ignorere all input
fram til og med '\n'. Dersom input'en ikke er linjebasert er det litt
mer vanskelig å si hva man skal "hoppe over".

Man kan gjøre ting fx. slik (ikke idiotsikkert, men det burde gi en
pekepinne):

$ cat zot.cpp
/*
*
* $Id$
*
* Copyright (C) 2001 by Igor V. Rafienko, <igorr@ifi.uio.no>
*
*/
#include <iostream>
#include <string>
#include <sstream>
#include <climits>
#include <fstream>


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


void
writeToFile( const std::string &name, std::istream &is )
{
using namespace std;

cout << "\tprocessing: " << name << endl;

ofstream ofs( name.c_str(), ios_base::trunc );
if ( !ofs )
exit( 1 );

double a, b;
while ( is >> a >> b ) {
ofs.write( (char*)&a, sizeof a );
ofs.write( (char*)&b, sizeof b );
}
ofs.flush();
ofs.close();

if ( is.fail() ) {
cerr << "stream failed";
// reached end of data while reading
if ( is.eof() ) {
cerr << " because of read past EOF\n";
is.clear();
}
// conversion failed. Ignore til end-of-line
else {
cerr << " because of erroneous input (ignoring)\n";
is.clear();
is.ignore( INT_MAX, '\n' ); // Mogens: ja, jeg er lat
}
}
else if ( is.bad() ) {
// stream is corrupted internally
cerr << "unrecoverable error while reading\n";
exit( 2 );
}
cout << "\tdone with: " << name << endl;
}


int
main( int argc, char *argv[] )
{
using namespace std;

int limit = stream_cast< int >( argv[ 1 ] ? argv[ 1 ] : "3" );
for ( int i = 0; i != limit; ++i ) {
string s = stream_cast< string >( i );
writeToFile( "datafile" + s, cin );
}
}
$ g++ zot.cpp
$ ./a.out 3
processing: datafile0
1 2
3 4
asdasd
stream failed because of erroneous input (ignoring)
done with: datafile0
processing: datafile1
5 6
stream failed because of read past EOF
done with: datafile1
processing: datafile2
8 9
stream failed because of read past EOF
done with: datafile2
$ ls -l datafile*
-rw------- 1 igorr igorr 32 Jul 31 18:58 datafile0
-rw------- 1 igorr igorr 16 Jul 31 18:58 datafile1
-rw------- 1 igorr igorr 16 Jul 31 18:58 datafile2
$


Jeg er ganske sikker på at det var et tilfelle jeg har glemt når det
gjelder håndtering av årsaker til hvorfor input fra is feil'et, men
ok, la gå.


> > Det er vanskelig å svare når du ikke engang har forklart hva du
> > vil oppnå. Det at koden kan _umulig_ kompileres gjør ikke saken
> > enklere.
>
> Det kan den altså........


Hvis jeg siterer standarden, vil du tro meg da? Koden som du oppga
trenger ikke å kunne kompileres. Og det gjør den ikke heller på en
rekke kompilatorer. "Det kan den altså" ikke.


> > > 2 ) Ved datainput cin>>a>>b skiftes der linie ved hvert enter,
> > > hvorledes undgårs det ???
> >
> > Hvorfor vil du ha det?
>
> Tro det eller lad være - Men det var for at få udskriften til "å se
> litt mindre jævlig ut "


Utskriften? Hva har input fra std::cin med _utskrift_ å gjøre?
*forvirret*...





ivr
--
You'd feel bad about not having a social life if only you could remember
what it was like to have one.
               IB stress descriptors

Anders Jensen (31-07-2001)
Kommentar
Fra : Anders Jensen


Dato : 31-07-01 19:46


> > void SKRIV_EN_FIL(void)
> > {int x ;double a,b,ab;ab=5;
> Definisjonen av ab var *ikke* med i den opprinnelige artikkelen.
> Forstår du hvorfor det er viktig å formattere koden noenlunde
> akseptabelt?

Hm...Tja....Ja...Ja

> t_fil.write( (char *)&a, sizeof a );
> heller enn å bruke størrelsen på en variabel som ikke har noe med a å
> gjøre? Hva er vitsen med å ha variabelen ab som ikke skal brukes i
> koden?

Det er rigtigt . Du har ret.Det er spild og noget sjusk ( Det er hvad der
sker når man i dovenskab " klippe/klistre/genbruger" linier andetsteds fra
i programmet

> > Indtil der indtastes f.eks et bogstav, hvorefter man springer ud .
> > Det fungere fint - Problemet er at funktionen kun virker en gang -
Formodenligt pga cin.
>
> Delvis, ja. Generelt: streams i C++ er ikke akkurat det jeg ville
> kalle "enkelt". En meget omstendig og bra bok som forklarer hvordan
> alt henger sammen er denne:
>
> <URL:http://www.langer.camelot.de/iostreams.htm>
>
Takker for tipset

> Idet en man prøver å lese det første tegnet fra en stream og man
> prøver å konvertere det tegnet til en double og det ikke går, settes
> tilstanden til "fail" og tegnet forblir i input-bufferet. Neste gang
> funksjonen kalles skjer nøyaktig det samme, da den feilaktige input'en
> ikke ble fjernet (det "feilaktige" tegnet vil fremdeles være det som
> leses først ved neste forsøk). (snip)

Men findes der ikke i VC++ en simpel ordre som tømmer input-bufferen
??(flusch)

> Man kan gjøre ting fx. slik (ikke idiotsikkert, men det burde gi en
> pekepinne):/*( snip voldsomt )> $ (snip) input fra is feil'et, men
> ok, la gå.

Takker for teksten-har ikke nået at gennemgå den endnu.

> Hvis jeg siterer standarden, vil du tro meg da? Koden som du oppga
> trenger ikke å kunne kompileres. Og det gjør den ikke heller på en
> rekke kompilatorer. "Det kan den altså" ikke.

Jeg ikke i tvivl om, at du nok skal have ret i, at koden formelt set ikke
kan kompiles. Men jeg gik ikke efter det formelle
men reelle tilfælde, som du tidligere komenterede "hva VC++ måtte akseptere
får være dens sak. "

> > > > 2 ) Ved datainput cin>>a>>b skiftes der linie ved hvert enter,
> > > > hvorledes undgårs det ???
> > >
> > > Hvorfor vil du ha det?
> > Tro det eller lad være - Men det var for at få udskriften til "å se
> > litt mindre jævlig ut "
>
> Utskriften? Hva har input fra std::cin med _utskrift_ å gjøre?
> *forvirret*...
Ikke noget..........Det var en sproglig "bøf"..Det var bare, hvad der så
pænt ud på skærmen.




Igor V. Rafienko (31-07-2001)
Kommentar
Fra : Igor V. Rafienko


Dato : 31-07-01 21:10

[ Anders Jensen ]

[ snip ]

> Men findes der ikke i VC++ en simpel ordre som tømmer input-bufferen
> ??(flusch)


Ta en titt på koden som jeg postet (nei, det er ikke flush(). Den
fungerer _aldri_ på input streams).

[ snip ]


> Jeg ikke i tvivl om, at du nok skal have ret i, at koden formelt set
> ikke kan kompiles. Men jeg gik ikke efter det formelle men reelle
> tilfælde, som du tidligere komenterede "hva VC++ måtte akseptere får
> være dens sak. "


Det reelle tilfellet er at koden kompileres ikke. Period.

[ snip ]





ivr
--
HÁÒÏÄÎÁÑ ÐÒÉÍÅÔÁ: åÓÌÉ áÄÍÉÎ × 09:00 ÎÁ ÒÁÂÏÞÅÍ ÍÅÓÔÅ - ÚÎÁÞÉÔ, ÓÅÒ×ÅÒ
ÎÅ ÒÁÂÏÔÁÅÔ.

Jesper Wolf Jesperse~ (11-08-2001)
Kommentar
Fra : Jesper Wolf Jesperse~


Dato : 11-08-01 19:14

Hej Anders.

"Anders Jensen" <linus@post2.tele.dk> wrote in message
news:3b665eec$0$3213$edfadb0f@dspool01.news.tele.dk...
> Der skulle vel ikke være nogen, der kan svare på følgende spørgmål ang.
> nedenstående prg-stump...

[...... cut ..... ]

Det var dog noget frygteligt rod du har postet, ulæseligt og så kan det ikke
engang oversættes.

Der er en meget større chance for at få ordentlig hjælp med dine problemer
hvis du gider at gøre forabejdet selv. Altså skrive en kodespump der kan
læses og oversættes, så slipper du for alt det ubrugelige kævl og får
istedet løst dit problem.

> 1 ) Der er intet problem første gang stumpen kaldes - men anden gang
> fungerer den ikke
> Jeg formoder - at det skyldes, at cin.fail() sætter en fejlbit. Men
> hvordan fjernes den igen ??
> Jeg har forsøg med cin.clear() - men det virker ikke.

Dit problem er at du ikke tømmer de data ud af input bufferen som fik
indlæsningen til at stoppe første gang. Jeg har her reformateret din kode
lidt og rettet op på miseren.

-----
#include <fstream.h>
int test()
{
double a,b;
int x=0;
ofstream t_fil("TEMPUS FUGI.DAT", ios::trunc);
while (x!=10)
{
cin >> a >> b;
if (cin.fail())
{
x=10;
}
else
{
t_fil.write((char *)&a,sizeof(a));
t_fil.write((char *)&b,sizeof(b));
}
}
cout<<" slut "<<endl;
cin.clear();
return 0;
}


int main (int argc, char* argv[])
{
char buffer[128];
for (int i=0; i<5; i++)
{
cout << "forsøg nr " << i << endl;
test();
buffer[0]='\0';
cin >> buffer;
cout << "cin indeholdt '"<< buffer << "'" <<endl;
}
return 0;
}
-----

> 2 ) Ved datainput cin>>a>>b skiftes der linie ved hvert enter, hvorledes
> undgårs det ???

Jeg kender ikke svaret på dette problem, jeg er bange for at du ikke kan
slippe for det uden at skrive din egen input rutine.

med venlig hilsen
Jesper Wolf Jespersen

PS. Programmet laver ikke ret meget fornuftigt, hvert kald til test
overskriver datafilen, men det kan du vel gennemskue



Igor V. Rafienko (11-08-2001)
Kommentar
Fra : Igor V. Rafienko


Dato : 11-08-01 20:23

[ Jesper Wolf Jespersen ]

[ snip ]

> int main (int argc, char* argv[])
> {
> char buffer[128];
> for (int i=0; i<5; i++)
> {
> cout << "forsøg nr " << i << endl;
> test();
> buffer[0]='\0';
> cin >> buffer;


Nei. Iallfall ikke uten width. Og det vil definitivt ikke gjøre det du
ønsker.





ivr
--
ëÓÔÁÔÉ, Ñ yÖÅ ÎÅ × ÐÅp×ÙÊ pÁÚ ÚÁÍÅÞÁÀ, ÞÔÏ ÏÎ ÉÎÏÇÄÁ ÓÔÁÎÏ×ÉÔÓÑ
yÄÉ×ÉÔÅÌØÎÏ ÎyÄÎÙÊ. þÔÏ ÚÁ ÍÁÎÅpÁ - ÐÏÄ ×ÓÅ ÐÏÄ×ÏÄÉÔØ ËÁËyÀ-ÔÏ ÂÁÚy É
ÄÅÊÓÔ×Ï×ÁÔØ ÉÓËÌÀÞÉÔÅÌØÎÏ ÐÏÄ ×ÏÚÄÅÊÓÔ×ÉÅÍ pÁÚyÍÁ, Á ÎÅ Þy×ÓÔ×?
   -- "úÁÐÉÓËÉ ÖÅÎÙ - ðÏÓÌÅÄÎÉÅ ÄÎÉ ÐÅÒÅÄ Ó×ÁÄØÂÏÊ", á. üËÓÌÅÒ

Jesper Wolf Jesperse~ (11-08-2001)
Kommentar
Fra : Jesper Wolf Jesperse~


Dato : 11-08-01 23:22

Hej Igor.
"Igor V. Rafienko" <igorr@ifi.uio.no> wrote in message
news:xjv3d6y5rlu.fsf@konungsblod.ifi.uio.no...
> [ Jesper Wolf Jespersen ]
>
> [ snip ]
>
> > int main (int argc, char* argv[])
> > {
> > char buffer[128];
> > for (int i=0; i<5; i++)
> > {
> > cout << "forsøg nr " << i << endl;
> > test();
> > buffer[0]='\0';
> > cin >> buffer;
>
>
> Nei. Iallfall ikke uten width. Og det vil definitivt ikke gjøre det du
> ønsker.

Jeg må indrømme at jeg ikke fatter hvad du mener.

Koden virker, den er cuttet direkte fra VC6 hvor den selvfølgeligt er blevet
testet inden den blev postet. Den virker også med gcc ver 2.91 som jeg lige
har testet der skal man bare huske en -lstdc++ i kommandolinien.

Hvad er det du tror jeg vil opnå ?
Hvorfor tror du ikke jeg opnår det ?

Kunne du ikke tage og komme med lidt information i stedet for kun at komme
med korte uforståelige påstande.
Det forudsætter selvfølgeligt at du ved hvad du taler om og kan udtrykke
dette i ord, men det kan du vel ?

med venlig hilsen
Jesper Wolf Jespersen


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


Dato : 12-08-01 01:29

[ Jesper Wolf Jespersen ]


> > > char buffer[128];
(...)
> > > buffer[0]='\0';
> > > cin >> buffer;
(...)


> > Nei. Iallfall ikke uten width. Og det vil definitivt ikke gjøre
> > det du ønsker.
>
> Jeg må indrømme at jeg ikke fatter hvad du mener.


En liten liste av ting jeg mener er feil:

a) buffer overflow (dersom det ligger mer enn 128 på stdin, så
begynner op>>() å skrible på hukommelsen som man ikke har kontroll
over. Anta at det står 10MB med data på stdin. Hva skjer med
programmet ditt da? (Kanskje jeg burde legge dette til kremeksempler
på hvorfor char* ikke skal brukes).

b) '\0' er _komplett_ meningsløs i koden over.

c) Selv om du hadde brukt setw()-manipulatoren for å fikse a), så
ville ikke dette ha vært tilstrekkelig: dersom det er mer input i
vente enn sizeof buffer, så vil påfølgende kall feile med samme
resultat. Strengt tatt ville koden fungere, men på flere forsøk enn
nødvendig.

d) Selv om du hadde brukt setw()-manipulatoren for å fikse a), så
ville ikke dette ha vært tilstrekkelig, siden op>>() for char*'ere
stopper på whitespace. Dvs. samme situasjon som i c)


> Koden virker,


Åh?

$ ./a.out < inputfile
forsøg nr 0
slut
Segmentation fault
$ ls -l inputfile
-rw------- 1 igorr igorr 300000 Aug 12 02:10 inputfile
$

(hmm, og der ser ut som at man trenger ikke så mye som det engang).

IMO har Henning Makholm gitt den beste beskrivelsen av denne
situasjonen:

[quote]

hvilket betyder at sprogdefinitionen tillader oversætteren at gøre
hvadsomhelst med den, inklusive oversætte den til kode der får små
nisser til at danse rundt om skærmen og råbe ukvemsord ad
programmøren.

[/quote]

Et annet spørsmål er _hvordan_ du fant at koden faktisk virket (særlig
med tanke på at jeg viste at den ikke virket uten å kompilere den
engang)?


> den er cuttet direkte fra VC6 hvor den selvfølgeligt er blevet
> testet inden den blev postet.


Veldig bra. Hadde ikke Dijkstra et utsagn om bugs og testing?

[ snip ]


> Hvad er det du tror jeg vil opnå ?


Det som basic_istream :: ignore() gjør. Tar jeg feil?


> Hvorfor tror du ikke jeg opnår det ?


Fordi programmet ikke virker.

[ snip ]





ivr
--
Amy: Psst... look what life was like before genetic engeneering.
Leela: Those poor 20th century women...
-- Futurama, "Why must I be a Crustacean in love?"

Jesper Wolf Jesperse~ (12-08-2001)
Kommentar
Fra : Jesper Wolf Jesperse~


Dato : 12-08-01 16:42

Hej Igor.

"Igor V. Rafienko" <igorr@ifi.uio.no> wrote in message
news:xjvae16xgro.fsf@konungsblod.ifi.uio.no...
> [ Jesper Wolf Jespersen ]
>
>
> > > > char buffer[128];
> (...)
> > > > buffer[0]='\0';
> > > > cin >> buffer;
> (...)
>
>
> > > Nei. Iallfall ikke uten width. Og det vil definitivt ikke gjøre
> > > det du ønsker.
> >
> > Jeg må indrømme at jeg ikke fatter hvad du mener.
>
>
> En liten liste av ting jeg mener er feil:
>
> a) buffer overflow (dersom det ligger mer enn 128 på stdin, så
> begynner op>>() å skrible på hukommelsen som man ikke har kontroll
> over. Anta at det står 10MB med data på stdin. Hva skjer med
> programmet ditt da? (Kanskje jeg burde legge dette til kremeksempler
> på hvorfor char* ikke skal brukes).

Jeg indrømmer blankt at der ikke er taget hensyn til buffer overflow.
Men det oprindelige spørgsmål som blev postet i denne tråd var hvorfor man
ikke kunne læse flere tal ind fra cin efter første afslutning, og det
spørgsmål har jeg besvaret.

Den simple form for input håndtering som det oprindelige program brugte er
generelt ikke brugbar i produktionskode, men jeg synes ikke der var nogen
grund til at indsætte tonsvis af fejlhåndtering og buffersikring blot for at
vise hvordan man tømmer uønskede data ud af input bufferen.


> b) '\0' er _komplett_ meningsløs i koden over.

Næ, det betyder at strengen er veldefineret selv om cin ikke giver noget
input. det betyder at udskrivningen længere nede ikke skriver garbage ud.

> c) Selv om du hadde brukt setw()-manipulatoren for å fikse a), så
> ville ikke dette ha vært tilstrekkelig: dersom det er mer input i
> vente enn sizeof buffer, så vil påfølgende kall feile med samme
> resultat. Strengt tatt ville koden fungere, men på flere forsøk enn
> nødvendig.

Du har ret der findes bedre måder at håndtere uønsket input på, men jeg
kunne vise hvad det var der blokerede for den videre indlæsning og det var
mit point.

Jeg tillader mig at stoppe tråden her for jeg er ret sikker på at vi ikke
får mere ud af mudderkastning.

Mit formål med at poste et svar var at der ikke var nogen der havde rettet
mandens kode så han kunne se hvad problemet var.
At der stadigt er masser af problemet med at håndtere input på den måde kan
der ikke være tvivl om.

Jeg benytter generelt ikke c++ streams i mine programmer fordi der er alt
for mange fejlmuligheder og at fordelen med at de er lettere at læse og
skrive forsvinder når disse fejl skal håndteres.

Jeg foretrækker at bruge gammeldags i/o via fscanf() og så videre, men det
har jo nok noget at gøre med at jeg har brugt den familie af funktioner så
længe at de ligger på rygraden.

At en bufferoverløbsfejl ikke behøver at være et stort problem kan ses af
login rutinen til unix, alle viste at der blev brugt en gets() i denne
rutine og at der kunne ske bufferoverløb men det var først i 90'erne at der
var nogen der brugte dette hul til at lave balade. Dengang skrev Morris en
virus der udnyttede hullet, men koden havde da været i drift i et par årtier
uden problemer.

Der findes ikke fejlfri kode, men det forhindrer ikke koden i at virke.

med venlig hilsen
Jesper Wolf Jespersen


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


Dato : 12-08-01 17:23

[ Jesper Wolf Jespersen ]

[ snip ]

> Jeg indrømmer blankt at der ikke er taget hensyn til buffer
> overflow.


Det ville ikke ha vært nødvendig, hadde du brukt riktig framgangsmåte.
Det å lese ting man egentlig ikke vil og dertil ved hjelp av op>>() er
ikke løsningen.


> Den simple form for input håndtering som det oprindelige program
> brugte er generelt ikke brugbar i produktionskode, men jeg synes
> ikke der var nogen grund til at indsætte tonsvis af fejlhåndtering
> og buffersikring blot for at vise hvordan man tømmer uønskede data
> ud af input bufferen.


Tonnvis? Det er snakk om _ett_ funksjonskall.


> > b) '\0' er _komplett_ meningsløs i koden over.
>
> Næ, det betyder at strengen er veldefineret selv om cin ikke giver
> noget input. det betyder at udskrivningen længere nede ikke skriver
> garbage ud.


Så vidt jeg ser fra 27.6.1.2.3, p 7 vil op>>() alltid sørge for å
skrive '\0'.

[ snip ]


> Mit formål med at poste et svar var at der ikke var nogen der havde
> rettet mandens kode så han kunne se hvad problemet var.


<URL:news:xjv7kwpdo1j.fsf@krokstjaki.ifi.uio.no>. IMO har jeg påpekt
hva feilen var og foreslo en løsning. En løsning som håndterer alle de
overnevnte tilfellene som feilet programmet ditt. Og en løsning som
er, imo, riktig i dette tilfellet.

[ snip ]


> Jeg foretrækker at bruge gammeldags i/o via fscanf() og så videre,


Det forklarer den interessante framgangsmåten.


> men det har jo nok noget at gøre med at jeg har brugt den familie af
> funktioner så længe at de ligger på rygraden.


Det forbauser meg dog at du foretrekker å jobbe med et verktøysett der
det er lettere å gjøre feil. Noe så banalt som en std::getline må se
_grusomt_ ut med fscanf().


> At en bufferoverløbsfejl ikke behøver at være et stort problem kan
> ses af login rutinen til unix, alle viste at der blev brugt en
> gets() i denne rutine og at der kunne ske bufferoverløb men det var
> først i 90'erne at der var nogen der brugte dette hul til at lave
> balade. Dengang skrev Morris en virus der udnyttede hullet, men
> koden havde da været i drift i et par årtier uden problemer.


Ah, så du vet tom. om konsekvensene av buffer-overflow, men velger
allikevel å ikke gjøre det _minst_ nødvendige for å forsikre noenlunde
koden din mot slike feil?


> Der findes ikke fejlfri kode, men det forhindrer ikke koden i at
> virke.


Jo, det gjør nettopp det. Løsningen er vanvittig enkel og jeg forstår
ikke hvorfor du _velger_ å ikke innse det.





ivr
--
Amy: Psst... look what life was like before genetic engeneering.
Leela: Those poor 20th century women...
-- Futurama, "Why must I be a Crustacean in love?"

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

Månedens bedste
Årets bedste
Sidste års bedste