fprintfが余分な値を出力する理由

c file-io printf
fprintfが余分な値を出力する理由

プロトコルバッファの目的で、フィールド番号とワイヤタイプを含むタグをエンコードしたい。 私が今抱えている問題は、「タグ」の値が「8」未満の場合、fprintfが正しい値の隣に追加の値を書き込むことです。 i.e. 38の代わりに38c0を出力します3。 tagの値が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;
}

  1  0


ベストアンサー

 if (fieldnumber <16){

あるべき

if (*fieldnumber <16){

3


次の場所で `else`を使用して、コードを単純化できます。

//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;
...

これは一般的なイディオムであり、適切なときに使用する必要があります-今のように。 コードの読みやすさが向上します。

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

問題の説明

実際、「else if」チェーンを使用するとコードが修正されます。 最初の「if」は「* <フィールド番号>」を「<< =」演算子で変更するため、2番目の条件が評価されると、「*フィールド番号」は7ではなく56になり、

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

また、より多くの情報を印刷して実行されます。

「else if」チェーンは、1つの代替のみが実行されるようにすることでそれを解決します。

” ” ‘

あなたが持っているので:

unsigned rv = 0;

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

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

この `fprintf()`を実行する必要がありますが、2、3、4、5に等しい `rv`の次のものは実行しないでください。

2


タイトルとURLをコピーしました