[resolved]NXC:bug?feature?printing non-printable-ASCII-chars

Discussion specific to NXT-G, NXC, NBC, RobotC, Lejos, and more.
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

[resolved]NXC:bug?feature?printing non-printable-ASCII-chars

Post by HaWe »

if I am printing chars < ASCII 30 (even negative values like -1) then NXC always prints a blank instead of just nothing (IMO it should be nothing).

Code: Select all

char chr=-1;
printf("%c", chr);
Is this a bug or a feature?^^
Last edited by HaWe on 04 Nov 2012, 17:52, edited 1 time in total.
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: NXC: bug? feature? when printing non-printable-ASCII-chars

Post by afanofosc »

Anytime you try to draw a character that does not exist in the firmware's font it draws a space instead. So that is a firmware feature.

John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: NXC: bug? feature? when printing non-printable-ASCII-chars

Post by HaWe »

How I hate "features" of that kind... :evil:
BTW, ASCII chars < 30 in strings are NOT always shown (e.g., control chars like \n, \t)!

Code: Select all

task main() {
  string str="1234\t5678";
  printf("%s",str);

 while(1);
}
spillerrec
Posts: 358
Joined: 01 Oct 2010, 06:37
Location: Denmark
Contact:

Re: NXC: bug? feature? when printing non-printable-ASCII-chars

Post by spillerrec »

IMO, it should display either a '?' or some dedicated character for unsupported character, because it clearly shows that you are doing something wrong. You simply can't satisfy everyone.
If you want specific behavior, I suggest you to use RIC fonts. (I made a RIC font which replicates the default font for the ASCII range at least, you could simply modify that if you want to use that approach. It is in the source of RICcreator, but I can upload it on request.)
My blog: http://spillerrec.dk/category/lego/
RICcreator, an alternative to nxtRICeditV2: http://riccreator.sourceforge.net/
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: NXC: bug? feature? when printing non-printable-ASCII-chars

Post by HaWe »

the issue is different. I currently try to mimic ANSI C i/o functions (like getch() using the MS NumPad) and echoing the chars on the display.
ANSI C doesn't print all chars <ASCII 32 as " ", like NXc does.
e.g.:
ASCII 7 is not printed at all by C

other examples:
ASCII 8 is printed as BACKSPACE
ASCII 10 is printed as LINEFEED
ASCII 13 is printed as CARRIAGERETURN

Code: Select all

char chr=7;
printf("%c", chr);
(-1 admittedly was a bad example)

For signalizing which function key has been pressed (like [ALT] on a PC keyboard) I was looking for (actually 3 different) values which could be returned by a key-scan function, but which would not be printed at all by NXC though, just like 7 by C.
But I meanwhile have a 1st workaround:
http://www.mindstormsforum.de/viewtopic.php?f=25&t=7266
spillerrec
Posts: 358
Joined: 01 Oct 2010, 06:37
Location: Denmark
Contact:

Re: NXC: bug? feature? when printing non-printable-ASCII-chars

Post by spillerrec »

(FYI, I'm pretty sure getch() and kbdhit() are not part of the standard library at all, but are POSIX and/or DOS extensions.)

printf does output all control characters as far as I know, it is just your console that does not show them. (I will check this in a moment, I just have to restart my computer first.) Just so you know, ASCII 7 is '\a' and I have actually heard some consoles beep when reading that character. I don't think there is any standardization at all on how stdout shall be treated, my console doesn't even treat it as ASCII! (Well, it is only '\' which is shown as 'Â¥', but still, it is not fully compatible with ASCII.)
(For fun, I just made an output-only console in NXC, you can find it on my blog: http://spillerrec.dk/2012/11/nxt-console-v0-1/)

Well, you just have to manually go through your data stream and convert it to the encoding TextOut() expect. Or you could use a RIC font which ignores those characters. (Example: In my Word Wrapping library, I used codes 240-255 (I think) to represent spaces with different widths for tabs, I swapped '\t' with one of those characters to make sure the next character would be properly aligned when printing the variable-width RIC-font.)
My blog: http://spillerrec.dk/category/lego/
RICcreator, an alternative to nxtRICeditV2: http://riccreator.sourceforge.net/
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: NXC: bug? feature? when printing non-printable-ASCII-chars

Post by HaWe »

both getch and kbdhit are from conio.h , it's quasi-standard as u might know.
unfortunately, getchar() from stdio.h is already occupied by the efw for buttons.
http://www.google.de/url?sa=t&rct=j&q=& ... TMkXGasbWg
and yes, ASCII 7 is BELL, and not written to screen out, but it's close to what I actually want^^,

but no, it's actually not about getch and kbdhit what I'm talking about but printf (not my redefinition, just the firmware-output like in TextOut),
and no, I don't want to use a ric font, it absolutely makes no sense - neither for me nor for general purposes using the NumPad as a stdin device.

maybe you'll have to try and check my program to see why (as I understand from your post, you didn't actually try this).
just remove
if (chr>=' ')
before printf...
and see what sometimes happens using function keys...
[OT]: in your console code I see nothing like std C functions, e.g., scanf, cin, getc, getch, getchar, cout, putc, putchar,
and even no printf including format strings like %04d %#x %#o %-5.2f %#.2f %+.0e %E %16x %08X %-10s %c
- I daresay that my own io functions getch, kbdhit, and my redefined printf are much closer to C than your "add_text" function
spillerrec
Posts: 358
Joined: 01 Oct 2010, 06:37
Location: Denmark
Contact:

Re: NXC: bug? feature? when printing non-printable-ASCII-chars

Post by spillerrec »

Wikipedia wrote:conio.h is a C header file used in old MS-DOS compilers to create text user interfaces. It is not described in The C Programming Language book, and it is not part of the C standard library, ISO C nor is it defined by POSIX.
Well, as standard as Windows.h... It is not portable (that is for me all that I care) and certainly not ANSI C. You are just usually so pedantic about ANSI C...

Anyway, I just don't see why you are trying to compare printf() in C with TextOut() as they are two very different functions. printf() doesn't display anything on your screen, it just formats data and appends it to a stream. TextOut() visualizes data on the NXT screen using its inbuilt font. I can't see the connection.
(I checked and printf() works like a file in text mode, you can even write '\x00' and it will still output that.)

I can't try your code as I simply don't have a Mindsensor NumPad. But I didn't say RIC fonts was the only way to do it, the console application I posted actually use TextOut() and doesn't print any control codes (other than supported) or non-ASCII characters.
My blog: http://spillerrec.dk/category/lego/
RICcreator, an alternative to nxtRICeditV2: http://riccreator.sourceforge.net/
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: NXC: bug? feature? when printing non-printable-ASCII-chars

Post by HaWe »

again: this thread is about printing non-printable-ASCII-chars <32, this thread is not about getch or kbdhit or conio.h , I didn't ever claim that the library conio.h =ANSI
(I dont' see where this should be written - I only said it's quasi-standard - and I can't understand why you are so pedantic about that), but anyway:
conio.h is a C header file used in old MS-DOS compilers to create text user interfaces.... This header declares several useful library functions for performing "console input and output" from a program. Most C compilers that target DOS, Windows 3.x, Phar Lap, DOSX, OS/2, or Win32[1] have this header and supply the associated library functions in the default C library...Some embedded systems use a conio-compatible library.[2]
that's exactly why I use it to create text user interfaces for the NXT.

but back to topic...
printf() doesn't display anything on your screen
what ???? :lol:

Code: Select all

string str="test";
int i=567; float f=1.2345; char c='A';
printf("%s", str);
Wait(1000);
printf("%4d", i);
Wait(1000);
printf ("%6.3f", f);
Wait(1000);
printf("%c", c);
Wait(1000);
(using the NXC implementation of printf it always writes at (0,56) opposite to mine)

- edit: I'm not sure if I just found a different behavior - must check it!
edit 2: opposite to what I observed and opposite to what John wrote the fw actually don't seem to write blanks for char values <32....

edit3: I got it: it's an artefact emerged by the strlen function which returns length=1 even if a character < ASCII 32 could not be written to the screen

edit4: the print-issue is fixed!

Code: Select all

char LCDline[]={56,48,40,32,24,16,8,0};

int _cur_x_=0, _cur_y_=56;      // cursor home for NXC  = upper left = (0,56)
int _tab_width_=24;             // tab width by default = 24 = 4* 6-point letter

unsigned long _TEXTSTYLE_ = DRAW_OPT_NORMAL;   // text style by default

#define scrclr() {  ClearScreen();  _cur_x_=0; _cur_y_=56; }

#define gotoxy( x, y )    { _cur_x_=x; _cur_y_=y; }   // move cursor to position
#define curxy( x, y )     { _cur_x_=x; _cur_y_=y; }   // move cursor to (alias)
#define curx  ( x )       { _cur_x_=x; }              // move cursor to x-pos
#define cury  ( y )       { _cur_y_=y; }              // move cursor to y-pos
#define getcurx()           _cur_x_                   // get cursor x-pos
#define getcury()           _cur_y_                   // get cursor y-pos
#define curhome           { _cur_x_=0; _cur_y_=56; }  // move cursor home
#define settabwidth( t )  { _tab_width_ = t; }        // redefine tab width
#define settextstyle( t ) { _TEXTSTYLE_ = t; }        // redefine text style


inline string strsplit(string &src, string mark) {
  string _sret="";
  int p=-1, l;
  p=Pos(mark, src);
  if (p>=0) {
    l=strlen(mark);
    _sret= SubStr(src, 0, p);
    src=SubStr(src, p+l, strlen(src)-p);
  }
  return _sret;
}


string strexch(string src, string ex, string ch) {
  string _sst;
  _sst=strsplit(src,ex);
  return (StrCat(_sst,ch,src));
}


// printfxy()
// featuring "\i" for writing inverted
//******************************************************************************
#define printfxy(_x_, _y_, fmt_, v_) {  \
  _cur_y_=_y_;   string  _s2, _sv;      \
  char _BLK_=32;                        \
  _s2=fmt_;                             \
  if (Pos("\i",_s2)>=0) {               \
    _TEXTSTYLE_= DRAW_OPT_INVERT;       \
    _s2=strexch(_s2,"\i","");           \
  }                                     \
  int len_=0;                           \
  if (Pos("%",_s2)==-1)  { _sv=_s2; }   \
  else { _sv = FormatVal(_s2, v_);  }   \
  TextOut(_x_, _y_, _sv, _TEXTSTYLE_);  \
  if(_sv[0]>=_BLK_) len_=strlen(_sv);   \
  _cur_x_=_x_ + 6*(len_);               \
  _TEXTSTYLE_= DRAW_OPT_NORMAL;         \
}


// printfEx redefined as printf()
// featuring \n, \t, and "\i" for writing inverted
//******************************************************************************
#define printf(_fmt, _val) {             \
  int _x=_cur_x_; int _y=_cur_y_;        \
  string _sf, _s;                        \
  _sf=_fmt;                              \
  while (Pos("\n",_sf)>=0) {             \
    _s=strsplit(_sf,"\n");               \
    while (Pos("\t",_s)>=0) {            \
      _x=(1+_x/_tab_width_)*_tab_width_; \
      _s=strexch(_s, "\t", ""); }        \
    printfxy( _x, _y, _s, _val);         \
    _x=0;  _y-=8;                        \
  }                                      \
  while (Pos("\t",_sf)>=0) {             \
    _x=(1+_x/_tab_width_)*_tab_width_;   \
    _sf=strexch(_sf, "\t", ""); }        \
    if(_x>=96) {_x=0; _y-=8;}            \
    if(_y<0) {scrclr(); _y=56;}          \
  printfxy( _x, _y, _sf, _val);          \
}


task main() {
  string str="test";
  int i=567; float f=1.2345; char c='A';
  printf("%s", str);
  Wait(1000);
  printf("%4d", i);
  Wait(1000);
  printf ("%6.3f", f);
  Wait(1000);

  printf("%c", 'A');
  Wait(1000);
  printf("%c", 'B');
  Wait(1000);
  
  printf("%c", 'C');
  Wait(1000);

  printf("%c", 7);      // <== not printed
  Wait(1000);
  
  printf("%c", 'D');
  Wait(1000);
  
  printf("%c", 14);     // <== not printed
  Wait(1000);

  printf("%c", 'E');
  Wait(1000);
  
  printf("%s", "_end_test_");
  Wait(1000);

  while(1);
}
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: [resolved]NXC:bug?feature?printing non-printable-ASCII-chars

Post by afanofosc »

Always best to check the source code before trying to describe its behavior from memory.

Code: Select all

    //If Item is defined by the font, display it.  Else, ignore it.
    Item = *pString - ' ';
    if (Item < Items)
Item is an unsigned long so it will wrap negative values (i.e., any ASCII character below ' ') to a very large positive value. Which means they aren't drawn, but the firmware increments X as it examines each character in the string being draw.

Code: Select all

    FontWidth = pFont->ItemPixelsX;
    //Calculate X coordinate of the right edge of this character.
    //If it will extend past the right edge, clip the string.
    X += FontWidth;
http://mindboards.svn.sourceforge.net/v ... rawing.inc

Which means that the effect is that a blank space will be left between two characters that are separated by a non-printable character.

strlen should return the number of characters before the first null, though in NXC it does not really do that. It returns ArrayLen - 1.

John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest