CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Weird behaviour with fgets

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
bwgames



Joined: 21 Jul 2005
Posts: 36

View user's profile Send private message

Weird behaviour with fgets
PostPosted: Mon Aug 14, 2006 3:49 am     Reply with quote

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 Smile


Last edited by bwgames on Mon Aug 14, 2006 4:28 am; edited 1 time in total
Ttelmah
Guest







PostPosted: Mon Aug 14, 2006 4:15 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Aug 14, 2006 4:21 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Aug 14, 2006 4:46 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Aug 14, 2006 4:57 am     Reply with quote

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







PostPosted: Mon Aug 14, 2006 5:02 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Aug 14, 2006 5:13 am     Reply with quote

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







PostPosted: Mon Aug 14, 2006 8:07 am     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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