md.jamal
md.jamal

Reputation: 4567

control characters in C Buffer

I need to transmit the following content over socket.

^ASO00^D

I tried to store them in buffer:

unsigned char fileData[] = {'^A','S','O','0','0','^D'},

when I print the fileData, it doesn't print the ASCII Characters.

 printf("%s\n", fileData);

It only prints "S000".

How can I save the control characters in buffer

But when I store this in a file and read it from the file, the control characters gets printed

Upvotes: 0

Views: 2233

Answers (2)

Attie
Attie

Reputation: 6979

I'm surprised this compiles... It certainly throws warnings on my system, and I see "ASO00D" printed.

#include <stdio.h>

void main(void) {
        unsigned char fileData[] = {'^A','S','O','0','0','^D'};

        printf("%s\n", fileData);
}
$ gcc x.c -o x -Wall
x.c:3:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
 void main(void) {
      ^
x.c: In function ‘main’:
x.c:4:30: warning: multi-character character constant [-Wmultichar]
  unsigned char fileData[] = {'^A','S','O','0','0','^D'};
                              ^
x.c:4:30: warning: large integer implicitly truncated to unsigned type [-Woverflow]
x.c:4:51: warning: multi-character character constant [-Wmultichar]
  unsigned char fileData[] = {'^A','S','O','0','0','^D'};
                                                   ^
x.c:4:51: warning: large integer implicitly truncated to unsigned type [-Woverflow]
$ ./x
ASO00D

Don't forget to use -Wall and read the warnings - they are helpful!

^A is not a printable character, thus printf() (or more correctly your terminal) will not render it correctly, even if this had worked as you expected.

Also, as pointed out by Michael Walz in the comments, you should always terminate a string with a nul character - \0. In the above example you risk running past the end of the array, and thus undefined behaviour.


What you are actually trying to use is the common human-readable notation for control characters.

Ctrl + A is typically printed as ^A.

This doesn't mean you can put ^A into a C character and expect it to work - for a start it's two characters... ^ and A.

Instead, you should refer to the ASCII table, and understand that pressing Ctrl or Shift actually modify the key pressed. [I'm not referring to the keyboard scancodes].

 a  0x61  0b01100001
 A  0x41  0b01000001
^A  0x01  0b00000001
  • Pressing A produces an a (0x61)
  • Pressing Shift + A produces an A (0x61 & ~0x20 = 0x41)
  • Pressing Ctrl + A produces a ^A (0x61 & ~0x60 = 0x01)

Try instead using this:

unsigned char fileData[] = {0x01,'S','O','0','0',0x04,'\0'};

However, even this will not printf() "correctly".

Try instead using a loop, like this: (note the isprint() and iscntrl() tests)

#include <stdio.h>
#include <ctype.h>

void main(void) {
        int i;
        unsigned char fileData[] = {0x01,'S','O','0','0',0x04,'\0'};

        printf("%s\n", fileData);

        for (i = 0; i < sizeof(fileData) - 1; i++) {
                printf("%3d: 0x%02X   ", i, fileData[i]);
                if (isprint(fileData[i])) {
                        printf("%c", fileData[i]);
                } else if (iscntrl(fileData[i])) {
                        printf("^%c", fileData[i] + 'A' - 1);
                } else {
                        printf(".");
                }
                printf("\n");
        }
}
$ gcc x.c -o x -Wall
x.c:4:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
 void main(void) {
      ^
$ ./x
SO00
  0: 0x01   ^A
  1: 0x53   S
  2: 0x4F   O
  3: 0x30   0
  4: 0x30   0
  5: 0x04   ^D

Upvotes: 3

Avi Avraham
Avi Avraham

Reputation: 1099

You are trying to store byte values in an array:

unsigned char fileData[] = {0x01,'S','O','0','0',0x04},

Upvotes: 0

Related Questions