0

構成ファイルを1行ずつ読み取ってから、結果をトークン化して別の変数に保存しようとしています。私の設定ファイルは次のようになります

stage 1
num_nodes 2
nonce 234567

行の各値を個別にトークン化する必要があるため、たとえば、最初の行の「ステージ」では、構成ファイルからステージ値を読み取ったかどうかを確認し、その値を変数に保存します。私のトークン化は正しく機能しているようです。ただし、トークン化後に変数を操作しようとすると、セグメンテーション違反が発生します。せいぜい変数の 1 つ、つまり stage または num_nodes または nonce のいずれかを正常に操作できますが、それらの組み合わせは操作できません。みたいなことをしようとしても

stage = stage + 1;
num_nodes = num_nodes + 1;

ただし、次のように 1 つの変数だけを変更すると、セグメンテーション エラーが発生します。

num_nodes = num_nodes + 1;

その後、正常に動作します。以下のコードを貼り付けています。ここで何が欠けているか教えてください。

main(int argc, char *argv[]){
  int nonce;
  int num_nodes;
  int stage; 
  char filename[256];   
  char *token1, *token2, *str;  
  FILE* fp;
  char bufr[MAXLINE];  

  printf("Please enter config file name\n");
  scanf("%s",filename);
  printf("You entered %s\n", filename);

  if((fp = fopen(filename, "r")) != NULL){

        while(fgets(bufr, MAXLINE, fp) != NULL){
            if(bufr[0] == '#') // to skip comments
                continue;

            printf("This is bufr: %s",  bufr);
            str = bufr;

              for(str;  ;str = NULL){
                token1 = strtok(str, " ");

                if(strcmp(token2, "num_nodes") == 0){
                    num_nodes = atoi(token1); 
                    printf("num_nodes = %d\n", num_nodes);
                }

                if(strcmp(token2, "nonce") == 0){
                    nonce = atoi(token1);
                    printf("nonce = %d\n", nonce);
                }       

                if(strcmp(token2, "stage") == 0){
                    stage = atoi(token1);
                    printf("stage = %d\n", stage);
                }                   

                token2 = token1; // making a copy of pointer

                if(str == NULL){
                    break;
                }
          }//end of for loop

        }//end of while loop
        fclose(fp); //close the file handle
    }
    else{
        printf("failed, file not found!\n");
    }

/*      This is where the segmentation fault kicks in, try to uncomment two lines and it will give a segmentation fault, if uncomment just one, then it works fine.
    nonce = nonce + 2;  
    num_nodes = num_nodes + 1;
    printf("stage = %d\n", stage);
*/
}
4

2 に答える 2

2

あなたのコードには以下が含まれています:

token1 = strtok(str, " ");

if (strcmp(token2, "num_nodes") == 0){
    num_nodes = atoi(token1); 
    printf("num_nodes = %d\n", num_nodes);
}

を設定しましtoken1たが、比較に進みますtoken2か? これにより、少なくとも初回token2から設定されていない場合は、コア ダンプが発生する可能性があります。

最後に、ループの後、コア ダンプが発生する唯一の理由は、割り当てられたメモリの範囲外を踏みにじったことです。理由はすぐにはわかりませんが、ループ構造は…興味深いですね。

これは、コードのクリーンアップされた、クラッシュしないバージョンです。あなたのオリジナルは悪くありませんでしたが、不確定なステータスtoken2が心配でした。出力の 1 つのバージョンには、次のような情報が含まれていました。

Please enter config file name
You entered config.file
This is bufr: # Comment
This is bufr: 
This is bufr: stage 1
token1 = <<stage>>; token2 = <<>>
token1 = <<1
>>; token2 = <<stage>>
stage = 1
This is bufr: num_nodes 2
token1 = <<num_nodes>>; token2 = <<des>>
token1 = <<2
>>; token2 = <<num_nodes>>
num_nodes = 2
This is bufr: nonce 234567
token1 = <<nonce>>; token2 = <<67
>>
token1 = <<234567
>>; token2 = <<nonce>>
nonce = 234567
This is bufr: 
stage = 1

の残骸に注目してくださいtoken2。以下のコードでそれをさらにクリーンアップしました。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum { MAXLINE = 4096 };

int main(void)
{
    int nonce = -1;
    int num_nodes = -1;
    int stage = -1;
    char filename[256];
    char *token1, *token2, *str;
    FILE *fp;
    char bufr[MAXLINE];

    printf("Please enter config file name\n");
    scanf("%s", filename);
    printf("You entered %s\n", filename);

    if ((fp = fopen(filename, "r")) == NULL)
    {
        printf("failed, file not found!\n");
        return(1);
    }

    while (fgets(bufr, MAXLINE, fp) != NULL)
    {
        printf("This is bufr: %s", bufr);
        if (bufr[0] == '#' || bufr[0] == '\n')
            continue;

        token2 = "";
        for (str = bufr; (token1 = strtok(str, " \n\t")) != 0; str = NULL)
        {
            printf("token1 = <<%s>>; token2 = <<%s>>\n", token1, token2);
            if (strcmp(token2, "num_nodes") == 0) {
                num_nodes = atoi(token1);
                printf("num_nodes = %d\n", num_nodes);
            }
            if (strcmp(token2, "nonce") == 0) {
                nonce = atoi(token1);
                printf("nonce = %d\n", nonce);
            }
            if (strcmp(token2, "stage") == 0) {
                stage = atoi(token1);
                printf("stage = %d\n", stage);
            }

            token2 = token1;

            if (str == NULL)    /* Terminate after name/value */
                break;
        }

    }
    fclose(fp);

    nonce = nonce + 2;
    num_nodes = num_nodes + 1;
    printf("stage = %d\n", stage);
    printf("nonce = %d\n", nonce);
    printf("nodes = %d\n", num_nodes);

    return(0);
}

このコードは、コマンド ラインを使用して GCC 4.8.1 を使用する Mac OS X 10.8.5 で正常にコンパイルされます。

gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition cfg.c -o cfg

という入力ファイルがあるとしますconfig.file

# Comment

stage 1
num_nodes 2
nonce 234567
 

(最後に空白行があります)、出力は次のとおりです。

Please enter config file name
You entered config.file
This is bufr: # Comment
This is bufr: 
This is bufr: stage 1
token1 = <<stage>>; token2 = <<>>
token1 = <<1>>; token2 = <<stage>>
stage = 1
This is bufr: num_nodes 2
token1 = <<num_nodes>>; token2 = <<>>
token1 = <<2>>; token2 = <<num_nodes>>
num_nodes = 2
This is bufr: nonce 234567
token1 = <<nonce>>; token2 = <<>>
token1 = <<234567>>; token2 = <<nonce>>
nonce = 234567
This is bufr: 
stage = 1
nonce = 234569
nodes = 3
于 2013-09-22T01:40:24.940 に答える
1

おい、libconfigを使用して構成ファイルを読み取ることができます。これを行うアルゴリズムを作成するよりも、libconfig を使用してこれを行う方が簡単です。

http://www.hyperrealm.com/libconfig/

以下に例を示します。

http://simplestcodings.blogspot.com.br/2012/02/libconfig-to-read-configuration-files.html

于 2013-09-22T01:42:35.223 に答える