/ 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
Er et std::list element garanteret at forb~
Fra : Thomas Krog


Dato : 23-05-01 20:18

Hvis man ikke kan regne med at std::list elementerne bliver på samme sted er
det jo nærmest umuligt at lave en graf/et netværk hvor elementerne er
allokeret i en stl containerer. Nedenstående eksempel udskriver 2
forskellige værdier af *p i vc++. Er det vc++ som ikke overholder ansi c++
standarden?

#include <list>
#include <iostream>
using namespace std;

int *p;
class Test{
list<int> ls;
public:
Test(){
// indsæt elementer til ls
// udfør et par andre ting
p = &(*ls.begin());
cout << "*p = " << *p;
}
};

int main(){
Test t;
cout << "*p = " << *p;
return 0;
}




 
 
Mogens Hansen (23-05-2001)
Kommentar
Fra : Mogens Hansen


Dato : 23-05-01 22:14

Hej Thomas,
"Thomas Krog" <rick@kampsax.dtu.dk> wrote in message
news:9eh2cj$93n$1@eising.k-net.dk...
> Hvis man ikke kan regne med at std::list elementerne bliver på samme sted
er
> det jo nærmest umuligt at lave en graf/et netværk hvor elementerne er
> allokeret i en stl containerer. Nedenstående eksempel udskriver 2
> forskellige værdier af *p i vc++. Er det vc++ som ikke overholder ansi c++
> standarden?

Når jeg kører dit eksempel i Visual C++ V6.0 udskriver den samme værdi begge
gange (4198512).
Du får den åbenbart til at skrive 2 forskellige værdier.
Umiddelbart mener jeg at begge dele er i overensstemmelse med ANSI C++:
"udefined behaviour".
Du derefererer "ls.begin()", som for en tom liste så du skriver hvad der
svarer til "*ls.end()", hvilket jeg mener er "undefined behaviour".

Dit eksempel viser ikke det du spørger om.
Dit eksempel skriver værdien af den integer som "p" peger på ud.
Det viser ikke noget om hvilken adresse elementet ligger på.

Jeg mener ikke at standarden siger noget om hvilken adresse elementerne i en
std::list ligger på.
Den beskæftiger sig ikke med adressen på elementerne i containere - den
beskræftiger sig derimod med iteratorer.
Standarden (§23.2.2.3) siger at når man indsætter elementer i en liste,
påvirker det ikke gyldigheden af iteratorer og referencer.
Når man sletter fra en liste bliver kun iteratorer og referencer til det/de
slettede elementer ugyldige.

Dit eksempel kan ikke belyse hvorvidt Visual C++ (eller andre compilere)
overholder standarden på dette punkt.
Jeg vil dog blive forundret hvis Microsoft Visual C++ V6.0 ikke overholder
standarden på dette punkt.


>
> #include <list>
> #include <iostream>
> using namespace std;
>
> int *p;
> class Test{
> list<int> ls;
> public:
> Test(){
> // indsæt elementer til ls
> // udfør et par andre ting
> p = &(*ls.begin());
> cout << "*p = " << *p;
> }
> };
>
> int main(){
> Test t;
> cout << "*p = " << *p;
> return 0;
> }
>

Venlig hilsen

Mogens Hansen



Thomas Krog (24-05-2001)
Kommentar
Fra : Thomas Krog


Dato : 24-05-01 02:04

> Når jeg kører dit eksempel i Visual C++ V6.0 udskriver den samme værdi
begge
> gange (4198512).
> Du får den åbenbart til at skrive 2 forskellige værdier.
> Umiddelbart mener jeg at begge dele er i overensstemmelse med ANSI C++:
> "udefined behaviour".
> Du derefererer "ls.begin()", som for en tom liste så du skriver hvad der
> svarer til "*ls.end()", hvilket jeg mener er "undefined behaviour".

ja, jeg burde have fremhævet mine to kommentarer noget tydeligere:
> > // indsæt elementer til ls
> > // udfør et par andre ting

da de spiller en væsentlig rolle.

> Dit eksempel viser ikke det du spørger om.

Rigtigt. Det skyldes at fejlen opstod i et lidt komplekst program, hvor det
ville tage en del tid at omdanne det til et eksempel der ville være
overkommeligt at sætte sig ind i her på nyhedsgruppen (dette har jeg
imidlertid gjort nu)

> Dit eksempel skriver værdien af den integer som "p" peger på ud.
> Det viser ikke noget om hvilken adresse elementet ligger på.

Jo, hvis jeg får forskellige udskrifter må det medføre at liste-elementet er
blevet flyttet væk.

> Jeg mener ikke at standarden siger noget om hvilken adresse elementerne i
en
> std::list ligger på.
> Den beskæftiger sig ikke med adressen på elementerne i containere - den
> beskræftiger sig derimod med iteratorer.
> Standarden (§23.2.2.3) siger at når man indsætter elementer i en liste,
> påvirker det ikke gyldigheden af iteratorer og referencer.
> Når man sletter fra en liste bliver kun iteratorer og referencer til
det/de
> slettede elementer ugyldige.

Det var præcis det jeg var ude efter i mit første indlæg.

> Dit eksempel kan ikke belyse hvorvidt Visual C++ (eller andre compilere)
> overholder standarden på dette punkt.
> Jeg vil dog blive forundret hvis Microsoft Visual C++ V6.0 ikke overholder
> standarden på dette punkt.

Her er et eksempel som (så vidt jeg kan se) viser at vc++ ikke overholder
standarden på det punkt du nævner. Fejlen kommer kun når konstruktoren til
Test bliver kaldt 2 gange:

#include <list>
#include <iostream>
using namespace std;

list<int>::iterator p;

class Test{
list<int> ls;
public:
Test(){
ls.push_back(5);
p = ls.begin();
cout << "*p = " << *p << endl;;
}
};

Test t;

int main(int argc, char* argv[])
{
t = Test();
cout << "*p = " << *p;
return 0;
}





Mogens Hansen (24-05-2001)
Kommentar
Fra : Mogens Hansen


Dato : 24-05-01 08:12

Hej Thomas,
"Thomas Krog" <rick@kampsax.dtu.dk> wrote in message
news:9ehnck$15n$1@eising.k-net.dk...
> > Når jeg kører dit eksempel i Visual C++ V6.0 udskriver den samme værdi
> begge
> > gange (4198512).
> > Du får den åbenbart til at skrive 2 forskellige værdier.
> > Umiddelbart mener jeg at begge dele er i overensstemmelse med ANSI C++:
> > "udefined behaviour".
> > Du derefererer "ls.begin()", som for en tom liste så du skriver hvad der
> > svarer til "*ls.end()", hvilket jeg mener er "undefined behaviour".
>
> ja, jeg burde have fremhævet mine to kommentarer noget tydeligere:
> > > // indsæt elementer til ls
> > > // udfør et par andre ting
>
> da de spiller en væsentlig rolle.

Jeg så dem godt, og prøvede også at tilføje en push_back. Det gav ikke nogen
non-compliant opførsel.
Det ændrer ikke på at det ikke belyser om et element i en liste forbliver på
samme adresse. Pointeren bliver kun tildelt en værdi een gang, hvorfor den
vil have samme værdi begge gange det den peger på bliver skrevet.

>
> > Dit eksempel viser ikke det du spørger om.
>
> Rigtigt. Det skyldes at fejlen opstod i et lidt komplekst program, hvor
det
> ville tage en del tid at omdanne det til et eksempel der ville være
> overkommeligt at sætte sig ind i her på nyhedsgruppen (dette har jeg
> imidlertid gjort nu)

Godt - eller kan det være svært at forstå hvad du mener.

>
> > Dit eksempel skriver værdien af den integer som "p" peger på ud.
> > Det viser ikke noget om hvilken adresse elementet ligger på.
>
> Jo, hvis jeg får forskellige udskrifter må det medføre at liste-elementet
er
> blevet flyttet væk.

Nej, det må betyde at det som pointeren peger på har ændret værdi.

>
> > Jeg mener ikke at standarden siger noget om hvilken adresse elementerne
i
> en
> > std::list ligger på.
> > Den beskæftiger sig ikke med adressen på elementerne i containere - den
> > beskræftiger sig derimod med iteratorer.
> > Standarden (§23.2.2.3) siger at når man indsætter elementer i en liste,
> > påvirker det ikke gyldigheden af iteratorer og referencer.
> > Når man sletter fra en liste bliver kun iteratorer og referencer til
> det/de
> > slettede elementer ugyldige.
>
> Det var præcis det jeg var ude efter i mit første indlæg.

Det tænkte jeg godt - men det var ikke det din kode viste.

>
> Her er et eksempel som (så vidt jeg kan se) viser at vc++ ikke overholder
> standarden på det punkt du nævner. Fejlen kommer kun når konstruktoren til

Hvilken version af Visual C++ bruger du ?
Hvilken opførsel ser du ?
Hvad, så præcist som muligt, mener du er problemet ?

> Test bliver kaldt 2 gange:
>
> #include <list>
> #include <iostream>
> using namespace std;
>
> list<int>::iterator p;
>
> class Test{
> list<int> ls;
> public:
> Test(){
> ls.push_back(5);
> p = ls.begin();
> cout << "*p = " << *p << endl;;
> }
> };
>
> Test t;
>
> int main(int argc, char* argv[])
> {
> t = Test();
> cout << "*p = " << *p;
> return 0;
> }
>

Det er jo et væsentligt anderledes program end det første, du præsenterede.

Det som jeg ser er at programmet skriver:
*p = 5
*p = 5
*p = -17891602
hvilket ikke er i modstrid med ANSI C++. Det er fortsat "undefined
behaviour".
Hvis jeg kører med BoundsChecker samtidig, skriver det
*p = 5
*p = 5
*p = 5
hvilket heller ikke er i modstrid med ANSI C++. Dog lidt skræmmende, at den
"skjuler" problemet uden at rapportere fejl.

Hvis jeg kører det med Borland C++Builder V5.0 med CodeGuard slået til
(CodeGuard bør altid være slået til under udvikling!), får jeg en
fejlmeldingen "pointer arithmetic in freed memory" (med tilhørende
kaldestak), på linien i main hvor det som p peger på bliver skrevet ud.
Desuden kommer der kaldestakken til hvor hukommelsen blev allokeret og hvor
den blev frigivet.

Prøv at lav en destructor (tom) til Test, og singlestep i gennem programmet.
Tænk over gyldigheden af det som p referer til.
Prøv at arbejd lidt med det selv, og sig til hvis du mangler et hint.

Venlig hilsen

Mogens Hansen

PS.
Det er væsentligt mere almindeligt at man selv laver fejl, end at der er
fejl i udviklingsværktøjerne.



Thomas Krog (24-05-2001)
Kommentar
Fra : Thomas Krog


Dato : 24-05-01 10:18

> Godt - eller kan det være svært at forstå hvad du mener.

ok, du får din vilje (selvom jeg mener det er unødvendigt) så her er en
ændring i main funktionen:

int main()
{
t = Test();
if(t.ls.begin() != p)
cout << "mystisk (efter min mening)" << endl;
else
cout << "som jeg ville forvente" << endl;

return 0;
}

> Hvilken opførsel ser du ?

det samme som du gør i eksempel nr. 2.
I det nye eksempel får jeg: "mystisk (efter min mening)

> Hvad, så præcist som muligt, mener du er problemet ?

at t.ls.begin() ændrer værdi fra sidste linje i konstruktoren som er kaldt
i main og frem til if sætningen

> PS.
> Det er væsentligt mere almindeligt at man selv laver fejl, end at der er
> fejl i udviklingsværktøjerne.

Det ved jeg, men jeg har grov svært ved at se hvorfor det opfører sig som
det gør. Jeg har dog prøvet det på g++ og får samme resultat så det er nok
mig der tager fejl.



Mogens Hansen (24-05-2001)
Kommentar
Fra : Mogens Hansen


Dato : 24-05-01 10:51

Hej Thomas,
"Thomas Krog" <rick@kampsax.dtu.dk> wrote in message
news:9eijkv$idh$1@eising.k-net.dk...

> int main()
> {
> t = Test();

Her opretter du et temporært, ikke navngivet objekt af typen "Test". "t"
bliver tildelt værdien af dette temporære objekt, hvorefter det temporære
objekt bliver nedlagt. Hint: implementer destructor og assignment operator,
læg break-points og single-step gennem koden.
I constructoren til det temporære objekt bliver "p" tildelt en gyldig værdi.
Da det temporære objekt bliver nedlagt efter tildelingen, vil "p" pege på
noget der er nedlagt. Dereferering af "p" giver herefter "undefined
behaviour".
Husk at "p" bliver tildelt en værdi 2 gange - een for hver gang Test
constructoren bliver udført.
Når du assigner en list, svarer det til at listen bliver tømt (hvorved alle
iteratorer bliver ugyldige), hvorefter den bliver fyldt op igen.

> if(t.ls.begin() != p)
> cout << "mystisk (efter min mening)" << endl;
> else
> cout << "som jeg ville forvente" << endl;
>
> return 0;
> }

>
> at t.ls.begin() ændrer værdi fra sidste linje i konstruktoren som er
kaldt
> i main og frem til if sætningen

Det kan du ikke se ud fra den kode du har postet i denne tråd.
Du husker ikke den oprindelige værdi af "t.ls.begin()" nogen steder.

> det gør. Jeg har dog prøvet det på g++ og får samme resultat så det er nok
> mig der tager fejl.

Det er en udemærket strategi at sammenligne 2 uafhængige implementeringer,
hvis man er i tvivl. Dog kan begge være fejlbehæftede.

Venlig hilsen

Mogens Hansen



Thomas Krog (24-05-2001)
Kommentar
Fra : Thomas Krog


Dato : 24-05-01 11:57

Mogens Hansen <mogens_h@dk-online.dk> skrev i en
nyhedsmeddelelse:9eilg3$11r9$1@news.cybercity.dk...
> Hej Thomas,
> "Thomas Krog" <rick@kampsax.dtu.dk> wrote in message
> news:9eijkv$idh$1@eising.k-net.dk...
>
> > int main()
> > {
> > t = Test();
>
> Her opretter du et temporært, ikke navngivet objekt af typen "Test". "t"
> bliver tildelt værdien af dette temporære objekt, hvorefter det temporære
> objekt bliver nedlagt.

doh! Jeg følte mig nok lidt for sikker i min sag...
(og var alt for fokuseret på at std::list var synderen)

Dette er så også en ret ineffektiv løsning hvis der ligger en stor
datastruktur gemt
i Test objektet. Vil det sige at det er umuligt omdefinere et objekt med
brug af konstruktoren uden at assignment operatoren bliver kaldt? Dvs. at
"problemet" kun kan løses ved at flytte indholdet af konstruktoren over i en
init funktion og så skrive noget i stil med:
t.init();
hver gang objektet skal omdefineres.

Men jeg kan godt se at:
t();
vil få det til at se ud som om det er en funktion der skal kaldes i stedet
for konstruktoren til objektet t (ikke særlig læsevenligt)



Mogens Hansen (24-05-2001)
Kommentar
Fra : Mogens Hansen


Dato : 24-05-01 13:12

> i Test objektet. Vil det sige at det er umuligt omdefinere et objekt med
> brug af konstruktoren uden at assignment operatoren bliver kaldt? Dvs. at

Ikke forstået. Har du et eksempel ?

> "problemet" kun kan løses ved at flytte indholdet af konstruktoren over i
en
> init funktion og så skrive noget i stil med:
> t.init();

Nej, nej, forhåbentlig ikke.

> hver gang objektet skal omdefineres.

Ikke forstået.
Hvad er problemet ?

Venlig hilsen

Mogens Hansen



Thomas Krog (24-05-2001)
Kommentar
Fra : Thomas Krog


Dato : 24-05-01 14:16

> Ikke forstået. Har du et eksempel ?

Hvis man fx. skulle lave et tekstbehandlingsprogram kunne man forestille sig
at det dokument som brugeren skriver på ligger i et globalt objekt:

TextDoc doc;

Brugeren skal nu have mulighed for at indlæse dokumenter fra filer. Hvis
denne indlæsning skulle foretages via en konstruktor kunne det fx. se
således ud:

class TextDoc{
TextDoc(std::string fileName); // opretter et TextDoc via en indlæsning
fra en tekstfil
};

Hvis jeg skulle gøre dette ville jeg med mit nuværende kendskab til c++ vil
jeg skrive noget med:

int main(){
doc = TextDoc("test.txt"); // først får brugeren lyst til at skrive
lidt i denne fil
doc = TextDoc("enandenfil.txt"); // senere skal der redigeres lidt i
denne fil
return 0;
}
Dette er dog ikke så smart da assignment operatoren bliver brugt til at
kopiere TextDoc som måske er stor. Kan konstruktoren kaldes så doc bliver
omkonstrueret uden at assignment operatoren bliver brugt?

En anden mulighed var:

class TextDoc{
init(std::string fileName); // omdefinerer et TextDoc via en indlæsning
fra en tekstfil
};
int main(){
doc.init("test.txt"); // først får brugeren lyst til at skrive lidt i
denne fil
doc.init("enandenfil.txt"); // senere skal der redigeres lidt i denne
fil
return 0;
}

Denne løsning er mere effektiv da den undgår assignment operatoren, dog
bliver konstruktoren overhovedet ikke brugt. Hvordan løses det bedst?



Mogens Hansen (24-05-2001)
Kommentar
Fra : Mogens Hansen


Dato : 24-05-01 14:54


"Thomas Krog" <rick@kampsax.dtu.dk> wrote in message
news:9ej1j5$ti1$1@eising.k-net.dk...

> Hvis jeg skulle gøre dette ville jeg med mit nuværende kendskab til c++
vil
> jeg skrive noget med:
>
> int main(){
> doc = TextDoc("test.txt"); // først får brugeren lyst til at skrive
> lidt i denne fil
> doc = TextDoc("enandenfil.txt"); // senere skal der redigeres lidt i
> denne fil
> return 0;


Som regel er "init" funktioner ikke at foretrække frem for anvendelse af
constructorer.
En god egenskab ved constructoren er at den kan bringe et objekt i en ønsket
tilstand, og hvis det ikke kan lade sig gøre, kan constructoren smide en
exception.

I dit eksempel er det måske smartere at bruge en pointer eller en
auto-pointer:

std::auto_ptr<TextDoc> doc;

void foo(void)
{
doc = std::auto_ptr<TextDoc>(new TextDoc("test.txt"));
doc = std::auto_ptr<TextDoc>(new TextDoc("enandenfil.txt"));
}

En anden funktion du nok skal være opmærksom på er "swap".
Den kan f.eks. bytte indholdet af 2 containere på en meget effektiv måde.
Du har sikkert en bog, hvor de er beskrevet.

Venlig hilsen

Mogens Hansen

PS
Jeg har ikke compileret ovenstående - der kan være fejl i det.



Igor V. Rafienko (23-05-2001)
Kommentar
Fra : Igor V. Rafienko


Dato : 23-05-01 22:38

* Thomas Krog

> Hvis man ikke kan regne med at std::list elementerne bliver på samme
> sted


De gjør det. Kun iterators/pekere til elementer som blir slettet
(erase()) invalideres.


> er det jo nærmest umuligt at lave en graf/et netværk hvor
> elementerne er allokeret i en stl containerer. Nedenstående eksempel
> udskriver 2 forskellige værdier af *p i vc++. Er det vc++ som ikke
> overholder ansi c++ standarden?

[snip]

Både Sun CC5.0 og g++-2.95.2 gjør det du ville ha gjort. Jeg ser ingen
grunn til at ting ikke skal fungere slik du vil det.





ivr
--
Documentation is like sex: when it is good, it is very, very good; and
when it is bad, it is better than nothing.
                  -- Dick Brandon

Thomas Krog (24-05-2001)
Kommentar
Fra : Thomas Krog


Dato : 24-05-01 02:08

> Både Sun CC5.0 og g++-2.95.2 gjør det du ville ha gjort. Jeg ser ingen
> grunn til at ting ikke skal fungere slik du vil det.

Det kunne være nyttigt at vide hvordan de 2 compilere reagerer på det nye
eksempel jeg har postet




Anders Bo Rasmussen (24-05-2001)
Kommentar
Fra : Anders Bo Rasmussen


Dato : 24-05-01 09:22

On 23 May 2001 23:37:48 +0200,
Igor V. Rafienko <igorr@ifi.uio.no> wrote:

>> Hvis man ikke kan regne med at std::list elementerne bliver på samme
>> sted
>
>De gjør det. Kun iterators/pekere til elementer som blir slettet
>(erase()) invalideres.

Jeg går ud fra at det er en del af standarden?

--
Anders Bo Rasmussen mailto:fuzz01@spamfilter.dk
Frimestervej 42 1.tv http://www.fuzz.dk
2400 Kbh. NV
Denmark

Mogens Hansen (24-05-2001)
Kommentar
Fra : Mogens Hansen


Dato : 24-05-01 09:41

> >
> >De gjør det. Kun iterators/pekere til elementer som blir slettet
> >(erase()) invalideres.
>
> Jeg går ud fra at det er en del af standarden?

ja, §23.2.2.3

Venlig hilsen

Mogens Hansen




Anders Bo Rasmussen (24-05-2001)
Kommentar
Fra : Anders Bo Rasmussen


Dato : 24-05-01 10:21

On Thu, 24 May 2001 10:40:56 +0200,
Mogens Hansen <mogens_h@dk-online.dk> wrote:

>> >
>> >De gjør det. Kun iterators/pekere til elementer som blir slettet
>> >(erase()) invalideres.
>>
>> Jeg går ud fra at det er en del af standarden?
>
>ja, §23.2.2.3

I hvilket dokument? Og hvor får man fat i det dokument?

--
Anders Bo Rasmussen mailto:fuzz01@spamfilter.dk
Frimestervej 42 1.tv http://www.fuzz.dk
2400 Kbh. NV
Denmark

Mogens Hansen (24-05-2001)
Kommentar
Fra : Mogens Hansen


Dato : 24-05-01 10:51

> I hvilket dokument? Og hvor får man fat i det dokument?

ISO C++ Standarden:
INTERNATIONAL STANDARD ISO/IEC 14882
ISO/IEC 14882:1998(E)

Det kan købes på
http://webstore.ansi.org/AnsiDocStore/shopper_lookup.asp
for $18.00

Venlig hilsen

Mogens Hansen



Anders Bo Rasmussen (24-05-2001)
Kommentar
Fra : Anders Bo Rasmussen


Dato : 24-05-01 12:12

On Thu, 24 May 2001 11:51:25 +0200,
Mogens Hansen <mogens_h@dk-online.dk> wrote:

>> I hvilket dokument? Og hvor får man fat i det dokument?
>
>ISO C++ Standarden:
>INTERNATIONAL STANDARD ISO/IEC 14882
>ISO/IEC 14882:1998(E)
>
>Det kan købes på
>http://webstore.ansi.org/AnsiDocStore/shopper_lookup.asp
>for $18.00

Hmm. 18 dollars for en pdf-fil. Hvor mange sidder er den på, og er den
beregnet til at udskrive i duplex? Jeg skal nemlig have printet den på
en ordentlig printer, hvis jeg skal give 18 dollars for en fil.

Er der en ny udgave på vej? Det ville være lidt ærgerligt hvis jeg skal
betale en gang til inden for et halvt år.

--
Anders Bo Rasmussen mailto:fuzz01@spamfilter.dk
Frimestervej 42 1.tv http://www.fuzz.dk
2400 Kbh. NV
Denmark

Mogens Hansen (24-05-2001)
Kommentar
Fra : Mogens Hansen


Dato : 24-05-01 13:10

>
> Hmm. 18 dollars for en pdf-fil. Hvor mange sidder er den på, og er den

Hvordan skal standardiserings arbejdet betales ?
Viden er penge værd.

> beregnet til at udskrive i duplex? Jeg skal nemlig have printet den på
> en ordentlig printer, hvis jeg skal give 18 dollars for en fil.

776 sider, som er til at skrive ud i duplex.

>
> Er der en ny udgave på vej? Det ville være lidt ærgerligt hvis jeg skal
> betale en gang til inden for et halvt år.

Nej, der er ikke en ny udgave på vej.
Det varer nogle år.

Venlig hilsen

Mogens Hansen



Anders Bo Rasmussen (24-05-2001)
Kommentar
Fra : Anders Bo Rasmussen


Dato : 24-05-01 15:06

On Thu, 24 May 2001 14:09:59 +0200,
Mogens Hansen <mogens_h@dk-online.dk> wrote:

>>
>> Hmm. 18 dollars for en pdf-fil. Hvor mange sidder er den på, og er den
>
>Hvordan skal standardiserings arbejdet betales ?
>Viden er penge værd.

Joe. Det ville være billigere hvis jeg fandt den på et bibliotek. Regner
dog med at købe den - og printe den i duplex. Så er spørgsmålet bare
hvordan man får 776/2 sider indbundet.

>> beregnet til at udskrive i duplex? Jeg skal nemlig have printet den på
>> en ordentlig printer, hvis jeg skal give 18 dollars for en fil.
>
>776 sider, som er til at skrive ud i duplex.
>
>>
>> Er der en ny udgave på vej? Det ville være lidt ærgerligt hvis jeg skal
>> betale en gang til inden for et halvt år.
>
>Nej, der er ikke en ny udgave på vej.
>Det varer nogle år.
>
>Venlig hilsen
>
>Mogens Hansen
>
>


--
Anders Bo Rasmussen mailto:fuzz01@spamfilter.dk
Frimestervej 42 1.tv http://www.fuzz.dk
2400 Kbh. NV
Denmark

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