4

マシン命令を実行できるように、テキスト ファイルから 16 進数を符号なし整数に読み込もうとしています。これは、テキスト ファイル内を調べ、値とそれに対応する命令に従って新しい値をレジスタに出力するシミュレーション タイプのものです。

たとえば、指示は次のようになります。

  • 1RXY -> メモリ アドレス XY の値でレジスタ R を保存
  • 2RXY -> レジスタ R を値 XY で保存
  • BRXY -> xy がこれとあれならレジスタ R にジャンプします。
  • ARXY -> レジスタ R とメモリアドレス XY の値の AND

テキストファイルには、次のようなものがそれぞれ新しい行に含まれています。(16 進数)

  • 120F
  • B007
  • 290B

私の問題は、個々の命令を符号なし整数にコピーすることです...どうすればよいですか?

#include <stdio.h>
int main(){
    FILE *f;
    unsigned int num[80];

    f=fopen("values.txt","r");
    if (f==NULL){
        printf("file doesnt exist?!");
    }

    int i=0;
    while (fscanf(f,"%x",num[i]) != EOF){
        fscanf(f,"%x",num[i]);
        i++;
    }
    fclose(f);
    printf("%x",num[0]);
}
4

5 に答える 5

7

あなたは正しい軌道に乗っています。私が見た問題は次のとおりです。

  • fopen()戻る場合は終了する必要がありNULLます-エラーメッセージを出力していますが、続行しています。
  • ループは ifi >= 80で終了する必要があるため、スペースよりも多くの整数を読み取ることはありません。
  • num[i]に値ではなくアドレスを渡す必要がありますfscanf
  • ループ内で 2 回呼び出しfscanf()ています。つまり、値を保存せずに半分を破棄しています。

これらの問題を修正すると、次のようになります。

#include <stdio.h>

int main() {
    FILE *f;
    unsigned int num[80];
    int i=0;
    int rv;
    int num_values;

    f=fopen("values.txt","r");
    if (f==NULL){
        printf("file doesnt exist?!\n");
        return 1;
    }

    while (i < 80) {
        rv = fscanf(f, "%x", &num[i]);

        if (rv != 1)
            break;

        i++;
    }
    fclose(f);
    num_values = i;

    if (i >= 80)
    {
        printf("Warning: Stopped reading input due to input too long.\n");
    }
    else if (rv != EOF)
    {
        printf("Warning: Stopped reading input due to bad value.\n");
    }
    else
    {
        printf("Reached end of input.\n");
    }

    printf("Successfully read %d values:\n", num_values);
    for (i = 0; i < num_values; i++)
    {
        printf("\t%x\n", num[i]);
    }

    return 0
}
于 2009-09-08T23:11:41.990 に答える
5

関数 strtol() を使用することもできます。基数 16 を使用すると、16 進文字列値が int/long に変換されます。

errno = 0;
my_int = strtol(my_str, NULL, 16);
/* check errno */

編集:もう1つの注意点として、さまざまな静的分析ツールがatoi()やscanf()などに安全ではないというフラグを立てる場合があります。atoi は、strtol() のようにエラーをチェックしないため、廃止されました。一方、scanf() は、scanf() に送信された型をチェックしないため、ある種のバッファ オーバーフローを行うことができます。たとえば、読み取り値が実際には long である scanf に short へのポインタを与えることができます....そしてブーム。

于 2009-09-08T23:15:15.120 に答える
2

この場合、小文字の hexを読み込もうとしている間、すべての入力は大文字のhexです。

それを修正するには、に変更%x%Xます。

于 2009-09-08T22:59:00.220 に答える
2

配列の各要素に 2 つの数値を読み込んでいます (そのため、上書きすると半分が失われます。

while (i < 80 && fscanf(f,"%x",&num[i]) != EOF)
    i++;

あなたのループのために

編集

また、配列要素のアドレスを取得するための「&」がないため、ランダムなガベージ ポインターを scanf に渡し、おそらくクラッシュします。-Wall オプションはあなたの味方です。

于 2009-09-08T23:01:06.223 に答える
0

各行 (それぞれ 4 文字の長さ) を 4 つの異なる配列要素に分割しますか? もしそうなら、私はこれを試します:

/* read the line */
/* fgets(buf, ...) */

/* check it's correct, mind the '\n' */
/* ... strlen ... isxdigit ... */

/* put each separate input digit in a separate array member */
num[i++] = convert_xdigit_to_int(buf[j++]);

関数 convert_xdigit_to_int() は、単純に '0' (文字) を 0 (int) に、'1' を 1 に、'2' を 2 に、... '9' を 9 に、'a' または 'A' に変換します。 10まで、...

もちろん、その疑似コードは、ファイルがなくなるか、配列がいっぱいになるまで実行されるループ内にあります。しばらくは fgets() を条件に入れるかも(...)

while(/*there is space in the array && */ fgets(...)) {
}
于 2009-09-08T23:10:06.580 に答える