LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

How can I show the non printable first ascii character NULL in a string?

Solved!
Go to solution

I am looking for a way how to show the ascii characters that could are not printable, especially the NULL ascii character. I tried to change the configuration of the com port, since I send the characters to a board through a com port. Here is the configuration:

iResult = OpenComConfig (5, "COM5", 9600, 0, 8, 1, 512, 512);

Is there a way or a function that I can use to show the non printable ascii characters, especially the NULL character?

0 Kudos
Message 1 of 10
(6,194 Views)
Solution
Accepted by topic author Ramles97

I normally dump these messages to file/screen printing the Hex code for each of the characters in them.

I have set up a compact instruction that performs this task in a single line leveraging Fmt () function in the Formatting and I/O Library of CVI (if you are focused on code portability you will need to replace it with appropriate sprintf equivalent). Take a look at the function help to understand how the formatting string works:

 

 

 

Fmt (buf, "%s In: 0x%*d[zb1w2p0r16j1] \n", TimeStr (), NumberOfChars, msg);
DebugPrintf ("%s", buf);

 

 

 

Provided he appropriate number of characters is given, NULL characters are displayed without complications producing an output similar to this one:

 

 

14:28:12 In: 0x02 00 00 00 14 00 00 04 60 05 f0 01 f4 00 00 0b b8 00 00 00 00

 

 

 



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
Message 2 of 10
(6,168 Views)

@RobertoBozzolo

Thank you so much for your reply.

I actually have a microcontroller that has an antenna, and with this antenna I send data to a tag, which contains some blocks.

The data are in form of 4 characters that can be sent to every block.

(See the code part)

https://forums.ni.com/t5/LabWindows-CVI/How-can-convert-a-string-character-that-I-have-into-a-hex-nu...

 

Since I show the data which has been sent in a panel as hex values, I just dont see any 0x00 that has been sent or saved in the block and this characters gets ignored. This is how I put the 4 characters(in a char array/string):

 

			Fmt(Result_Block0,"%s<%s%s%s%s",c_Char1,c_Char2,c_Char3,c_Char4);

 

 I added the next line :

DebugPrintf ("%s<%s%s%s%s\n", Result_Block0, c_Char1,c_Char2,c_Char3,c_Char4);

But no avail (Except the c_char1, which contains the value 0x00, get the character '0' which is not 0x00 but 0x30. I know  I must be doing something wrong or there is something that might be missing..

Thanks a lot in adance for the big help! @RobertoBozzolo

0 Kudos
Message 3 of 10
(6,149 Views)

Consider that wherever you use %s the command treats it as a string, so it stops at the first NUL byte. You have no way of displaying characters past the first NUL byte in a string (or a string control/indicator, which is the same), that's why  I adopted the solution described earlier.



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 4 of 10
(6,128 Views)

in C strings are 0 terminated. -LabWindows CVI is a C compiler. If you want to see incoming binary data as 4 byte integer you have to treat it accordingly. The %s formatting specifier is in that case definitely the wrong choice as Roberto already pointed out!

Rolf Kalbermatter
My Blog
0 Kudos
Message 5 of 10
(6,100 Views)

in C strings are 0 terminated. -LabWindows CVI is a C compiler. If you want to see incoming binary data as 4 byte integer you have to treat it accordingly. The %s formatting specifier is in that case definitely the wrong choice as Roberto already pointed out!

Tip, it likely will involve %hx and some extra modifiers to tell it it is an array and the length of it if you have more than 1 4 byte value in the stream.

Rolf Kalbermatter
My Blog
0 Kudos
Message 6 of 10
(6,099 Views)

Thanks a lot for the reply.

Thanks to your answer I got to learn what the format modifiers are for and how to use them.

But I just cannot show the null terminator in the string.. I tried your solution and also some other modifiers that I read they could solve my problem ( appending the null for example [q]..)

I wrote an If-Condition to add the '/0' to the character if the character is empty but also no avail...

I am sorry I am still a beginner at CVI.. maybe it is something easy to solve, but I just cannot find the solution for it..

0 Kudos
Message 7 of 10
(6,069 Views)

Well, as you may imagine, even we experienced CVI programmers are not so good in reading what's written only in your brain... 😉

 

If you may post here

  • Actual raw content of the message
  • What you want to obtain
  • What you have done till now

we may be able to give you some hint on how to modify your code.

'cause as you know NUL bytes are.... NULLs! There is really nothing to show in those bytes so: how are you willing to evidence them in your output?



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 8 of 10
(6,063 Views)

Well in binary you do find in the string a byte full of "00000000" of the characters. So the characters are not  empty and 0x00 is also a value, you can correct me if I am wrong.

I already did post a part from the code and shared the link since I posted another question related to this one, but since I changed the code a bit, here is what I wrote to send DATA through COMPort.

 

PS: I know people here are sincere und say it like it is especially if the code looks bad. But I am still learning.. 🙂

B1 has 32 Bits and each 8 Bits gets converted to a character. The problem is when there are 00000000 Bits, I get an empty char.

 

 //GTIN first 32 Bits to the first Block
//Write into Variable B1 and convert from binary to decimal
Daten_EEPROM_Byte_VERTEILER (B1, cFirst_Byte, &i_Char1, cSecond_Byte, &i_Char2, cThird_Byte, &i_Char3, cFourth_Byte, &i_Char4);

//Convert the decimal into ASCII character
Daten_HILFSFUNKTION_decimal_char (c_Char1, i_Char1, c_Char2, i_Char2, c_Char3, i_Char3, c_Char4, i_Char4);

//Converting Ascii to Hex to visualize Hex Values on the panel
Daten_Uebergangshilfsfunktion_char_hex (c_Char1, x_char1, c_Char2, x_char2, c_Char3, x_char3, c_Char4, x_char4, iSeriennummer);

// Writing Data in Block 1
Fmt(Result_Block1,"%s<%s%s%s%s",c_Char1,c_Char2,c_Char3,c_Char4);
Fmt(cCommand,"%s<%s%s%s%s",WRITE_BLOCK,"1_",Result_Block1,ENDE);
iResult = Befehl_Senden(cCommand,cAnswer);

Fmt(x_Result_B1,"%s<%s%s%s%s",x_char1,x_char2,x_char3,x_char4);
SetCtrlAttribute(sPanels.P_Hauptmenue, P_MAIN_WB1, ATTR_CTRL_VAL, x_Result_B1);


// Reading Data from Block 1 to check if Data has been successfully written.
Fmt(cCommand,"%s<%s%s%s",READ_BLOCK,"1",ENDE);
iResult = Befehl_Senden(cCommand,cAnswer);
CopyBytes(cRead_Block_1,0,cAnswer,23,8);
SetCtrlAttribute(sPanels.P_Hauptmenue, P_MAIN_BR1, ATTR_CTRL_VAL, cRead_Block_1);

//Initializing all the variables for further use
h_Memset_Function(x_char1,x_char2,x_char3,x_char4);
c_Memset_Function(c_Char1, c_Char2, c_Char3, c_Char4);
c_Memset_Function(cFirst_Byte, cSecond_Byte, cThird_Byte, cFourth_Byte);

Here are all the functions I used for the main code:


void GTIN_96_Bits_To_3x_32_Bits(char *EEPROM, char *B0_0_31Bits, char *B1_32_63Bits, char *B2_64_95Bits)
{
CopyString(B0_0_31Bits,0,EEPROM,0,32);
CopyString(B1_32_63Bits,0,EEPROM,32,32);
CopyString(B2_64_95Bits,0,EEPROM,64,32);
}


// ************************************************************************************************************************
// OK: CHECK?; V.Nachname 22.06.2021
// Dieses Funktion verteilt 4 Bytes / 32 Bits in 4 Binär und dann Dezimal Variablen.
// ************************************************************************************************************************
void Daten_EEPROM_Byte_VERTEILER(char *B, char *cFirst_Byte,int *i_Char1,char *cSecond_Byte,int *i_Char2,char *cThird_Byte,int *i_Char3,char *cFourth_Byte,int *i_Char4)
{
CopyBytes(cFirst_Byte, 0,B,0,8);
CopyBytes(cSecond_Byte, 0,B,8,8);
CopyBytes(cThird_Byte, 0,B,16,8);
CopyBytes(cFourth_Byte, 0,B,24,8);

Daten_HILFSFUNKTION_binary_decimal(cFirst_Byte,i_Char1);
Daten_HILFSFUNKTION_binary_decimal(cSecond_Byte,i_Char2);
Daten_HILFSFUNKTION_binary_decimal(cThird_Byte,i_Char3);
Daten_HILFSFUNKTION_binary_decimal(cFourth_Byte,i_Char4);
}
void Daten_Uebergangshilfsfunktion_char_hex (char *c_Char1, char *x_char1, char *c_Char2, char *x_char2, char *c_Char3, char *x_char3,char * c_Char4, char *x_char4, int iSeriennummer)
{
DATEN_Umwandlungsfunktion_Char_hex (c_Char1, x_char1, &iSeriennummer);
DATEN_Umwandlungsfunktion_Char_hex (c_Char2, x_char2, &iSeriennummer);
DATEN_Umwandlungsfunktion_Char_hex (c_Char3, x_char3, &iSeriennummer);
DATEN_Umwandlungsfunktion_Char_hex (c_Char4, x_char4, &iSeriennummer);
}

void Daten_HILFSFUNKTION_decimal_char (char *c_Char1, int i_Char1,char *c_Char2, int i_Char2,char *c_Char3, int i_Char3,char * c_Char4, int i_Char4)
{
Fmt(c_Char1,"%c[w1p0]<%i",i_Char1);
Fmt(c_Char2,"%c[w1p0]<%i",i_Char2);
Fmt(c_Char3,"%c[w1p0]<%i",i_Char3);
Fmt(c_Char4,"%c[w1p0]<%i",i_Char4);
}


void Daten_c_PV_Byte_TEILER (char *c_PV, char *c_Char1, int *i_Char1, char *c_Char2, int *i_Char2, char *c_Char3,int *i_Char3, char *c_Char4, int *i_Char4)
{
CopyBytes(c_Char1,0,c_PV,0,1);
CopyBytes(c_Char2,0,c_PV,1,1);
CopyBytes(c_Char3,0,c_PV,2,1);
CopyBytes(c_Char4,0,c_PV,3,1);

Daten_HILFSFUNKTION_binary_decimal(cFirst_Byte,i_Char1);
Daten_HILFSFUNKTION_binary_decimal(cSecond_Byte,i_Char2);
Daten_HILFSFUNKTION_binary_decimal(cThird_Byte,i_Char3);
Daten_HILFSFUNKTION_binary_decimal(cFourth_Byte,i_Char4);
}


void Daten_cLC_ID_Byte_TEILER (char *cLC_ID, char *cFirst_Byte, char *cSecond_Byte, char *cThird_Byte, char *cFourth_Byte)
{
CopyBytes(cFirst_Byte, 0,cLC_ID,0,8);
CopyBytes(cSecond_Byte, 0,cLC_ID,8,8);
CopyBytes(cThird_Byte, 0,cLC_ID,16,8);
CopyBytes(cFourth_Byte, 0,cLC_ID,24,8);
}


char *decimal_to_binary(int n)
{
int c, d, t;
char *p;

t = 0;
p = (char*)malloc(32+1);

if (p == NULL)
exit(EXIT_FAILURE);

for (c = 31 ; c >= 0 ; c--)
{
d = n >> c;

if (d & 1)
*(p+t) = 1 + '0';
else
*(p+t) = 0 + '0';

t++;
}
*(p+t) = '\0';

return p;
}void Daten_HILFSFUNKTION_binary_decimal (char *cEingang, int *iAusgang)
{
int multiplier = 0;
int i;
int sum = 0;
int length;
char cMonth[10] = {0};
int iMonth;

length = StringLength (cEingang);
for (i=length-1; i>=0; i--)
{
CopyBytes (cMonth, 0, cEingang, i, 1);
Fmt (&iMonth, "%x<%s", cMonth);
sum = sum +(iMonth*pow(2, multiplier));
multiplier = multiplier + 1;
}
Fmt (iAusgang, "%i<%i", sum);
}


char *Daten_EEPROM_HILFSFUNKTION(char *Char_in_Bits, char *c_8Bits)
{
int Decimal = 0;
char c_Character[5] = {0};
CopyString(Char_in_Bits, 0,c_8Bits,0,8);
Daten_HILFSFUNKTION_binary_decimal (Char_in_Bits, &Decimal);
int B_1_dec = Decimal;
Fmt(c_Character,"%c<%i",B_1_dec);
Char_Ueberpruefung_Null_ASCII(&B_1_dec, c_Character);
memset(Char_in_Bits,0,sizeof(Char_in_Bits));
return c_Character;

}

void char_Umwandeln (char *cEingang,char *cAusgang)
{
int ilaenge;
int idez_Wert;
int iPos;
char cZwischenspeicher [5] = {0};
ilaenge = StringLength(cEingang);
for (iPos = 0; iPos <=ilaenge - 1; iPos++)
{
idez_Wert = 0;
//CopyBytes (cZwishcenspeicher, 0, cEingang, ilaenge-iPos,1);
CopyBytes (cZwischenspeicher,0,cEingang,iPos,1);
Scan (cZwischenspeicher,"%s>%i[r256]",&idez_Wert);
if (idez_Wert == 0)
{
CopyBytes (cAusgang, 0,"00",0,2);
}
else if (idez_Wert <16)
{
Fmt(cAusgang,"%s<%s%s%i[r16]",cAusgang,"0",idez_Wert);
}
else
{
Fmt(cAusgang,"%s<%s%i[r16]",cAusgang,idez_Wert);
}
}
StringUpperCase(cAusgang);
}

void DATEN_Umwandlungsfunktion_Char_hex (char *Char, char *hex_Char, int *dec_Nummer)
{
char_Umwandeln (Char,hex_Char);
Scan(&hex_Char,"%s>%x",&dec_Nummer);
}


void h_Memset_Function(char *hexchar1,char *hexchar2,char *hexchar3,char *hexchar4)
{
memset(hexchar1,0,sizeof(hexchar1));
memset(hexchar2,0,sizeof(hexchar2));
memset(hexchar3,0,sizeof(hexchar3));
memset(hexchar4,0,sizeof(hexchar4));
}

void c_Memset_Function(char *cChar1,char *cChar2,char *cChar3,char *cChar4)
{
cChar1 = "\0";
cChar2 = "\0";
cChar3 = "\0";
cChar4 = "\0";

}


*
void Char_Ueberpruefung_Null_ASCII (int *i_Char, char *Char)
{
if (*i_Char == 0)
{
Fmt(Char,"%c<%i[w1p0r256]",0);
}
}

 

0 Kudos
Message 9 of 10
(6,060 Views)

Lots of code to do a simple thing. Consider this:

 

char bytes[] = {0x00, 0x01, 0x30, 0xA7};

FmtOut("%s<This is the 32-bit hex big endian form of above bytestream: 0x%x[b4o3210w8p0]\n", *(int*)bytes);
FmtOut("%s<This is the 32-bit hex little endian form of above bytestream: 0x%x[b4o0123w8p0]\n", *(int*)bytes);
FmtOut("%s<You can also format it as array of 4 comma separated hex bytes: %4x[b1w2p0j1],\n", bytes);

FmtOut("%s<4chars: %c%c%c%c", bytes[0], bytes[1], bytes[2], bytes[3]);
FmtOut("%s<array of 4 chars: %4c", bytes);

 

But don't use %s (or %c) when trying to format a parameter that can contain NULL bytes and you don't want the format function to stop at that NULL byte. The NULL character in the lowest two examples will be usually invisible in most consoles unless your console uses a special font that contains a real glyph at ASCII code 0.

This is the 32-bit hex big endian form of above bytestream: 0xA7300100
This is the 32-bit hex little endian form of above bytestream: 0x000130A7
You can also format it as array of 4 comma separated hex bytes: 00,01,30,A7
4 chars: ÿ §
array of 4 chars: 
Rolf Kalbermatter
My Blog
0 Kudos
Message 10 of 10
(6,046 Views)