1

次の形式のテキスト ファイルをバイナリに変換する必要があります。

最初の行には、在庫にある製品の数が含まれます。次の行には次のものが含まれます:
製品名'\t'製品価格'\t'数量'\n' (列間に複数の \t が存在する可能性があります)

すべての製品について、バイナリ出力ファイルには、製品名の長さを表す int、製品名を保持する文字、価格を表す int、および数量を表す int が含まれます。

サンプル入力ファイル:

Asus Zenbook    1000    10
iPhone 5        750     22
Playstation 4   1000    0

私は次のコードを書きましたが、文字列をプレーンテキストで表示することになっていることを理解しましたが、整数は意味不明 (バイナリ) として表示されます。

int convertTextToBinary(char *fileName)
{
    FILE *pText, *pBinary;

    int size, i;

    char *currProdName;
    int currProdNameLen, currQuantity, currPrice;

    if (checkFileExists(fileName) == FALSE)
    {
        printf("- Given file does not exists!\n");
        return ERROR;
    }

    else
        pText = fopen(fileName, "r");

    // get the number of products in the inventory
    fscanf(pText, "%d", &size);
    #ifdef DBG
    printf("##DBG Successfuly read &size = %d DBG##\n", size);
    #endif  
    pBinary = fopen(strcat(fileName, ".bin"), "wb");

    fwrite(&size, sizeof(int), 1, pBinary);
    #ifdef DBG
    printf("##DBG Successfuly wrote &size = %d DBG##\n", size);
    #endif  
    for (i = 0; i < size; i++)
    {
        // get product name and name length
        currProdNameLen = getProdName(pText, &currProdName);
        #ifdef DBG
        printf("##DBG %d Successfuly read &currProdName = %s DBG##\n", i+1, currProdName);
        printf("##DBG %d Successfuly read &currProdNameLen = %d DBG##\n", i+1, currProdNameLen);
        #endif          
        // get product price 
        fscanf(pText, "%d", &currPrice);
        printf("##DBG %d Successfuly read &currPrice = %d DBG##\n", i+1, currPrice);
        // get product quantity
        fscanf(pText, "%d", &currQuantity);
        printf("##DBG %d Successfuly read &currQuantity = %d DBG##\n", i+1, currQuantity);
        // write data to binary file
        fwrite(&currProdNameLen , sizeof(int), 1, pBinary);
        fwrite(&currProdName, sizeof(char), currProdNameLen, pBinary);
        fwrite(&currPrice, sizeof(int), 1, pBinary);
        fwrite(&currQuantity, sizeof(int), 1, pBinary);
        free(currProdName);
    }

    fclose(pText);
    fclose(pBinary);
    return 1;
}

/* This function checks if a file in a given path exists or not by using fopen with "read" argument */
BOOL checkFileExists(char *fileName)
{
    FILE *fp;

    fp = fopen(fileName, "r");

    // file does not exists
    if (fp == NULL)
        return FALSE;

    // file does exists
    else
    {
        fclose(fp);
        return TRUE;
    }
}
int getProdName(FILE *fp, char **prodName)
{
    int nameLen = 0, offset;

    // count the length of the product name
    while (fgetc(fp) != '\t')
        nameLen++;

    // allcoate memory for the product name
    *prodName = (char*)malloc(sizeof(char)*nameLen);
    //checkalloc(&prodName);

    // get the cursor back to the original position
    offset = -1 * nameLen;
    fseek(fp, offset, SEEK_CUR);

    // copy product name from text to string
    fgets(*prodName, nameLen, fp);

    return strlen(*prodName);
}

しかし、地獄、私の出力ファイルは次のようになります。

       ¨ ּּּּּט        ¨ ּּּ¯        ¨ ּּּּּּּּ   ּּּ«
        ¨      

これはプレーンテキストを保持しません。fopen 引数を「wb」から「w」に変更しようとしましたが、まだ意味不明なファイルが表示されます。私は何を間違っていますか?

4

1 に答える 1

1

ここでは、ポインターが指す文字列の代わりに、ポインターと追加のガベージを記述します。

    fwrite(&currProdName, sizeof(char), currProdNameLen, pBinary);

以下を使用する必要があります。

    fwrite(currProdName, sizeof(char), currProdNameLen, pBinary);

あなたのバージョンでは、ポインターをポインターに渡していますが、ポインター自体を渡したいと考えています。

ところで:関数では、正確な文字列の長さを割り当てているが、最後にバイトgetProdName()の余地がないため、追加の文字を追加する必要があります。0これも問題を引き起こす可能性があります。またfgets、1 文字少なく読み取ります。のマニュアルページを確認してくださいfgets。を使う代わりに、とにかく長さがわかるので をfgets使うこともできます。fread追加の解析は必要ありません。

アップデート

これを変える:

    fscanf(pText, "%d", &currQuantity);

    fscanf(pText, "%d\n", &currQuantity);
于 2013-08-18T20:12:29.457 に答える