Hi Dave, > So I was using sprintf to create some data to send to the LCD, by way of > lcd_puts. > I had a pair of arrays, A_String[17], and B_String[17] which I filled > using two loops. > > I hit some problems when I tried to consolidate this into one loop. > The symptom was that the second string wouldn't display, but it would if I > had the two routines in separate loops. > I'm creating a simple bar graph, Data_A and Data_B have some value that is > roughly between 0 and 16* the Step value. > > for (i=0; i<16; i++) > { > if ((Step * i) < Data_A) { > sprintf((A_String+i), "%c", 0xFF); > } else { > sprintf((A_String+i), "%c", 0x20); > } > if ((Step * i) < Data_B) { > sprintf((B_String+i), "%c", 0xFF); > } else { > sprintf((B_String+i), "%c", 0x20); > } > }
Wow - using sprintf to write single character values is an awfully expensive way of doing things. I would have coded: for (i=0; i<16; i++) { if ((Step * i) < Data_A) { A_String[i] = 0xFF; } else { A_String[i] = 0x20; } if ((Step * i) < Data_B) { B_String[i] = 0xFF; } else { B_string[i] = 0x20; } } A_String[16] = 0; B_String[16] = 0; > > lcd_home(); > lcd_gotoxy(0,0); > lcd_puts(A_String); // String must be null terminated. > lcd_gotoxy(0,1); > lcd_puts(B_String); > In the above implementation, B_String would not show up on the display, but > A_String would.. > > Below is the version that worked, the only difference is that the A string > is completed before starting on the B string. > > for (i=0; i<16; i++) > { > if ((Step * i) < Data_A) { > sprintf((A_String+i), "%c", 0xFF); > } else { > sprintf((A_String+i), "%c", 0x20); > } > > for (i=0; i<16; i++) > { > if ((Step * i) < Data_B) { > sprintf((B_String+i), "%c", 0xFF); > } else { > sprintf((B_String+i), "%c", 0x20); > } > } > > It turned out that I had neglected to allow for the terminating null in the > strings, but this raises two questions for me. > > 1: Why doesn't sprintf((A_String+16), "%c", 0x00); drop a null into the last > element of A_String. This will actually drop two characters. The null character for the %c and a terminating null character. sprintf( foo, "%c", 'A' ); will write the A followed by a null character. So each time through the loop you're actually writing two characters. As you discovered the arrays need to be sized appropriately to deal with this. > 2: Why does the separate loops case work at all? It probably depends. The order of A_String and B_String relative to each other and the exact size probably makes a difference. If you only declared A_String as a 16 element array and you did sprintf( A_String + 15, "%c", 0x20 ); then this will write the 0x20 to A_String[15] and 0x00 to A_String[16], which will trample the byte beyond the end of A_String, which might have been the beginning of B_String. So if you looped writing A_String first, it would trample B_String, but the second loop writing B_String would have fixed B_String[0] back up. Then you amalgamated the loops, A_String[16] was trampled after B_String[0] was written, so things didin't get corrected. > I solved my problem by inserting the null with > memset((A_String+16), 0, 1); and the same for B_String. A_String[16] = 0; would be a much more efficient way of performing the same operation. -- Dave Hylands Shuswap, BC, Canada http://www.DaveHylands.com/ _______________________________________________ AVR-GCC-list mailing list AVR-GCC-list@nongnu.org http://lists.nongnu.org/mailman/listinfo/avr-gcc-list