Почему fprintf выводит дополнительные значения - PullRequest
1 голос
/ 22 июля 2011

Я хочу закодировать теги, которые будут содержать номер поля и тип провода для буферов протокола. Проблема, с которой я сталкиваюсь сейчас, заключается в том, что всякий раз, когда мое значение для тега ниже 8, fprintf записывает дополнительные значения рядом с правильными. то есть вместо 38 он печатает 38c0 3. Если значение тега равно 8 или выше, скрипт работает нормально. Ниже приведен код без опущенных строк.

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 &= 0x1F;
        *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;
}

Ответы [ 2 ]

3 голосов
/ 22 июля 2011
 if (fieldnumber <16){

должно быть

if (*fieldnumber <16){
2 голосов
/ 22 июля 2011

Вы можете упростить код, используя 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;

Заменить на:

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

Это распространенная идиома, которую следует использовать при необходимости - каксейчас.Это улучшит удобочитаемость кода.

Возможно, это не вся проблема;вероятно, это не так.

Объяснение проблемы

Фактически, использование цепочки else if исправляет код.Поскольку первый if изменяет *fieldnumber с помощью оператора <<=, при оценке второго условия *fieldnumber больше не 7, а 56, поэтому также выполняется условие для

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

, распечатывая дополнительную информацию.

Цепочка else if решит эту проблему, обеспечив выполнение только одной альтернативы.


Поскольку у вас есть:

unsigned rv = 0;

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

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

Это fprintf() должно быть выполнено, но следующие для rv, равного 2, 3, 4, 5, никогда не должны выполняться.

...