View previous topic :: View next topic |
Author |
Message |
Dutch Guy
Joined: 20 Mar 2018 Posts: 21 Location: University of Antwerp
|
atoi(*s) pointing to where? |
Posted: Sat Apr 18, 2020 1:25 pm |
|
|
CCS C v5.074
Code: | #include <18f87J50.h>
#fuses NOWDT,PLL3,NOCPUDIV,HSPLL,NOXINST
#DEVICE PASS_STRINGS=IN_RAM
|
When atoi(string_pointer) is called the pointer address gets transferred correctly though the dereferencing gives a weird output. I expect to get 35(ASCII'5') and I get 53....
What memory am I referencing to? Isn't the file register and it isn't the program register (bank 0 nor 1)...
Code: |
char *begin_char_ptr
if((atoi(begin_char_ptr+1)) > (2767 + (int)negative))
|
The function parameter s in atoi gives ok address (0x02B5) but *s gives a number that is not in my file register memory....
0x02B5 holds 35 and *s shows ans proceeds with 53 in MPLAB watch.
function called defines : signed int atoi(char *s).
I am reading numbers out of a string.
Anyone knows what is happening? _________________ I just can`t get it all in my head.... But wait, there is a new hole opening up.... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sat Apr 18, 2020 1:50 pm |
|
|
As posted, begin_char_ptr will contain random values.
The begin_char_ptr actual value will be the 16bit value held by the memory
at 0x2B5.
You have declared a pointer, but not actually set it to point to anything...
It needs to be pointed to the string you want it to access. |
|
|
Dutch Guy
Joined: 20 Mar 2018 Posts: 21 Location: University of Antwerp
|
|
Posted: Sat Apr 18, 2020 4:38 pm |
|
|
Thanks for the interest again Ttelmah.
I did shorten the posted code. The begin_char_pointer is loaded trough the function parameters in which itoa is used. While debugging it loads s in stdlib.h as 0x02B5(OK). This position holds 35 which is the '5' in my string as i see in the file register window. But when I look at the locals watch and also when mouseover *s it states a value of 53. When I put a '6' on the position 02B5 *s returns 54, a '1' returns 49 ...consistently. When I change the value of the position the itoa responds to it. 0x02b5 unchanged.
List of mapping(expected) : '1' = 49(31); '2' =50(32); '3'=51(33) ....
So it seems an offset of 28 ??? If i'd hypothetically change the *s=(*s-28)
in stdlib it would work but truely ugly.
Code: |
struct rtn sint16_atoi(char *begin_char_ptr, unsigned int digits,short negative) // declaring return of function in a struct c_s fashion
{
struct rtn C_S_ATOI;
signed int16 intercalc;
*(begin_char_ptr + digits) = '\0';
if (digits == 5)
{
if((atoi(begin_char_ptr+1)) > (2767 + (int)negative)) //convert last 4 and check for > 2767 / -2768
{
if(*begin_char_ptr <= '2')
{
intercalc = atoi(begin_char_ptr);
}
else
{
return(0);
}
}
else if(*begin_char_ptr <= '3')
{
intercalc = atoi(begin_char_ptr);
}
else
return(0);
}
else if (digits < 5)
{
intercalc = atoi(begin_char_ptr);
}
if(negative)
intercalc |= 0x8000; //ORmask neg bit 15
C_S_ATOI.value.s_value = intercalc;
return (C_S_ATOI);
} |
Already holding my hand close to my head for a "stupid slap" _________________ I just can`t get it all in my head.... But wait, there is a new hole opening up.... |
|
|
Dutch Guy
Joined: 20 Mar 2018 Posts: 21 Location: University of Antwerp
|
|
Posted: Sat Apr 18, 2020 4:50 pm |
|
|
This is the weirdest thing I saw in a while.
How can I post the printscreen png of my environment with watch windows and mouseover?
If I see mouseover 's' as 0x02B5 and I look at the file register then *s must be that value correct? If I change the 4th digit in my sent string then the value changes relatively with 28 offset... _________________ I just can`t get it all in my head.... But wait, there is a new hole opening up.... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sun Apr 19, 2020 12:40 am |
|
|
I think the big reason you are getting confused is numeric.
53 is 35......
35_hex_ is 53 in base 10.
You have different numeric formats selected for different parts of the
debugger.
Result confusion. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sun Apr 19, 2020 2:34 am |
|
|
As a further comment, are you using a PIC24/30/33?.
If not, for a 5 digit number you need to be using atol, not atoi. |
|
|
Dutch Guy
Joined: 20 Mar 2018 Posts: 21 Location: University of Antwerp
|
|
Posted: Sun Apr 19, 2020 5:33 am |
|
|
Not slapping myself yet
The device I'm using is a Clicker 2 board with a 18F87J50. I got tempted to use the ATOL() even with the 8 bit device. I was trying to check the number being in the -32768-32767 range before calling ATOI so I can send an err_rsp before a non signed int16 is put trough to convert. In my program it can be max 5 number-digits with a while(isdigit() && n<5) routine.
But I'm sure you know the feeling of trying it your way first ending with something hopefully working and several self inflicted head injuries Messing around is an excellent way of getting better in CCSC without using a driver at first attempt.
I'm digging in to the dec-hex problem now. Still not sure how atoi has reference problems. I'm also using strcpy, memcmp, strlen and strchr all passing their pointer and char value correctly regarding the file register window.
All is tested/stepped working up to the ATOI conversion. That's where I'm stuck now.
I copied some essentials out of my code, could be I missed some. Now I have also a strange feeling having also defined c as a global in the past.
The guide through is : USB_handler called -> command_len = command_checker(extracted_command) returns (int len) -> command_handler()
Code: |
//header
void clear_USB_command_buffer();//
void USB_handling();//
void command_handler(unsigned int,signed int);
enum {NONE,EJECT,UP,DOWN,BELT,STATUS}command_id = 0;
unsigned int command_checker(char *);
#define MAX_COMMANDS 7
#define MAX_COMMAND_LENGTH 10
char command_list[][MAX_COMMAND_LENGTH] ={"NONE","EJECT","LOAD","UP","DOWN","BELT","STATUS"};
struct rtn //returnstruct
{
short OK;
union value
{
signed int s_value;
unsigned int u_value;
};
};
struct rtn sint16_atoi(char *, unsigned int ,short );
//globals:
char c;
char OK[4] = "OK ";
char Ack_Packet_IN[13] = "Command_IN:";
char incoming_FIFO[FIFO_LENGTH];
//unsigned int last_FIFO_pos;
short new_incoming_command;
unsigned int8 start_FIFO_pos,last_FIFO_pos;
short command_to_echo;
//USB code:
void USB_handling()
{
if (usb_enumerated())
{
// unsigned int len = 0;
while (usb_cdc_kbhit())
{
if(!new_incoming_command)
{
last_FIFO_pos = start_FIFO_pos = (last_FIFO_pos + 1)%FIFO_LENGTH;
}
else
{
last_FIFO_pos = (last_FIFO_pos+1)%FIFO_LENGTH; // go around 64 positions
}
new_incoming_command = 1;
c = usb_cdc_getc();
incoming_FIFO[last_FIFO_pos] = c;
}
char extracted_command[32];
(last_FIFO_pos++)%FIFO_LENGTH;
incoming_FIFO[last_FIFO_pos] = '\0';
strcpy(extracted_command,(incoming_FIFO + start_FIFO_pos));
if(new_incoming_command)
{
unsigned int command_len = command_checker(extracted_command);
if (command_to_echo)
{
short command_var1_ok = 0;
signed int s_comvar_1; //signed comm value 1
if(command_len)
{
usb_cdc_puts(extracted_command);
delay_ms(1);
usb_cdc_putc('\n');
usb_cdc_putc(0x0D);
int *command_char_ptr = (strchr((extracted_command+command_len),' '));
int *begin_ptr = command_char_ptr;
for(int n = 0;(*command_char_ptr ==' ') && n < 8;n++)
{
command_char_ptr++; // SKIP UP TO 8 SPACES
begin_ptr++;
}
int digit_count = 0;
short negative;
if (*command_char_ptr == '-') //check for negative
{
negative = 1;
command_char_ptr++;
begin_ptr++;
}
else
negative = 0;
while(isdigit(*command_char_ptr) && digit_count < 6) // check up to 5 digits
{
digit_count++;
command_char_ptr++;
}
struct rtn c_s_1;
// come out with number of digits and sign
c_s_1 = sint16_atoi(begin_ptr,digit_count,negative); //declaration of struct element
if (c_s_1.OK )
{
command_var1_ok = 1;
s_comvar_1 = c_s_1.value.s_value;
}
else
{
command_var1_ok = 0;
s_comvar_1 = 0;
}
command_handler(command_id,s_comvar_1);
// command_to_echo= 0;
} //command length END
else//no command length
{
usb_cdc_puts(command_list);
delay_ms(1);
usb_cdc_putc('\n');
usb_cdc_putc(0x0D);
// command_to_echo= 0;
}
command_to_echo= 0;
} //command to echo END
new_incoming_command = 0;
} //new_incoming END
} //enumerated END
} //USB handling END
unsigned int command_checker(char *command_str) //returns command length if match, else 0
{
char *command_list_ptr; //defines empty 8 bit spaces with a pointer index
usb_cdc_puts(Ack_Packet_IN);
delay_ms(1);
command_list_ptr = &command_list[0]; //seemed wrapping of commandlist with element 0 and referencer is needed. TEST LATER
for(unsigned int i = 0 ; i <= MAX_COMMANDS && *(command_list_ptr) != '\0'; i++)
{
int c_len = strlen(command_list_ptr);
if(!memcmp(command_str,command_list_ptr,c_len) && (*(command_str+c_len) == ' ' || *(command_str+c_len) == '\0') )
{
command_to_echo = 1;
command_id = i-1;
return(c_len);
}
command_list_ptr += MAX_COMMAND_LENGTH;
}
command_id = 0;
command_to_echo = 1;
return(0);
}
void command_handler(unsigned int id,signed int handler_com_var1)
{
switch (id)
{
case 1 : //EJECT
bit_set(EJECT_REQ);
command_id = 0;
break;
case 2 : // put glass on belt
bit_set(LOAD_REQ);
command_id = 0;
break;
case 3 :
bit_set(UP_REQ);
command_id = 0;
break;
case 4 :
bit_set(DOWN_REQ);
command_id = 0;
break;
case 5 ://belt
if(handler_com_var1 < 0)
{
if(bit_test(DIR_BELT_COIL))
{
bit_set(BELT_DIR_TOGGLE_REQ);
if(!bit_test(RUN_BELT_COIL))
bit_set(BELT_RUN_TOGGLE_REQ);
}
}
else if((handler_com_var1 > 0))
{
if(!bit_test(DIR_BELT_COIL))
{
bit_set(BELT_DIR_TOGGLE_REQ);
if(!bit_test(RUN_BELT_COIL))
bit_set(BELT_RUN_TOGGLE_REQ);
}
}
else
{
if(bit_test(RUN_BELT_COIL))
bit_set(BELT_RUN_TOGGLE_REQ);
}
command_id = 0;
break;
case 6 ://belt
break;
default:
command_id = 0;
break;
} //switch id END
} //command handler end
struct rtn sint16_atoi(char *begin_char_ptr, unsigned int digits,short negative) // declaring return of function in a struct c_s fashion
{
struct rtn C_S_ATOI;
signed int16 intercalc;
*(begin_char_ptr + digits) = '\0';
if (digits == 5)
{
if((atoi(begin_char_ptr+1)) > (2767 + (int)negative)) //convert last 4 and check for > 2767 / -2768
{
if(*begin_char_ptr <= '2')
{
intercalc = atoi(begin_char_ptr);
}
else
{
return(0);
}
}
else if(*begin_char_ptr <= '3')
{
intercalc = atoi(begin_char_ptr);
}
else
return(0);
}
else if (digits < 5)
{
intercalc = atoi(begin_char_ptr);
}
if(negative)
intercalc |= 0x8000; //ORmask neg bit 15
C_S_ATOI.value.s_value = intercalc;
return (C_S_ATOI);
} |
_________________ I just can`t get it all in my head.... But wait, there is a new hole opening up.... |
|
|
Dutch Guy
Joined: 20 Mar 2018 Posts: 21 Location: University of Antwerp
|
|
Posted: Sun Apr 19, 2020 5:52 am |
|
|
Yes Ttelmah you are right again. My itoa is failing because of something else. I just discovered that the mouseover results in decimal values. I really got fixed on this as being an error.
Thanks _________________ I just can`t get it all in my head.... But wait, there is a new hole opening up.... |
|
|
Dutch Guy
Joined: 20 Mar 2018 Posts: 21 Location: University of Antwerp
|
|
Posted: Sun Apr 19, 2020 6:44 am |
|
|
And it got completely clear now I see that int result variable in itoa is only 8-bit.
I_to_l it is. Flips at 128
Switching between int definitions and processors will keep haunting me. _________________ I just can`t get it all in my head.... But wait, there is a new hole opening up.... |
|
|
Dutch Guy
Joined: 20 Mar 2018 Posts: 21 Location: University of Antwerp
|
|
Posted: Sun Apr 19, 2020 7:05 am |
|
|
Its working fully now.
My end question is : What would be best ?
- First checking for last 4 digits to be under the +276-278 range and checking the 5th digit for being 3 or lower before feeding the A_TO_L.
or
-Converting with A_to_I32 and then checking the int32 for being withing 32767 to -32768 range.
This is what I had in mind in the beginning, I was only confused again atoi being 8 bit and not 16. _________________ I just can`t get it all in my head.... But wait, there is a new hole opening up.... |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Sun Apr 19, 2020 8:17 am |
|
|
OK, please humour me......
You've got a 5 character string ( ASCII) xxxxx and you want to know if it's less than 32767
so... wouldn't a set of simple compare tests, in the right sequence work better or faster ?
consider when a[5] = '32767'
....
if a[4] =>4 //too big ( 4xxxx)
then
if a[3] =>3 //too big ( 33xxx)
then
if a[2] =>8 //too big ( 328xx)
.....
Ok I'm NOT a C programmer, just trying to thing of an easier way to do the test as I assume atoi are 'big' functions....size and execute. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Sun Apr 19, 2020 1:17 pm |
|
|
If the strings are purely 'numbers', without any of the formatting
supported by atol (no hex or binary), and are always +ve, it is actually
significantly faster and smaller to go 'DIY'.
Code: |
#inline
unsigned int16 times10(unsigned int16 val)
{
return (val*8+val*2);
} //this is significantly more efficient than a standard *10.
unsigned int16 asctoul(char * string)
{
byte chr;
unsigned int16 result=0;
chr=*(string++);
while (chr!=0 && chr!=13) //LF or NUL terminates
{
if (chr==' ')
continue; //ignore spaces
chr=chr-'0'; //ascii to binary
result=times10(result);
result+=chr; //add in the digit
chr=*(string++);
}
return result;
}
|
You may be surprised at how much faster this is than atol. |
|
|
|