3

fscanf() を使用して、txt ファイルからパラメーターを入力しようとしています。これが私のコードです:

fpin = fopen("parameter_file.txt","r");
fscanf(fpin,"%d\n", &code_value);
fscanf(fpin,"%d\n", &origin_x);
fscanf(fpin,"%d\n", &origin_y);
fscanf(fpin,"%d\n", &dpi);
fscanf(fpin,"%d\n", &width);
fscanf(fpin,"%d\n", &height);

そして、parameter_file.txt は (たとえば):

333 
123 
123 
800
6
8

各行の後に注釈を追加したい。例: 333 //code_valueまたは123 //origin_x私の問題は、いくつかの文字を追加すると、fscanf()が機能せず、継続パラメーターを読みたいと思ったことです。

私が試してみましたfscanf(fpin,"%[^a-z]%d\n", &code_value);

もう 1 つの問題は、入力ファイルが次のようになっている場合、私のコードはどのように実現できるのでしょうか?

333 //code_value_1
123 //origin_x_1
123 //origin_y_1
800 //dpi_1
6 //width_1
8 //height_1
12 // code_value_2
10 //origin_x_2
20 //origin_y_2
800 //dpi_2
10 //width_2
10 //height_2
.
.
.
20 // code_value_n
10 //origin_x_n
20 //origin_y_n
800 //dpi_n
30 //width_n
30 //height_n
4

1 に答える 1

5

形式が常に 1 行に 1 つの数値である場合は、次を使用できます。

fscanf(fpin, "%d%*[^\n]", &var);

%*[^\n]、改行文字までのすべての文字を飲み込みます。は*抑制であり、^\n改行文字を除くすべての文字がスキャン セットの一部であることを意味します。

ただし、数値の直後に改行がある場合、これは古いスタイルの入力では失敗します。sscanf()より堅牢な方法は、最初に行全体をバッファーに読み込み、次にorを使用してバッファーを解析することstrtol()です。

char buf[MAX_LINE_LENGTH];

if (fgets(buf, sizeof(buf), fpin) != 0) {
    if (sscanf(buf, "%d", &var) == 1) {
        /* ... */
    } else {
        /* ...handle parse error */
    }
} else {
    /* ...handle file read error */
}

getline()C++ では、 と を使用して同様に実行できますistringstream

std::string line;
std::istringstream iss;

if (std::getline(std::cin, line)) {
    iss.str(line);
    if (iss >> var) {
        //...
    } else {
        //...handle scan error
    }
} else {
    //...handle read error
}

コメントでは、次のように尋ねます。

すべてのcinを異なるパラメータに割り当てる方法は?

各コメントが値の意味を説明している場合、 を使用しmap<string, int>て名前と値の関連付けを作成できます。コメントは通常の形式に従っていないため、解析には注意が必要です。

C バージョンでは、配列を使用して関連付けを格納します。その後、( を使用して) ソートqsort()し、ルックアップを実行する必要があるときに ( を使用して) 二分探索を実行できますbsearch()

struct value_item {
    char name[MAX_NAME_SIZE];
    int value;
};

struct value_item value_map[MAX_VALUE_MAP];
size_t value_map_size = 0;

while (fgets(buf, sizeof(buf), fpin) != 0) {
    const char *slash2 = strstr(buf, "//");
    if (slash2 && slash2[2] != '\0') {
        sscanf(buf, "%d", &value_map[value_map_size].value);
        sscanf(slash2+2, "%s", value_map[value_map_size].name);
        ++value_map_size;
    } else {
        /* ...handle parse error */
    }
}

C++ バージョンも同様です。C++ にはmap、関連付けを簡単に作成するために使用できる が用意されています。

std::map<std::string, int> value_map;

while (std::getline(std::cin, line)) {
    std::string::size_type n = line.find("//");
    if (n != std::string::npos && line.size() > (n+2)) {
        int value;
        std::string name;
        iss.str(line);
        iss >> value;
        iss.str(line.substr(n+2));
        iss >> name;
        value_map[name] = value;
    } else {
        //...handle parse error
    }
 }

私はこれを頭の上から書いているので、エラーやより良い方法があるかもしれません. しかし、これで一般的なアイデアが得られるはずです。

于 2013-07-20T03:39:22.470 に答える