This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Problem on using %x for sprintf( )

Hi, Everybody,
Is there anyone have the same problems while using %x as the output type for sprintf()? The outputs have the following sequences...
0 1 2 3 4 5 6 7 8 9 @ a b c d e
But it should be...
0 1 2 3 4 5 6 7 8 9 a b c d e f

Codes:

    for(i=0;i<16;i++) {
        sprintf(Buf,"%x",(int)i);//%X has the same problem.
    }

Note: My target links c51s.lib. I have download 7.20 version.

Parents
  • I tried the following in V7.20.

    #include <stdio.h>
    #include <string.h>
    
    xdata char buf [100] = "";
    xdata char buf2 [100] = "";
    
    void main (void)
    {
    unsigned char i;
    
    for (i = 0; i < 16; i++)
      {
      sprintf (buf, "%x", (int) i);
      strcat(buf2,buf);
      strcat(buf2," ");
      }
    
    while(1);

    After running this example, buf2 contained "0 1 2 3 4 5 6 7 8 9 a b c d e f " as I expected. Maybe something is corrupting your output?

    Jon

Reply
  • I tried the following in V7.20.

    #include <stdio.h>
    #include <string.h>
    
    xdata char buf [100] = "";
    xdata char buf2 [100] = "";
    
    void main (void)
    {
    unsigned char i;
    
    for (i = 0; i < 16; i++)
      {
      sprintf (buf, "%x", (int) i);
      strcat(buf2,buf);
      strcat(buf2," ");
      }
    
    while(1);

    After running this example, buf2 contained "0 1 2 3 4 5 6 7 8 9 a b c d e f " as I expected. Maybe something is corrupting your output?

    Jon

Children
  • Here is my test...

    void puts (void *p)
    {
        unsigned char *pb=(unsigned char *)p;
        while(*pb) {
            TI=0;
            SBUF0=*pb;
            ++pb;
            while(!TI);
        }
    }
    
    void test (void)
    {
        char i,xdata BufA[50],BufB[50];
        char xdata *p1=BufA,*p2=BufB;
        for(i=0;i<16;i++) {
            p1+=sprintf(p1,"%d,",(int)i);
            p2+=sprintf(p2,"%x,",(int)i);
        }
        p1=p2=0;
        puts(BufA);
        puts(BufB);
    }
    

    I capture the output from HyperTerminal...
    0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7,8,9,@,a,b,c,d,e,

    Am I do anything wrong?

  • "Am I do anything wrong?"

    You're overflowing BufA[] for a start.

  • Here are a few notes.

    1. I compiled your example. The compiler complained about redefining puts (so I called my copy my_puts). This may be causing problems.

    2. What I compiled and tested worked just fine.

    3. You didn't include a complete working example (it compiled with errors and the serial port is not configured). So, I can't really debug those things for you. I added those things in my test.

    4. Your treatment of the TI flag in the puts function is not ideal. You should really check if TI is set at the beginning of the loop rather than at the end. Checking at the end consumes time unnecessarily. That time could be spent executing other code.

    5. You don't specify a type for BufA and BufB. The compiler assumes int. You probably meant char.

    6. p1=p2=0; I assume this is supposed to null-terminate the strings. It doesn't. For that you'll need *p1='\0'; *p2='\0';

    7. Overall, for what it does, the code snippet you have uses a lot of variables. If you are just learning C, this is OK. But, they are not required.

    Following is my example that works OK.

    #include <reg51.h>
    #include <stdio.h>
    
    
    void my_puts (char *p)
    {
    for (; *p; p++)
      {
      while (TI == 0);
      SBUF = *p;
      TI = 0;
      }
    }
    
    xdata char BufA[50];
    xdata char BufB[50];
    
    
    void main (void)
    {
    char i;
    char xdata *p1=BufA,*p2=BufB;
    
    SCON  = 0x50;		        /* SCON: mode 1, 8-bit UART, enable rcvr      */
    TMOD |= 0x20;               /* TMOD: timer 1, mode 2, 8-bit reload        */
    TH1   = 221;                /* TH1:  reload value for 1200 baud @ 16MHz   */
    TR1   = 1;                  /* TR1:  timer 1 run                          */
    TI    = 1;                  /* TI:   set TI to send first char of UART    */
    
    for(i = 0; i < 16; i++)
      {
      p1 += sprintf(p1, "%d,", (int)i);
      p2 += sprintf(p2, "%x,", (int)i);
      }
    
    *p1='\0';
    *p2='\0';
    
    my_puts(BufA);
    my_puts(BufB);
    
    while (1);
    }
    

    Jon

  • "You're overflowing BufA[] for a start."

    Sorry! I thought there was a space after the %d, in your sprintf(). There isn't.

  • "You don't specify a type for BufA and BufB."

    I'm seeing things that aren't there, you're missing things that are!

  • "You don't specify a type for BufA and BufB."

    I'm seeing things that aren't there, you're missing things that are!


    Yep. I'm recovering from a 23-hour plane ride. Sorry for that.

    Jon

  • Thanks for all of your kindly reply.
    Please see the example again...

    #pragma disable
    void my_puts (void *p)
    {
        unsigned char *pb=(unsigned char *)p;
        while(*pb) {
            TI=0;
            SBUF0=*pb;
            ++pb;
            while(!TI);
        }
    }
    
    void test (void)
    {
        char xdata BufA[30];
        int x=0xABC;//2748.
        sprintf(BufA,"0xABC:%x,%X,%u:0xabc\r",x,x,x); my_puts(BufA);
        sprintf(BufA,"%d,%d,%d,%x\r",(int)(x>>8),(int)(x>>4&0xF),(int)(x&0xF),x); my_puts(BufA);
        for(;;);
    }
    

    The result from HyperTerminal are (I can see the output, so my setting/initialize should be correct) ...
    0xABC:@ab,@AB,2748:0xabc
    10,11,12,@ab

    The problem is still on %x, sprintf() seems to shift one ASCII value for hex format?

  • I think you need to post the smallest complete, compilable program that exhibits the problem.