|
|
View previous topic :: View next topic |
Author |
Message |
bwgames
Joined: 21 Jul 2005 Posts: 36
|
Weird behaviour with fgets |
Posted: Mon Aug 14, 2006 3:49 am |
|
|
My code is as follows:
Code: |
char duration_char[7];
...
duration_label: fprintf(Computer,"\n\r\n\rEnter required duration (hhmmss):");
fgets(duration_char,Computer);
fprintf(Computer,"\n\rInput: %s\n\r",duration_char);
hrs_char[0] = duration_char[0];
hrs_char[1] = duration_char[1];
min_char[0] = duration_char[2];
min_char[1] = duration_char[3];
sec_char[0] = duration_char[4];
sec_char[1] = duration_char[5];
hours = atoi(hrs_char);
minutes = atoi(min_char);
seconds = atoi(sec_char);
acceptable=check_duration(hours,minutes,seconds,sspeed);
....
|
When I output the duration_char array, I only get the first 3 characters that I input (e.g. if I type in 552211 - for 55hrs, 22mins, 11seconds), Output: 552. This is reflected in the atoi operands - it does not appear to be a case of fprintf not printing the whole array, fgets just appears not to read anything beyond the third character....
Any ideas?
Cheers
Last edited by bwgames on Mon Aug 14, 2006 4:28 am; edited 1 time in total |
|
|
Ttelmah Guest
|
|
Posted: Mon Aug 14, 2006 4:15 am |
|
|
First, 'atoi', only accepts a single character, not a string of characters. You need to convert each character in turn.
So something like:
hours=(atoi(duration_char[0])*10)+atoi(duration_char[1]);
Then the code as given puts both the 'hours' bytes into the same target byte.
Then you have nothing to deal with the possibility of somebody typing a longer string. Look at using the 'get_string' function (in input.c), or your own version of this to deal with streams.
If you are typing the characters at the far end, are you sure that six characters are being typed (remember that if 'echo' is turned on, typing 552, will display on the source as 555522, and would then lead to gets only seeing three characters.
Best Wishes |
|
|
bwgames
Joined: 21 Jul 2005 Posts: 36
|
|
Posted: Mon Aug 14, 2006 4:21 am |
|
|
Quote: |
First, 'atoi', only accepts a single character, not a string of characters. You need to convert each character in turn. |
Are you sure?
Quote: |
(From CCS Manual, for atoi)
Syntax:
ivalue = atoi(string)
or
lvalue = atol(string)
or
i32value = atoi32(string)
Parameters:
string is a pointer to a null terminated string of characters.
Returns:
ivalue is an 8 bit int.
lvalue is a 16 bit int.
i32value is a 32 bit int.
|
hrs_char[2] etc is NULL.
(set earlier in code by hrs_char[2] = NULL; etc and for min_, sec_)
Local echo on the PC terminal program is turned on, but this shouldn't affect it surely? Turning it off has no effect either...
my USE RS232 line is:
#use rs232(baud=19200, xmit=PIN_B1, rcv=PIN_B0, DISABLE_INTS, STREAM=Computer) //Computer |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Aug 14, 2006 4:46 am |
|
|
Quote: | I only get the first 3 characters that I input | You didn't mention the processor type you are using so I can't check what is connected to pins B0 and B1, but is it possible you are using the hardware UART? If yes, then it is possible the UART has a receive buffer overflow because you are not reading the data quick enough. Try adding the ERRORS directive to the #use RS232 line and see if this improves things. |
|
|
bwgames
Joined: 21 Jul 2005 Posts: 36
|
|
Posted: Mon Aug 14, 2006 4:57 am |
|
|
That is software UART (Its a 18F452).
All fgets does is, wait for a character, reads it in, and when a return is read, terminates the array. Interrupts are disabled too (both in the use RS232, and in the subroutine that calls fgets etc, so I can't see anything that would be interrupting it.... |
|
|
Ttelmah Guest
|
|
Posted: Mon Aug 14, 2006 5:02 am |
|
|
Sorry, I was thinking about an older byte conversion code. However the problem will remain, that the strings need to be terminated. As shown the code does not show this being done.
He should be reading fast enough, unless the baud rate is 'silly', since he is doing nothing between the characters, and it sounds as if the data is being typed.
One thing that really 'worries' me, is that I suspect he is overrunning the input buffer. If the source sends LF/CR, rather than just CR, for the 'enter', then the buffer will be overrunning. The effect of this is indeterminate (depends what else is stored in memory). This will also apply if the source sends CR/LF, if the 'fetch' is repeated, since there will then be an extra character at the front of the data..
I also 'worry', that he is showing a label defined at the start of the code, since this suggests the possibility of some 'messy' programming, which could cause any number of effects...
Best Wishes |
|
|
bwgames
Joined: 21 Jul 2005 Posts: 36
|
|
Posted: Mon Aug 14, 2006 5:13 am |
|
|
Ttelmah wrote: | Sorry, I was thinking about an older byte conversion code. However the problem will remain, that the strings need to be terminated. As shown the code does not show this being done.
|
Apologies for that, as I mentioned in a post later, I am terminating my strings with
Code: |
char duration_char[7];
char sec_char[3];
char min_char[3];
char hrs_char[3];
sec_char[2]=NULL;
min_char[2]=NULL;
hrs_char[2]=NULL;
|
Quote: |
He should be reading fast enough, unless the baud rate is 'silly', since he is doing nothing between the characters, and it sounds as if the data is being typed.
|
yes it is being typed
Quote: |
One thing that really 'worries' me, is that I suspect he is overrunning the input buffer. If the source sends LF/CR, rather than just CR, for the 'enter', then the buffer will be overrunning. The effect of this is indeterminate (depends what else is stored in memory). This will also apply if the source sends CR/LF, if the 'fetch' is repeated, since there will then be an extra character at the front of the data..
|
Thanks, I hadn't thought of that! However it turns out that just <CR> is being sent, not CR+LF.
Quote: |
I also 'worry', that he is showing a label defined at the start of the code, since this suggests the possibility of some 'messy' programming, which could cause any number of effects...
Best Wishes |
I wasn't keen on the label either, but I needed a way to enable the user to re-enter the duration if the check_acceptable routine returned a error value (e.g. if there wasn't enough EEPROM space to store the data for that duration).
I tried commenting that out, and no difference.
However, I tried a simple test program consisting of just the above code,
and it worked, so somethings up somewhere.
The strange thing is, that just before the duration code, I have
Code: |
fprintf(Computer,"\n\r\n\rEnter sample speed for TX %03i \n\r",tx);
fprintf(Computer,"Maximum speed is 2Mhz (2000000Hz).\n\r\n\r");
fgets(sspeed_char,Computer);
sspeed = atoi32(sspeed_char);
|
which works fine; its just the duration code for some reason. |
|
|
Ttelmah Guest
|
|
Posted: Mon Aug 14, 2006 8:07 am |
|
|
I'd seriously consider just coding a version the 'get_string' function, from input.c, to use your named stream, so that you can specify the string length. This should be considered the 'standard'input method, because gets, with the possibility of incorrect length strings is so damn dangerous...
One thought is (for instance), that it may be the fetch in front of this one, that is actually overflowing, and damaging another variable...
The 'obvious' thoughts now, are that 1) the transmitter is doing a LF, perhaps because of the total line length so far, and 2), that some form of overwriting is taking place. Multiple possibilities with the latter. Something with string handling going further than it should, or something actually stopping the UART ( like the classic end of code 'sleep', though I'd expect to only lose two characters in this case).
The way you loop back if the data can't read, is normally with a while. So:
Code: |
int1 save_ok=false;
while (!save_ok) {
//Get value here
save_ok = status_of_eeprom_operation;
}
|
Best Wishes |
|
|
|
|
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
|