| 
	
	|  |  |  
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| cvargcal 
 
 
 Joined: 17 Feb 2015
 Posts: 134
 
 
 
			    
 
 | 
			
				| help with string [Solved] |  
				|  Posted: Mon Apr 27, 2020 11:58 pm |   |  
				| 
 |  
				| I have a problem for read this data, 
 
 I capture  this data and when  I use  printf  %X show this
 301c0017637661726763616c2f66656564732f636f6e74726f6c31333431
 
 printf  %c
 0cvargcal/feeds/control1341
 
 
 
  	  | Code: |  	  | void test(){ 
 buffer[50]=301c0017637661726763616c2f66656564732f636f6e74726f6c31333431;
 
 int len strlen(buffer);
 
 for (int  i=0; i<len;i++)   fprintf(uart4,"%x",buffer[i]);
 
 if (strstr(buffer, "control1") != 0)   fprintf(uart4," found control\r\n");
 
 }
 | 
 
 so why dont work strstr, never found the word?
 |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Apr 28, 2020 12:24 am |   |  
				| 
 |  
				|  	  | Quote: |  	  | I capture this data and when I use printf %X show this 301c0017637661726763616c2f66656564732f636f6e74726f6c31333431
 
 | 
 You have 0x00 as the 3rd byte.  That 0x00 byte terminates the string.
 The strstr() function will not search past the end of a string.
 
 To fix it, set the start of the string to buffer+3 as shown below:
 
  	  | Quote: |  	  | if(strstr(buffer+3, "control1") != 0)
 | 
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Apr 28, 2020 12:25 am |   |  
				| 
 |  
				| The %x print can't show what you say. 
 You show the third character as being 00. This is the end of string character
 in C, so strlen would only give the length as two characters.....
 
 strstr, would stop at this NUL character....
 
 Just built a demo based on what you post:
 
  	  | Code: |  	  | #include <18F4520.h>
 #device PASS_STRINGS=IN_RAM  //needed to allow constant in strstr
 #device ADC=10
 
 #FUSES NOWDT                    //No Watch Dog Timer
 
 #use delay(crystal=20000000)
 
 
 #use rs232(UART1, baud=9600, ERRORS, stream=UART4)
 #include "string.h"
 
 void test(){
 
 char buffer[50]={0x30,0x1c,0x00,0x17,0x63,0x76,0x61,0x72,0x67,0x63,0x61,0x6c,0x2f,0x66, \
 0x65,0x65,0x64,0x73,0x2f,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x31,0x33,0x34,0x31};
 
 int len;
 len=strlen(buffer);
 
 for (int  i=0; i<len;i++)
 fprintf(uart4,"%x",buffer[i]);
 
 if (strstr(buffer, "control1") != 0)
 fprintf(uart4," found control\r\n");
 
 }
 
 void main()
 {
 setup_adc_ports(NO_ANALOGS, VSS_VDD);
 
 while(TRUE)
 {
 test();
 delay_cycles(1);
 }
 }
 
 | 
 Stuck the output to UART1, and if I stop at:
 for (int  i=0; i<len;i++)
 
 len is 2.
 
 I see PCM spotted the same problem as I was typing...
  |  |  
		|  |  
		| cvargcal 
 
 
 Joined: 17 Feb 2015
 Posts: 134
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Apr 28, 2020 12:40 am |   |  
				| 
 |  
				| Thanks you for answers... So the best way is copy the string and change the 0x00 by other byte??
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Apr 28, 2020 12:49 am |   |  
				| 
 |  
				| At the end of the day a lot depends on 'unsaid' things about this. 
 You are receiving this data?.
 If so, does it have a NUL at the end of the buffer?.
 If it doesn't, 'string' based operations if they get past the NUL earlier
 in the data, risk walking off through memory, taking a long time, and
 finding unexpected things.
 To use 'string' operations, you need to design how you receive and store the
 data, so that if a NUL is received earlier, it is perhaps replaced with
 another 'unused' character. Perhaps 0xFF for example.
 Then you need to ensure that before any string function is used, you have
 added a genuine NUL terminator to the data.
 
 Alternatives are as PCM_Programmer says, to simply skip the first three
 characters, if the NUL is always going to be at this point. Or you could
 just use the source code for strstr (it's in string.h), and instead of
 searching till the NUL is seen, use the length of the actual data
 (I'm guessing that your actual %x print, was really using the received
 length, not strlen as you show, since as posted it won't work...).
 If so, use the length this was using.
 |  |  
		|  |  
		| cvargcal 
 
 
 Joined: 17 Feb 2015
 Posts: 134
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Apr 28, 2020 6:49 pm |   |  
				| 
 |  
				| Why no work this: 
 data
 301c0017637661726763616c2f66656564732f636f6e74726f6c31333431
 
 char
 0cvargcal/feeds/control1341
 
 
 
 
  	  | Code: |  	  | uint16_t  len = readPacket(buffer,5000);   // return one full packet      301c0017637661726763616c2f66656564732f636f6e74726f6c31333431
 if (len>0){
 
 int8 topic_len=24;            //cvargcal/feeds/control1
 int8 f=1+4+ topic_len ;    //29
 
 //  ___________  _________
 // 30 1c 00 17 63  topic/data
 // C    1   2   3  4
 
 
 while (1){
 
 char dat2[40];
 if(strstr(buffer+3, "control1") != 0) {
 
 fprintf(" found control1\r\n");
 int k=0;
 for (uint16_t i=0; i+f <len;i++){
 dat2[k] = buffer[i+f];
 k++;
 }
 fprintf("\r\n dat %s\r\n",dat2);
 for (uint16_t h=0; dat2[h]!=0;h++) fprintf("%c",dat2[h]);
 break;
 
 }
 }
 | 
 
 
 Why no print the dat2?
 
 
 I need get the value that mqtt server send
 C control byte + 4 byte len + payload (topic+data)
 
 
 
 edit
 
 
 
 I GET IT!! (Well copy code from mqtt adafruit)
 
 
  	  | Code: |  	  | if (len>0){ uint16_t i, topiclen, datalen;
 
 // Parse out length of packet.
 topiclen = buffer[3];
 
 
 uint8_t packet_id_len = 0;
 uint16_t packetid = 0;
 // Check if it is QoS 1, TODO: we dont support QoS 2
 if ((buffer[0] & 0x6) == 0x2) {
 packet_id_len = 2;
 packetid = buffer[topiclen+4];
 packetid <<= 8;
 packetid |= buffer[topiclen+5];
 }
 
 memset(dat2, 0, 100);
 
 datalen = len - topiclen - packet_id_len - 4;
 
 // extract out just the data, into the subscription object itself
 memmove(dat2, buffer+4+topiclen+packet_id_len, datalen);
 
 
 for (int  i=0; i<datalen;i++)  fprintf(uart4,"%c",dat2[i]);
 break;
 
 }
 | 
 |  |  
		|  |  
		|  |  
  
	| 
 
 | You cannot post new topics in this forum You cannot reply to topics in this forum
 You cannot edit your posts in this forum
 You cannot delete your posts in this forum
 You cannot vote in polls in this forum
 
 |  
 Powered by phpBB © 2001, 2005 phpBB Group
 
 |