0

My microcontroller UART has a small buffer to process data, therefore i would like sent data in small chunks, in string format using sprintf. sample[k] = voltage sample not random number, and comma is required to separate voltages.

So I would like to fill up the sample array with random numbers, instead of if() else statement. How to make sprintf() use dynamic index ?

char str[512];
int sample[512];

printf("T1[");

int i = 0;
for (int j = 0; j < 64; j++)
{
    for(int k = 0; k < 8; k++)
    {
        sample[k] = rand() % 256;
    }

    sprintf( str, "%d,%d,%d,%d,%d,%d,%d,%d", sample[0],sample[1],sample[2],sample[3],sample[4],sample[5],sample[6],sample[7]);
    printf(str);
}

printf("]\r\n");

i could do something like this

if (j == 0)
sprintf( str, "%d,%d,%d,%d,%d,%d,%d,%d", sample[0],sample[1],sample[2],sample[3],sample[4],sample[5],sample[6],sample[7]);
if (j == 1)
sprintf( str, "%d,%d,%d,%d,%d,%d,%d,%d", sample[8],sample[9],...

I have tried:

sprintf( str, "%d,%d,%d,%d,%d,%d,%d,%d", sample[i++],sample[i++],sample[i++],sample[i++],sample[i++],sample[i++],sample[i++],sample[i++]);
User6996
  • 2,953
  • 11
  • 44
  • 66
  • 3
    So much undefined behavior, so little time. – WhozCraig Sep 19 '13 at 20:43
  • Who's telling you you have to print *all eight* entries per line *at once* ? The `sprintf()` is entirely unneeded for this to output what you're apparently trying to do. (64 rows of 8 random numbers between 0..255 in each row, separated by commas). And do you realize you never populate more than the first 8 entries in the `sample[]` array? Did you *try* to debug this ? – WhozCraig Sep 19 '13 at 20:53
  • Im sorry but i don't get it – User6996 Sep 19 '13 at 20:53
  • Not a duplicate, but worth reading for the shared issue: http://stackoverflow.com/questions/376278/parameter-evaluation-order-before-a-function-calling-in-c – Chris Stratton Sep 19 '13 at 20:55
  • microcontroller UART has a small buffer to process data, therefore i would like sent data in small chunks, in string format using sprintf. – User6996 Sep 19 '13 at 21:01
  • sample[k] = voltage sample not random number – User6996 Sep 19 '13 at 21:02
  • and comma is required to separate voltages – User6996 Sep 19 '13 at 21:05

2 Answers2

1

Unfortunately,

sprintf( str, "%d,%d,%d,%d,%d,%d,%d,%d", sample[i++],sample[i++],sample[i++],
           sample[i++],sample[i++],sample[i++],sample[i++],sample[i++]);

won't work; since the order in which function arguments are evaluated is unspecified, it's not guaranteed that each sample[i++] will be evaluated from left to right, nor is it guaranteed that the side effect of ++ is applied immediately after each i++ is evaluated. The behavior of this code is undefined, meaning the result is not predictable.

Unfortunately, there's no good way to do what you're asking within a single sprintf call. You will either have to specify each index explicitly, as you do in

sprintf( str, "%d,%d,%d,%d,%d,%d,%d,%d", sample[0],sample[1],sample[2],sample[3],
           sample[4],sample[5],sample[6],sample[7]);

or you'll have to write something different, like

strcpy( str, "" );
for ( size_t i = 0; i < 8; i++ )
{
  char tmp[4] = {0};
  char *empty = "";
  char *comma = ",";
  char *sep = empty;

  sprintf( tmp, "%s%d", sep, samples[i] );
  strcat( str, tmp );
  sep = comma;
}

Yuck, I know. Frankly, you're better off just specifying each index manually in a single sprintf call.

Serves me right for not paying better attention. If you just need to print a row of 8 samples to standard output at a time, this will be much simpler:

for ( j = 0; j < 64; j++ )
{
  printf( "%d", samples[ j * 8 ] );

  for ( k = 1; k < 8; k ++ )
  {
    printf( ",%d", sep, samples[ j * 8 + k ] );
  }
  putchar( '\n' );
}        

Edit

for ( j = 0; j < 63; j++ )
{
    sprintf( str, "%d,%d,%d,%d,%d,%d,%d,%d,", 
      samples[ j * 8 ],     samples[ j * 8 + 1 ], samples[ j * 8 + 2 ],
      samples[ j * 8 + 3 ], samples[ j * 8 + 4 ], samples[ j * 8 + 5 ],
      samples[ j * 8 + 6 ], samples[ j * 8 + 7 ] );

    // send str
}        

sprintf( str, "%d,%d,%d,%d,%d,%d,%d,%d", 
  samples[ j * 8 ],     samples[ j * 8 + 1 ], samples[ j * 8 + 2 ],
  samples[ j * 8 + 3 ], samples[ j * 8 + 4 ], samples[ j * 8 + 5 ],
  samples[ j * 8 + 6 ], samples[ j * 8 + 7 ] );

// send str

Special case for the last row, since I'm assuming you don't want a trailing comma after the last sample.

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • no i don't wanna just print, i need to buffer, and then print out in small chunks – User6996 Sep 19 '13 at 21:19
  • @Power-Mosfet Since you are using printf() to send the strings, why do you need sprintf()? If you are using something else to send them, you can put one value into the buffer at a time, send it, then put in the next one - that will take *less* memory than your type of approach anyway. – Chris Stratton Sep 19 '13 at 21:37
  • i dont use printf, i only use it to test the function other windows application. – User6996 Sep 19 '13 at 21:41
  • Thank you for the input, but it still returns the sample results as sample[i++] – User6996 Sep 19 '13 at 22:18
  • @Power-Mosfet: Not sure I understand your point; you want to print 8 samples to the string at a time, right? I explained why using consecutive `sample[i++]` expressions wouldn't work. You asked how to make `sprintf` use a dynamic index; well, this is how. – John Bode Sep 19 '13 at 22:27
  • Yes you do understand my point. I have tried your code and it return negative values – User6996 Sep 20 '13 at 09:14
  • Are you still actually filling the samples with random data anywhere? – Chris Stratton Sep 21 '13 at 15:31
0

You may find it much easier to send the data one piece at a time; this will actually take less memory. For example

char str[10]; //FIXME verify this is enough for longest possible case
int samples[256];

//fill random data here

for (i = 0; i< 256; i++) {
    sprintf(str, "%d, ", samples[i]);  //could use snprintf for more safety
    #ifdef WINDOWS
      printf(str);
    #else
      UART_SEND_STRING(str);
    #endif
}
Chris Stratton
  • 39,853
  • 6
  • 84
  • 117