[c] vreemd verschil tussen %c en %s

Pagina: 1
Acties:
  • 155 views sinds 30-01-2008
  • Reageer

  • cenix
  • Registratie: September 2001
  • Laatst online: 25-05 17:24
In mijn programma wil ik een reeks karakters (in een array) weergeven.
Nu heb ik hiervoor 2 manieren om te testen.

C:
1
        printf("%16s", buffer);


waarvan de uitvoer is.

code:
1
2
0x000000 : ca fe ba be 00 00 00 2e 00 10 07 00 0c 07 00 0d             ╩■║╛
0x000010 : 07 00 0e 01 00 05 70 6f 77 65 72 01 00


Opzicht niets verkeerd mee dacht ik zo.

Nu probeer ik het volgende (omdat op bovenstaande manier soms de tekens willekeurig op het scherm verschijnen (dus random x en y posities))

C:
1
2
        for (i = 0; i < strlen(buffer); i++)
                printf("%c ", buffer[i]);

(btw, de buffergrootte is 16)

en de uitvoer is
code:
1
2
0x000000 : ca fe ba be 00 00 00 2e 00 10 07 00 0c 07 00 0d &#9577; &#9632; &#9553; &#9563;
0x000010 : 07 00 0e 01 00 05 70 6f 77 65 72 01 00


als je goed vergelijkt zie je dat de ascii tekens (de meest rechtse) niet op dezelfde posities staan. Voor zover ik het kan controleren klopt de onderste manier beter dan de bovenste omdat hex ca = decimaal 202 = ascii (t-splitsing zeg maar, zie & #9577;).

Waardoor wordt dit verschil veroorzaakt? Ik kan hier nergens iets over vinden (omdat ik niet exact weet hoe dit genoemd wordt).

sorry als het een beetje vaag lijkt, ik weet niet hoe ik het duidelijker kan uitleggen.

Ohja.. compiler is gcc 3.3.3 (onder linux/debian) en mingw (bij Dev-C++ 4.9.8.7) onder Win XP

[ Voor 12% gewijzigd door cenix op 08-05-2004 12:59 ]


  • Sendy
  • Registratie: September 2001
  • Niet online
En waarmee druk je die &# dingen af dan? Die komen niet uit wat je hier beschrijft?

  • cenix
  • Registratie: September 2001
  • Laatst online: 25-05 17:24
die karakters zijn ╩ ■ ║ ╛
sorry.. in een code block werken deze niet

ff kleine uitleg over programma.

Ik lees een binair (bv. exe filetje) bestand in en wil hiervan de offset (1e kolom) de hexwaarden (16 stuks op 1 rij) (2e kolom) en het ascii teken (3e kolom) laten zien.

Verwijderd

Het voorbeeld is niet echt duidelijk door die &#xxxx dingen (zijn dit de html codes voor die karakters of zo?). Een duidelijker voorbeeld zou zijn met gewone ascii codes.

Voor de rest moet je oppassen met het uitgeven van sommige karakers (of karakter reeksen) op de console (bijv. die met codes < 0x20). Dit kunnen control codes van de console zijn die bijv. een newline, linefeed,... weergeven (en dus verplaatsingen op het scherm zijn).

  • cenix
  • Registratie: September 2001
  • Laatst online: 25-05 17:24
Voor alle duidelijkheid zal ik hier mijn volledige code plaatsen

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/* Courtesy of Advanced Linux Programming */

// aanpassen zodat ook eventuele vertaalde hexcodes (in ascii)
// op het scherm komen (hebben we een soort hexeditor/viewer)

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    unsigned char buffer[16];
    size_t offset = 0;
    size_t bytes_read;
    int i;

    // Open file for reading
    int fd = open(argv[1], O_RDONLY);

    // Read one chunk from file
    do {
        // read the next lines of bytes
        bytes_read = read(fd, buffer, sizeof(buffer));
        // print offset in file, followed by the bytes itself
        printf("0x%06x : ", offset); // offset
        for (i = 0; i < bytes_read; ++i)
                printf("%02x ", buffer[i]); // hex numbers

        // print ascii tokens
//        printf("%16s", buffer); // ascii
        for (i = 0; i < strlen(buffer); i++)
                printf("%c ", buffer[i]);

        printf("\n");
        // Keep count of position in file
        offset += bytes_read;
    } while (bytes_read == sizeof(buffer));

    close(fd);

    system("PAUSE"); // voor pauze op win32

    return 0;
}


@H3AsO4: Control Codes, natuurlijk... dat ik daar niet bij stilgestaan had 8)7
maargoed, als ik deze wil weergeven in een console, hoe moet ik dit dan aanpassen?
Uiteindelijk wil ik er een win32 applicatie van bakken (om m'n skills wat uit te breiden -> want hexviewers/editors zijn er genoeg :) )

[ Voor 6% gewijzigd door cenix op 08-05-2004 14:13 ]


  • ajhaverkamp
  • Registratie: November 2001
  • Laatst online: 22-05 23:32

ajhaverkamp

gewoon Arjan

Checken of het karakter binnen een reeks zit die je kunt tonen op je scherm, en anders een ander karakter tonen (bv 2x *).

This footer is intentionally left blank


Verwijderd

Je kunt eenvoudig controleren of een karakter afdrukbaar is met isprint() en kijken of het een controle karakter is met iscntrl(); die functies zijn gedeclareerd in ctype.h

Verder loop je in die for lus op regel 33 maar tot strlen(buffer) in plaats van tot bytes_read, wat betekent dat niet altijd de complete buffer wordt afgedrukt.

(Ik neem aan dat dit genoeg hints zijn, met een kleine aanpassing in regels 33 en 34 en een extra #include bovenaan werkt het.)

[ Voor 8% gewijzigd door Verwijderd op 08-05-2004 14:45 ]


  • cenix
  • Registratie: September 2001
  • Laatst online: 25-05 17:24
dank _/-\o_

maar nu weet ik eigenlijk nog steeds niet waar het verschil tussen %s en %c zit m.b.t. het weergeven

bij %s wordt het als volgt weergegeven (spaties zijn nu punten)
.....╩■║╛

bij %c wordt het als volgt weergegeven (spaties zijn punten)
╩■║╛.....

  • Sjaaky
  • Registratie: Oktober 2000
  • Laatst online: 01:17
Bij de "%c " print je per char een spatie extra?

Verwijderd

cenix schreef op 08 mei 2004 @ 16:10:
maar nu weet ik eigenlijk nog steeds niet waar het verschil tussen %s en %c zit m.b.t. het weergeven
Een string wordt in C afgesloten door een null-karakter ('\0', ASCII waarde 0). Je leest binaire input, wat betekent dat de 16 karakters die je in buffer leest al dan niet een 0 bevatten. Bevat buffer een 0 dan zal "%16s" karakters totaan die 0 laten zien, links uitgevuld tot 16 karakters met spaties; bevat buffer geen 0 dan wordt er met een string gewerkt die groter is dan 16 karakters (en dus buffer overfowt), je ziet dan maar 16 karakters omdat je "%16s" gebruikt.

Met "%c" druk je de boel karakter voor karakter af, maar ook hier heb je de zelfde problemen door strlen(buffer) die ook naar een 0 in buffer zoekt (die er mischien niet is, of mischien te vroeg).

Al je rare output heeft er dus mee te maken dat je enerzijds binaire input die ASCII-waarde 0 kan bevatten gewoon als string gebruikt, en anderzijds dat je je string niet afsluit met een ASCII-waarde 0.

Ik zou het zo oplossen:
C:
33
34
        for (i = 0; i < bytes_read; i++)
                putchar(isprint(buffer[i]) ? buffer[i] : '?');

(en bovenaan nog #include <ctype.h>)

[ Voor 9% gewijzigd door Verwijderd op 08-05-2004 18:22 . Reden: verduidelijkt ]


  • PommeFritz
  • Registratie: Augustus 2001
  • Laatst online: 24-11-2025

PommeFritz

...geen friet

<lullige_opmerking>
od -t x1 -c binaryfile
</lullige_opmerking>

Helaas komen de ascii tekens op de regels eronder te staan...

[ Voor 40% gewijzigd door PommeFritz op 09-05-2004 10:08 ]

FireFox - neem het web in eigen hand


  • cenix
  • Registratie: September 2001
  • Laatst online: 25-05 17:24
Oke, nu is het me helemaal duidelijk..

Verwijderd

PommeFritz schreef op 09 mei 2004 @ 10:05:
<lullige_opmerking>
od -t x1 -c binaryfile
</lullige_opmerking>

Helaas komen de ascii tekens op de regels eronder te staan...
offtopic:
info lezen is een kunst :)
od -A x -t x1z -v <FILE>

  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

Wat losse opmerkingen : Binaire data moet je met 'gewone' lengtes werken, en niet met strlen(). Zoals opgemerkt kun je control characters niet zondermeer printe. Je kan op *NIX je scherm ik raw mode zetten, zodat
de karakters gewoon geprint worden.

Ik zou zelf alles < 0x20 gewoon vervangen door de hexwaarde, want de meeste control characters hebben geen printbare waarde.
Pagina: 1