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 CCS Technical Support

Problem w. built-in function toupper (convert to uppercase)

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



Joined: 24 Mar 2006
Posts: 1

View user's profile Send private message

Problem w. built-in function toupper (convert to uppercase)
PostPosted: Fri Mar 24, 2006 11:21 am     Reply with quote

Hi,
Does anyone know why the line
strnew[i]=toupper(*ptr);
does not work? It works in every ANSI C-Compiler but not with the CCS-Compiler. Its a simple task converting a char to uppercase.
I have found the work around you can see below, but i would like to know why the specific line does not work.
This is only a code fragment - all pointers and variables are set correctly!
Thx for any answer.
Quinni

char c;
char * ptr;


This does NOT Work

strnew[i]=toupper(*ptr); // this line does not work as i expect
//convert to uppercase and store it in a new string

This Code works:
c=*ptr; //first store dereferenced pointer to c
strnew[i]=toupper(c); //convert c to uppercase and store it in new string
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message Visit poster's website

PostPosted: Fri Mar 24, 2006 12:39 pm     Reply with quote

..

Last edited by treitmey on Fri Mar 24, 2006 4:05 pm; edited 1 time in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Mar 24, 2006 2:51 pm     Reply with quote

It looks like the problem occurs when the result from toupper()
is assigned to an array with a variable index. Look at the test
program shown below. It produces the results shown below. It's only
incorrect in the 2nd test. I tested this with PCM vs. 3.248 and 3.449.
Code:

first result = 41

2nd result = 61    <-- incorrect

3rd result = 41

(Values are in Hex)


Code:

#include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

//============================
void main()
{
char *ptr;
char c;
char string[10] = {"a"};
char strnew[10];
int8 i;

ptr = string;
c = toupper(*ptr);
printf("first result = %x \n\r", c);

i = 0;
ptr = string;
strnew[i] = toupper(*ptr);
printf("2nd result = %x \n\r", strnew[0]);

ptr = string;
strnew[0] = toupper(*ptr);
printf("3rd result = %x \n\r", strnew[0]);

while(1);
}

=======================

I don't have time to investigate this right now. I've got to
do some work at the company. But as a work-around you can
use the following replacement function for toupper(). I tested
it with the program above and it always works.
Code:

char my_toupper(char c)
{
if(c >= 'a' && c <= 'z')
   c -= 0x20;
return(c);
}
Ttelmah
Guest







PostPosted: Sat Mar 25, 2006 9:02 am     Reply with quote

Yes, it a definite bug.
If you look at the assembler generated, in the specific case of using a pointer reference on both sides of the equation (remember in C an array, and pointer are just two different constructs giving the same result), with a variable index on the left side, the code generates:
Code:

.................... strnew[i] = (toupper(*ptr));
00BE:  MOVLW  2D
00BF:  ADDWF  37,W
00C0:  MOVWF  38
00C1:  MOVF   21,W
00C2:  MOVWF  04
00C3:  MOVF   00,W
00C4:  MOVWF  39
00C5:  SUBLW  60
00C6:  BTFSC  03.0
00C7:  GOTO   0CF
00C8:  MOVF   39,W
00C9:  SUBLW  7A
00CA:  BTFSS  03.0
00CB:  GOTO   0CF
00CC:  MOVF   39,W
00CD:  ANDLW  DF   //Correctly generates result
00CE:  GOTO   0CF
00CF:  MOVF   38,W  //Uurgh, W is now destroyed
00D0:  MOVWF  04
00D1:  MOVF   39,W //Retreive the original value...
00D2:  MOVWF  00   //and save this.

I'd report this, but in the meantime, probably use:
Code:

#define toupper(x) ((x)>='a' && (x)<='z')?(x&0xDF):(x)

Which has the advantage of 'overwriting' the existing declaration, without having to change the rest of the code (though produces slightly bulkier code).

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