/ 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
Crash, men hvor?
Fra : Mads A. Jensen


Dato : 19-05-02 21:02

Hej

Jeg er ny til c++. Når jeg afvikler følgende kode, kommer der en fejl, men
hvad skyldtes fejlen:

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <iostream.h>
#include <fstream.h>

int main(int argc, char *argv[])
{
char *line;
char *file;
int *i;
if(argv[1] == NULL){
cout << "Location of file: ";
cin >> file;
}
else{
file = argv[1];
}

ifstream filep(file);

while(!filep.eof()){
filep.getline(line, sizeof(line));
i = (i + 1);
}
cout << "Number of lines in file were: " << i << endl;
return 0;
}

Det skal lige siges, at jeg bruger MinGw og Dev C++ 4. På en Windows 2000
maskine!

Mange tak for hjælpen.

/Mads
--

--
Mads Jensen
http://ddfr.dk - Dansk Donaldist Forening
http://www.disney-comics.dk - Free Disney comics on the web!
info@disney-comics.dk



 
 
Anders Borum (19-05-2002)
Kommentar
Fra : Anders Borum


Dato : 19-05-02 21:34

"Mads A. Jensen" <mads@NOSPAManything.dk> skrev i en meddelelse
news:ac906c$8pj$1@sunsite.dk...
> Hej
>
> Jeg er ny til c++. Når jeg afvikler følgende kode, kommer der en fejl, men
> hvad skyldtes fejlen:

Hej Mads

Dit eksempel indeholder flere mulige årsager til fejlen.

[klip]
> int main(int argc, char *argv[])
> {
> char *line;
> char *file;
> int *i;
> if(argv[1] == NULL){
Hvis programmet kaldes uden argumenter er argv[1] ikke
veldefineret. Når du sammenligner det med NULL kan du
risikere en fejl.

I stedet for at checke om argv[1] == NULL skulle du
hellere undersøge om argc (argument count) er stor nok.

> cout << "Location of file: ";
> cin >> file;
Du indlæser her en linie fra terminalen og placerer den
i hukommelsen som file-variablen peger på. Men file peger
ikke nogen steder hen og så vil et eller andet gå galt.

Du kunne erklære file som en array:
char file[80];
Men det kan stadig gå galt hvis der bliver indtastet for mange
tegn på terminalen.

> }
> else{
> file = argv[1];
> }
>
> ifstream filep(file);
>
> while(!filep.eof()){
> filep.getline(line, sizeof(line));

Her gentager problemet sig med line.

> i = (i + 1);
> }
> cout << "Number of lines in file were: " << i << endl;
> return 0;
> }
[klip]



Anders Melchiorsen (19-05-2002)
Kommentar
Fra : Anders Melchiorsen


Dato : 19-05-02 21:48

"Anders Borum" <overflade@fedt.dk> skrev:

> Hvis programmet kaldes uden argumenter er argv[1] ikke veldefineret.

Hm, argv[] er nulafsluttet, såfremt argc > 0.

Strengt taget har du ret, men præmissen er "argc==0", ikke "programmet
kaldes uden argumenter".


> Du kunne erklære file som en array:
> char file[80];

Et bedre valg er nok

std::string file;


Anders.

--
Address is valid for a week.
After that, remove (only) the '.day-JJJ-YYYY' part.

Ivan Johansen (19-05-2002)
Kommentar
Fra : Ivan Johansen


Dato : 19-05-02 21:51

Anders Melchiorsen wrote:

> "Anders Borum" <overflade@fedt.dk> skrev:
> Strengt taget har du ret, men præmissen er "argc==0", ikke "programmet
> kaldes uden argumenter".


Er det muligt? Indeholder argv[0] ikke altid filnavnet?

Ivan Johansen



Anders Melchiorsen (19-05-2002)
Kommentar
Fra : Anders Melchiorsen


Dato : 19-05-02 23:35

Ivan Johansen <NG@Padowan.dk> skrev den 19-May-02:

> Anders Melchiorsen wrote:
>
> > "Anders Borum" <overflade@fedt.dk> skrev:
> > Strengt taget har du ret, men præmissen er "argc==0", ikke "programmet
> > kaldes uden argumenter".
>
>
> Er det muligt? Indeholder argv[0] ikke altid filnavnet?

Ikke hvis argc er lig nul.

I øvrigt kan argv[0][0] også være nul, selv hvis argc>0.


Anders.

--
Address is valid for a week.
After that, remove (only) the '.day-JJJ-YYYY' part.

Ivan Johansen (20-05-2002)
Kommentar
Fra : Ivan Johansen


Dato : 20-05-02 00:01

Anders Melchiorsen wrote:

> Ikke hvis argc er lig nul.
>
> I øvrigt kan argv[0][0] også være nul, selv hvis argc>0.


Men kan argc være 0? Så har programmet ikke noget filnavn. Er det muligt?


Ivan Johansen


Byrial Jensen (20-05-2002)
Kommentar
Fra : Byrial Jensen


Dato : 20-05-02 08:36

Ivan Johansen <NG@Padowan.dk> skrev:
> Anders Melchiorsen wrote:
>
>> Ikke hvis argc er lig nul.
>>
>> I øvrigt kan argv[0][0] også være nul, selv hvis argc>0.
>
> Men kan argc være 0? Så har programmet ikke noget filnavn. Er det muligt?

Nu var der tale om et C++-program, og der kender jeg ikke reglerne,
men i et C-program må argc gerne være 0, og hvis argc er større end
0, må argv[0] gerne være en tom streng.

Mogens Hansen (20-05-2002)
Kommentar
Fra : Mogens Hansen


Dato : 20-05-02 09:24


"Anders Melchiorsen" <postmaster@anders.day-139-2002.nospam.kalibalik.dk>
wrote

>
> Hm, argv[] er nulafsluttet, såfremt argc > 0.
>

Kravet er at argv[argc] er 0, og at argc ikke er negativ.
Altså argc må gerne være 0, og også i det tilfælde vil argv[argc] være 0.

Venlig hilsen

Mogens Hansen





Anders Borum (20-05-2002)
Kommentar
Fra : Anders Borum


Dato : 20-05-02 10:19

"Anders Melchiorsen" <postmaster@anders.day-139-2002.nospam.kalibalik.dk>
skrev i en meddelelse news:m2offb7tkk.fsf@dolle.kalibalik.dk...
> "Anders Borum" <overflade@fedt.dk> skrev:
>
> > Hvis programmet kaldes uden argumenter er argv[1] ikke veldefineret.
>
> Hm, argv[] er nulafsluttet, såfremt argc > 0.
>
> Strengt taget har du ret, men præmissen er "argc==0", ikke "programmet
> kaldes uden argumenter".

Nu hvor jeg kigger efter er der i "K&R's CPL 2. udg." eksempler hvor det
antages at argc != 0; fx. side 163. Så måske præmissen slet ikke er
nødvendig.

> > Du kunne erklære file som en array:
> > char file[80];
>
> Et bedre valg er nok
>
> std::string file;

Ja - det er det nok.

De iostreams der følger med min egen Visual C++ version 6 kan ikke
indlæse direkte til en std::string og cin har altså ikke mulighed for
at øge kapaciteten for file-objektet hvis det skulle blive nødvendigt.

Jeg tror jeg skifter til gcc.

Anders



Byrial Jensen (20-05-2002)
Kommentar
Fra : Byrial Jensen


Dato : 20-05-02 11:21

Anders Borum <overflade@fedt.dk> skrev:
> Nu hvor jeg kigger efter er der i "K&R's CPL 2. udg." eksempler hvor det
> antages at argc != 0; fx. side 163.

Ja, K&R2 siger at argc er mindst 1 (øverst s. 115), og laver
eksempler der bygger på den antagelse. Den holder bare ikke for C99
(se afsnit 5.1.2.2.1), og ifølge Mogens Hansen heller ikke for C++.

Jeg kan ikke huske hvad ANSI C siger om det.

> Så måske præmissen slet ikke er
> nødvendig.

Jo.

Anders Borum (20-05-2002)
Kommentar
Fra : Anders Borum


Dato : 20-05-02 12:23

"Byrial Jensen" <bjensen@nospam.dk> skrev i en meddelelse
news:slrnaehjhj.28f.bjensen@ask.ask...
> Anders Borum <overflade@fedt.dk> skrev:
> > Nu hvor jeg kigger efter er der i "K&R's CPL 2. udg." eksempler hvor det
> > antages at argc != 0; fx. side 163.
>
> Ja, K&R2 siger at argc er mindst 1 (øverst s. 115), og laver
> eksempler der bygger på den antagelse. Den holder bare ikke for C99
> (se afsnit 5.1.2.2.1), og ifølge Mogens Hansen heller ikke for C++.
>
> Jeg kan ikke huske hvad ANSI C siger om det.

Her er hvad en ISO draft fra 3. august 1998 siger.
Den færdige ANSI standard koster penge, så den kan jeg ikke citere.

5.1.2.2.1 Program startup

[#1] The function called at program startup is named main.
The implementation declares no prototype for this function.
It shall be defined with a return type of int and with no
parameters:

int main(void) { /* ... */ }

or with two parameters (referred to here as argc and argv,
though any names may be used, as they are local to the
function in which they are declared):

int main(int argc, char *argv[]) { /* ... */ }

or equivalent;8) or in some other implementation-defined
manner.

[#2] If they are declared, the parameters to the main
function shall obey the following constraints:

-- The value of argc shall be nonnegative.

-- argv[argc] shall be a null pointer.

-- If the value of argc is greater than zero, the array
members argv[0] through argv[argc-1] inclusive shall
contain pointers to strings, which are given
implementation-defined values by the host environment
prior to program startup. The intent is to supply to

____________________

8) Thus, int can be replaced by a typedef name defined as
int, or the type of argv can be written as char ** argv,
and so on.

5.1.2 Environment 5.1.2.2.1




12 Committee Draft -- August 3, 1998 WG14/N843


the program information determined prior to program
startup from elsewhere in the hosted environment. If
the host environment is not capable of supplying
strings with letters in both uppercase and lowercase,
the implementation shall ensure that the strings are
received in lowercase.

-- If the value of argc is greater than zero, the string
pointed to by argv[0] represents the program name;
argv[0][0] shall be the null character if the program
name is not available from the host environment. If
the value of argc is greater than one, the strings
pointed to by argv[1] through argv[argc-1] represent
the program parameters.

-- The parameters argc and argv and the strings pointed to
by the argv array shall be modifiable by the program,
and retain their last-stored values between program
startup and program termination.

> > Så måske præmissen slet ikke er
> > nødvendig.
>
> Jo.



Byrial Jensen (20-05-2002)
Kommentar
Fra : Byrial Jensen


Dato : 20-05-02 14:47

Anders Borum <overflade@fedt.dk> skrev:
> "Byrial Jensen" <bjensen@nospam.dk> skrev i en meddelelse
> news:slrnaehjhj.28f.bjensen@ask.ask...
>> Anders Borum <overflade@fedt.dk> skrev:
>> > Nu hvor jeg kigger efter er der i "K&R's CPL 2. udg." eksempler hvor det
>> > antages at argc != 0; fx. side 163.
>>
>> Ja, K&R2 siger at argc er mindst 1 (øverst s. 115), og laver
>> eksempler der bygger på den antagelse. Den holder bare ikke for C99
>> (se afsnit 5.1.2.2.1), og ifølge Mogens Hansen heller ikke for C++.
>>
>> Jeg kan ikke huske hvad ANSI C siger om det.
>
> Her er hvad en ISO draft fra 3. august 1998 siger.

Det du citerer fra, må være et udkast til C99-standarden (ISO/IEC
9899:1999).

Med ANSI C menes den standard som først blev vedtaget af ANSI i
1989, og siden af ISO og IEC året efter som ISO/IEC 9899:1990, og
som nu teknisk set er forældet idet den er afløst af C99.

Jeg er som sagt ikke sikker på hvad ANSI C siger om argc, men jeg
formoder at værdien 0 også tillades her.

Richard Flamsholt (22-05-2002)
Kommentar
Fra : Richard Flamsholt


Dato : 22-05-02 00:53

Byrial Jensen <bjensen@nospam.dk> skrev:
>Jeg er som sagt ikke sikker på hvad ANSI C siger om argc, men jeg
>formoder at værdien 0 også tillades her.

Det gør C89, ja: 5.1.2.2.1. Der står bl.a., at hvis argc>0 repræsenterer
argv[0] programnavnet og at argv[0][0] er nul såfremt navnet ikke findes
der, hvor main() kaldes fra. Det kan fx være via en exec*() som ikke kan
eller vil aflevere programnavnet i argv[0].

Iøvrigt læste jeg det her i Schildt's annoterede udgave af C-standarden
(skønt jeg faktisk har den rigtige på papir, men den var længere væk) og
på højresiden brillerer han med at konkludere, at eftersom main ikke har
en prototype kan man definere den som man har lyst til (ja, det skriver
han faktisk!), fx som "void main(void)".

Endnu et glimrende argument for at hive alle højresiderne ud af den bog,
og såmænd nok også alle hans andre bøger...

--
Richard Flamsholt
richard@flamsholt.dk - www.richard.flamsholt.dk

Claus Rasmussen (19-05-2002)
Kommentar
Fra : Claus Rasmussen


Dato : 19-05-02 21:39

Mads A. Jensen wrote:

> Jeg er ny til c++. Når jeg afvikler følgende kode, kommer der en fejl, men
> hvad skyldtes fejlen:

[...]

> filep.getline(line, sizeof(line));

'line' skal være allokeret på forhånd. Og når du bruger sizeof() på
en pointer, får du kun størrelsen på pointeren - ikke størrelsen af
det, den peger på.

Du kan prøve med flg. lille test:

int main() {
char* line1;
char line2[80+1];
cout << sizeof(line1) << endl
<< sizeof(line2) << endl;
}

MVH
-Claus


Ivan Johansen (19-05-2002)
Kommentar
Fra : Ivan Johansen


Dato : 19-05-02 21:50

Mads A. Jensen wrote:

> Jeg er ny til c++. Når jeg afvikler følgende kode, kommer der en
fejl, men
> hvad skyldtes fejlen:


Hvis du skrev hvad fejlen bestod i og helst hvor fejlen opstår ville det
hjælpe en hel del. Kan programmet ikke compiles eller springer
computeren i luften, når programmet køres?

> #include <stdio.h>
> #include <math.h>

> #include <string.h>

Disse bør ændres til <cstdio>, <cmath> og <cstring>. <stdio.h>, <math.h>
og <string.h> er kun understøttet af hensyn til bagudkompatibilitet og
bør derfor ikke bruges i ny kode.

> #include <iostream.h>
> #include <fstream.h>

Disse findes ikke i standarden. De hedder <iostream> og <fstream>. Du
skal desuden skrives
using namespace std;
hvis du ikke vil skrive std:: foran alt i namespace std.


> int main(int argc, char *argv[])
> {
> char *line;
> char *file;
> int *i;

Da jeg kan se at du bruger i til at tælle linier med skal den ikke være
en pointer brug følgende i steret:
int i;

> if(argv[1] == NULL){
> cout << "Location of file: ";
> cin >> file;

Her overskriver du et tilfældigt sted i hukommelsen. Jeg vil anbefale at
du erklærer file som:
string file;

og åbner filen med:
ifstream filep(file.c_str());

> }
> else{
> file = argv[1];
> }
> ifstream filep(file);

Du undersøger ikke om det lykkedes at åbne filen:
if(!filep)
{
cerr << "Could not open file"
return 1;
}

> while(!filep.eof()){
> filep.getline(line, sizeof(line));


Her læser du en linie ind hvor line peger. Da du ikke har allokeret
hukommelse til line, vil du overskrive data et tilfældigt sted i
hukommelsen. Du læser højest 4 bytes, da dette er størrelsen på en
pointer under Windows 2000.

Du kan løse problemet ved at deklarere line som:
char line[100];

Dette afsætter 100 bytes til din linie inklusiv terminering. Da line nu
er et array i stedet for en pointer, vil sizeof(line) korrekt returnere
størrelsen på dit array i stedet for størrelsen på en pointer.

En endnu bedre løsning ville være at bruge en std::string.
string line;

while(!filep.eof()){
getline(filep, line);

Her behøver du ikke tænker på hvor stor en linie kan være. line får
automatisk den størrelse, som er nødvendig. Husk dog
#include <string>


> i = (i + 1);

Dette skrives normalt i c++ som
++i;

Jeg håber at du kan bruge mine kommentarer.

Ivan Johansen



Igor V. Rafienko (21-05-2002)
Kommentar
Fra : Igor V. Rafienko


Dato : 21-05-02 13:09

[ Ivan Johansen ]

> > while(!filep.eof()){
> > filep.getline(line, sizeof(line));

[ snip ]

> En endnu bedre løsning ville være at bruge en std::string.
> string line;
>
> while(!filep.eof()){
> getline(filep, line);
>
> Her behøver du ikke tænker på hvor stor en linie kan være. line får
> automatisk den størrelse, som er nødvendig. Husk dog
> #include <string>


Nesten. Bortsett fra den situasjonen når:

* man leser den siste linjen MEN eofbit ikke blir satt (det er en
mulig hendelsesforløp). Antall linjer økes med 1.
* Man tester på eofbif, som ikke er satt enda og går inn i løkken. Der
gjør man en getline som forsøker å lese forbi EOF, noe som
naturligvis går galt. Når blir (bl.a.) eofbit satt
* Og man øker antall linjer med 1 for en ikke-eksisterende linje.

Svaret blir 1 linje for mye.

En av riktige varianter er:

while ( getline( filep, line ) )
++count;

der man tester på streamstate _før_ man kommer inn i løkken. En ganske
så vesentlig forskjell.





ivr, som har sans for Mogens sitt forslag
--
C++: "an octopus made by nailing extra legs onto a dog"
            -- Steve Taylor, 1998

Ivan Johansen (21-05-2002)
Kommentar
Fra : Ivan Johansen


Dato : 21-05-02 21:21

Igor V. Rafienko wrote:

> Nesten. Bortsett fra den situasjonen når:
>
> * man leser den siste linjen MEN eofbit ikke blir satt (det er en
> mulig hendelsesforløp). Antall linjer økes med 1.
> * Man tester på eofbif, som ikke er satt enda og går inn i løkken. Der
> gjør man en getline som forsøker å lese forbi EOF, noe som
> naturligvis går galt. Når blir (bl.a.) eofbit satt
> * Og man øker antall linjer med 1 for en ikke-eksisterende linje.
>
> Svaret blir 1 linje for mye.


Selvfølgelig. Det havde jeg lige overset.

> En av riktige varianter er:
>
> while ( getline( filep, line ) )
> ++count;


Det ser flot ud. Det vil jeg lige huske på.

Ivan Johansen




Jesper Toft (19-05-2002)
Kommentar
Fra : Jesper Toft


Dato : 19-05-02 21:52

Mads A. Jensen wrote:

Du benytter pointere men allokere ikke hukommelse til dem ikke..


> char *line;
Denne bør være:
char line[1000];

> char *file;

> int *i;
Denne bør være:
int i = 0;

> if(argv[1] == NULL){
> cout << "Location of file: ";
indsæt noget i retningen af:
file = new char[1000];
> cin >> file;
> }

/Jesper


Mogens Hansen (20-05-2002)
Kommentar
Fra : Mogens Hansen


Dato : 20-05-02 09:28


"Mads A. Jensen" <mads@NOSPAManything.dk> wrote

fra de andre svar, ved du at et væsentligt problemer er at du ikke har
allokeret plads

> Jeg er ny til c++. Når jeg afvikler følgende kode, kommer der en fejl, men
> hvad skyldtes fejlen:
>
> #include <stdio.h>
> #include <math.h>
> #include <string.h>

Hvorfor includerer du stdio, math og string ?
Så vidt jeg kan se, bruger du dem ikke.

[snip]
> int main(int argc, char *argv[])
> {
> char *line;
> char *file;

Generelt er det en god ide, i C++, at vente med at erklære variable til man
har brug for dem.

[snip]
> ifstream filep(file);
>

Hvad hvis filen ikke kan åbnes ?

> while(!filep.eof()){

Det bør nok nærmere være
while(filep) {


Du kan gøre programmet mere tydeligt, og sikkert ved at sige:
"jeg skal lave et program, der kan tælle antallet af linier i en fil",
og bruge standard algoritmen std::count

#include <fstream>
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
#include <cstdlib>

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

string file_name;
if(2 != argc) {
cout << "Location of file:" << endl;
getline(cin, file_name);
}
else {
file_name = argv[1];
}

ifstream is(file_name.c_str(), ios_base::binary);

if(!is) {
cerr << "Unable to upen file: " << file_name << endl;
return EXIT_FAILURE;
}

cout << "Number of lines in file were: "
<< count(
istreambuf_iterator<char>(is),
istreambuf_iterator<char>(),
'\n')
<< endl;
}

Metoden kan bruges uanset om det er antallet af linieskift eller antallet af
et andet tegn der skal skrives.

Venlig hilsen

Mogens Hansen



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

Månedens bedste
Årets bedste
Sidste års bedste