开发者

Why does fprintf print extra values

I want to encode tags that will contain a field number and a wire type for the purpose of protocol buffers. The problem that I am having now is that whenever my value for 'tag' is below '8' fprintf writes additional values next to the correct ones. i.e. instead of 38 it prints 38c0 3. If the value of tag is 8 or higher the script works fine. Below is the code with irrelavent lines omitted.

int uint32_pack (uint8_t *fieldnumber, uint32_t value, uint8_t *out);

int main(){

uint32_t initvalue = 2;
int return_rv;
uint8_t *tag = (uint8_t *) malloc(sizeof(uint8_t));    
uint8_t *tempout= (uint8_t *) malloc(sizeof(uint32_t));
*tag = 7; //value to be encoded (won't work for values less than 8)

return_rv = uint32_pack (tag, initvalue, tempout);

free(tempout);

    }

/* === pack() === */
/* Pack an unsigned 32-bit integer in base-128 encoding, and return the number
 of bytes needed: this will be 5 or less. */

int uint32_pack (uint8_t *fieldnumber, uint32_t value, uint8_t *out)
{
  unsigned rv = 0;
  FILE *wiretypetag;
  int secondaryvalue;

  wiretypetag = fopen("wiretype.txt","w");


    //encodes wire type and the field number
    if (*fieldnumber <16){
       *fieldnumber <<= 3;
       fprintf(wiretypetag,"%x",fieldnumber[0]);
       }
    if (*fieldnumber < 32 && *fieldnumber > 15){
       *fieldnumber <<= 3;
       secondaryvalue = 0x01;
       fprintf(wiretypetag,"%x %x",fieldnumber[0],secondaryvalue);
           }
    if (*fieldnumber < 48 && *fieldnumber > 31){
        *fieldnumber += 0x10;
        *fieldnumber &= 0x1F;
        *fieldnumber <<= 3;
        secondaryvalue = 0x02;
        fprintf(wiretypetag,"%x %x",fieldnumber[0], secondaryvalue);
        }       
    if (*fieldnumber < 64 && *fieldnumber > 47){
        *fieldnumber &= 0x开发者_开发问答1F;
        *fieldnumber <<= 3;
        secondaryvalue = 0x03;
        fprintf(wiretypetag,"%x %x",fieldnumber[0], secondaryvalue);
        }       

  /* assert: value<128 */   
    out[rv++] = value;


    if (rv == 1){         
           fprintf(outfile,"%x",out[0]);
           }
    if (rv == 2){
           fprintf(outfile,"%x %x",out[0], out[1]);
           }    
    if (rv == 3){
           fprintf(outfile,"%x %x %x",out[0],out[1],out[2]);
           }
    if (rv == 4){
           fprintf(outfile,"%x %x %x %x",out[0],out[1],out[2],out[3]);
           }
    if (rv == 5){
           fprintf(outfile,"%x %x %x %x %x",out[0],out[1],out[2],out[3],out[4]);
           }

    fclose(wiretypetag);

    return rv;
}


 if (fieldnumber <16){

should be

if (*fieldnumber <16){


You can simplify the code by using else at:

//encodes wire type and the field number
if (*fieldnumber <16){
   *fieldnumber <<= 3;
   fprintf(wiretypetag,"%d",fieldnumber[0]);
   }
if (*fieldnumber < 32 && *fieldnumber > 15){
   *fieldnumber <<= 3;

Replace with:

//encodes wire type and the field number
if (*fieldnumber < 16) {
   *fieldnumber <<= 3;
   fprintf(wiretypetag, "%d", fieldnumber[0]);
   }
else if (*fieldnumber < 32) {
   *fieldnumber <<= 3;
...

This is a common idiom and one you should use when appropriate - as now. It will improve the legibility of the code.

That may not be the whole problem; it probably isn't.

Explanation of Problem

In fact, using an else if chain corrects the code. Because the first if modifies *fieldnumber with the <<= operator, when the second condition is evaluated, *fieldnumber is no longer 7 but 56, so the condition for

if (*fieldnumber < 64 && *fieldnumber > 47){

is also executed, printing out more information.

The else if chain will resolve that by ensuring that only one alternative is executed.


Since you have:

unsigned rv = 0;

[...]
/* assert: value<128 */   
out[rv++] = value;

if (rv == 1){         
       fprintf(outfile,"%x",out[0]);
       }

This fprintf() should be executed, but the following ones for rv equal to 2, 3, 4, 5 should never be executed.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜