[C/C++] terminating null-character toch geprint?

Pagina: 1
Acties:

  • Patriot
  • Registratie: December 2004
  • Laatst online: 13:00

Patriot

Fulltime #whatpulsert

Topicstarter
Hallo,

Ik ben bezig met een beetje C++ voor mezelf. Gewoon voor de lol, om de taal een beetje te leren kennen. Heb er dan ook nog geen ervaring in, en het is eigenlijk het eerste wat ik ooit gemaakt heb in C++.

Nu heb ik een class gemaakt om wat karakters op het scherm te gooien. Dat klinkt simpel genoeg, en dat is het eigenlijk ook, maar ik wilde de karakters op specifieke plekken in de console gooien (dus op een bepaald coördinaat). Dat zag er ongeveer zo uit:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Test {
  HANDLE hOutput;
  COORD cursorPos;
public:
  Test();
  void WriteCharacters();
};

Test::Test() {
  hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
}

void Test::WriteCharacters() {

  char verylongline[50];
  DWORD BytesWritten;

  for (int i = 0; i < 50; i++)
    verylongline[i] = char(219);

  WriteFile(hOutput, verylongline, 50, &BytesWritten, NULL);

}

int main() {

  Test t;

  t.WriteCharacters();

  return 0;
}


Dat deed zijn werk prima. Omdat ik in het uiteindelijke script wat vaker WriteFile aanriep (een stuk of 8 keer waartussen ik steeds de positie van de cursor verander), leek het me handig om een soort wrapper te maken. De class definitie werd toen zo:

C++:
1
2
3
4
5
6
7
8
class Test {
  HANDLE hOutput;
  COORD cursorPos;
  int Write(const char data[]);
public:
  Test();
  void WriteCharacters();
};


En de nieuwe functie zag er zo uit:

C++:
1
2
3
4
5
6
7
8
int Test::Write(const char data[]) {

  DWORD BytesWritten;

  WriteFile(hOutput, data, strlen(data), &BytesWritten, NULL);

  return (int)BytesWritten;
}


Nu gaat dat niet helemaal zoals ik verwacht had. De boel draait nog, alleen print hij er een aantal extra karakters bij. Volgens mij zijn die karakters die te zien zijn een poging van de console om de null characters die nog in de array van characters staan te weergeven.

Mijn probleem is nu als volgt: Ten eerste snap ik niet hoe het kan dat die array groter is. Ik dacht dat het misschien kwam omdat ik de groote niet aangaf bij de functie, maar zelfs als ik dat expliciet wel doe dan blijven de karakters. Echter, zelfs als die karakters er zijn (en dus null characters in de array) zou hij deze volgens mij niet moeten laten zien, het derde argument van WriteFile geeft aan hoeveel bytes hij weg moet schrijven en ik geloof dat strlen stopt bij het eerste null character, dat zou toch betekenen dat hij de laatste null characters niet gaat proberen te printen?

EDIT:

Ik geloof dat ik het heb. Het komt blijkbaar door het uitblijven van een null character. Als die er niet is dan gaat strlen blijkbaar raar doen. Zit wel wat in.

[ Voor 3% gewijzigd door Patriot op 20-11-2008 20:15 ]


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
De kans dat er in al je RAM geen enkele \0 staat is vrij klein. strlen doet niet raar, strlen zoekt gewoon totdat die \0 gevonden is. Wat er tussen jouw laatste karakter en die \0 staat wordt dus ook geprint.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

strlen loopt natuurlijk niet heel je RAM af (als je buiten je proces pages gaat lezen, krijg je een access violation).

daarnaast:
char * en char [] zijn niet echt de simpelste manieren om C(++) te leren, aangezien je zelf al zegt dat je geen ervaring hebt, kan je misschien beter eerst es gaan werken met std::string. Die verbergen al de interne pointers en arrays en memory management :)

als je toch met char * strings wilt gaan werken, bedenk je dan dat een string ALTIJD null-terminated moet zijn (dus, na de laatste letter moet een ASCII null karakter). Ook moet je er als programmeur altijd voor zorgen dat er voldoende ruimte is om de hele string EN het null karakter te herbergen. Succes!

-niks-


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 13:03
MLM schreef op vrijdag 21 november 2008 @ 00:21:
char * en char [] zijn niet echt de simpelste manieren om C(++) te leren, aangezien je zelf al zegt dat je geen ervaring hebt, kan je misschien beter eerst es gaan werken met std::string.
Niet het makkelijkst, wel verplichte (basis)kost.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • Patriot
  • Registratie: December 2004
  • Laatst online: 13:00

Patriot

Fulltime #whatpulsert

Topicstarter
MLM schreef op vrijdag 21 november 2008 @ 00:21:
strlen loopt natuurlijk niet heel je RAM af (als je buiten je proces pages gaat lezen, krijg je een access violation).

daarnaast:
char * en char [] zijn niet echt de simpelste manieren om C(++) te leren, aangezien je zelf al zegt dat je geen ervaring hebt, kan je misschien beter eerst es gaan werken met std::string. Die verbergen al de interne pointers en arrays en memory management :)

als je toch met char * strings wilt gaan werken, bedenk je dan dat een string ALTIJD null-terminated moet zijn (dus, na de laatste letter moet een ASCII null karakter). Ook moet je er als programmeur altijd voor zorgen dat er voldoende ruimte is om de hele string EN het null karakter te herbergen. Succes!
Het probleem is dat dat wat ik wilde doen met std::string niet echt te bereiken was. Bovendien is het (zoals de persoon na jou) wel iets wat ik uiteindelijk wil leren. Dan heeft uitstellen niet zoveel zin.

Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 13:03
Patriot schreef op vrijdag 21 november 2008 @ 09:59:
Het probleem is dat dat wat ik wilde doen met std::string niet echt te bereiken was.
Met std::string kun je koffiezetten als je dat zou willen :) Wat wilde je bereiken wat niet met std::string kon dan?

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • Patriot
  • Registratie: December 2004
  • Laatst online: 13:00

Patriot

Fulltime #whatpulsert

Topicstarter
farlane schreef op vrijdag 21 november 2008 @ 10:06:
[...]


Met std::string kun je koffiezetten als je dat zou willen :) Wat wilde je bereiken wat niet met std::string kon dan?
Ok, het is vast niet onmogelijk, punt was dat een bepaalde functie die ik aan wilde roepen niet met std::string overweg kon. Daar is vast wel iets op te vinden, maar het 'goede' type gebruiken leek me handiger.

Acties:
  • 0 Henk 'm!

  • Glorificationer426
  • Registratie: November 2001
  • Laatst online: 13:40

Glorificationer426

come we hero rush yes?

Je kunt daarvoor ook c_str() gebruiken :)

(@DiscWout) omg
(@DiscWout) bijna over mn nek :D
(@DiscWout) echt zo een boer laten, hele mond vol kots :D


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 13:03
Patriot schreef op vrijdag 21 november 2008 @ 13:57:
Ok, het is vast niet onmogelijk, punt was dat een bepaalde functie die ik aan wilde roepen niet met std::string overweg kon. Daar is vast wel iets op te vinden, maar het 'goede' type gebruiken leek me handiger.
Ik snap de gedachtengang, en als je dat leuk vindt/er iets van wilt leren moet je dat zeker doen ( Ik gaf al aan dat werken met C-strings imho verplichte kost is voor een C/C++ programmeur ).

Echter, een string class als std::string neemt wel wat van de "moeilijke" dingen van C-strings voor je over waardoor, als je veel moet concatten etc, je dit waarschijnlijk sneller bugvrij(arm) hebt dan zelf met buffers stoeien.

Voor de uiteindelijke interfacing met je API functies die graag een kale pointer hebben is er, zoals gezegd de c_str() member functie.

[ Voor 5% gewijzigd door farlane op 21-11-2008 16:27 ]

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • Patriot
  • Registratie: December 2004
  • Laatst online: 13:00

Patriot

Fulltime #whatpulsert

Topicstarter
In ieder geval bedankt voor de hulp. Ik ben blij met zulke opmerkingen, ik kan er namelijk niet naar vragen maar gaandeweg is zulke hulp gewoon het handigst. Het is in mijn ogen de meest waardevolle hulp die je kunt krijgen. In ieder geval bedankt allemaal, mijn probleem is opgelost en ik heb er weer wat bruikbare dingen bijgeleerd.

Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

farlane schreef op vrijdag 21 november 2008 @ 08:39:
[...]
Niet het makkelijkst, wel verplichte (basis)kost.
Eens, maar er is een verschil tussen basis C++ (met, imo, std::string) en basis C (met char *). Pas als je serieus C libraries gaat gebruiken (Windows API etc), word het pas belangrijk om te weten wat er "echt" gebeurd.

Als sidenote, je kan een std::string maken van een char *:
C++:
1
2
char *ptr = "c style string";
std::string str(ptr);

en indien nodig kan je er ook weer een char * van maken:
C++:
1
char *ptr = str.c_str();

-niks-


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 13:03
MLM schreef op zaterdag 22 november 2008 @ 14:10:
en indien nodig kan je er ook weer een char * van maken:
C++:
1
char *ptr = str.c_str();
c_str() geeft een const char*. Als je de buffer probeert te bewerken krijg je hoogst waarschijnlijk een av om je oren of gaat de software met je vriendin aan de haal. :P

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.

Pagina: 1