Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
逐行读取文件并在C中使用strtok()_C_Strtok - Fatal编程技术网

逐行读取文件并在C中使用strtok()

逐行读取文件并在C中使用strtok(),c,strtok,C,Strtok,我试图逐行读取配置文件,然后标记并将结果存储到单独的变量中。我的配置文件如下所示 stage 1 num_nodes 2 nonce 234567 我需要分别标记行中的每个值,例如,在第一行“stage”中,用于检查我是否已从配置文件中读取stage值,然后将其值保存在变量中。我的标记化似乎工作正常。然而,当我尝试在标记化后操作变量时,它会给我一个分段错误。最多我只能成功地操作其中一个变量,即stage或num_节点或nonce,但不能操作它们的组合。即使试着做一些像 stage = stag

我试图逐行读取配置文件,然后标记并将结果存储到单独的变量中。我的配置文件如下所示

stage 1
num_nodes 2
nonce 234567
我需要分别标记行中的每个值,例如,在第一行“stage”中,用于检查我是否已从配置文件中读取stage值,然后将其值保存在变量中。我的标记化似乎工作正常。然而,当我尝试在标记化后操作变量时,它会给我一个分段错误。最多我只能成功地操作其中一个变量,即stage或num_节点或nonce,但不能操作它们的组合。即使试着做一些像

stage = stage + 1;
num_nodes = num_nodes + 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);
*/
}
您的代码包含:

token1 = strtok(str, " ");

if (strcmp(token2, "num_nodes") == 0){
    num_nodes = atoi(token1); 
    printf("num_nodes = %d\n", num_nodes);
}
您刚刚设置了
token1
,但继续比较
token2
?这可能会导致核心转储,至少在第一次到从未设置
token2
时是如此

最后,在循环结束后,出现核心转储的唯一原因是您在分配的内存边界之外到处践踏。原因目前还不清楚,但循环结构……奇怪,我们可以说

这是一个清理过的,没有崩溃的版本。您的原始版本还不错,但是
token2
的不确定状态令人担忧。一个版本的输出包含以下信息:

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
此代码使用命令行在Mac OS X 10.8.5和GCC 4.8.1上干净地编译:

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
请输入配置文件名
您输入了config.file
这是bufr:#评论
这是bufr:
这是bufr:第一阶段
标记1=;令牌2=
标记1=;令牌2=
阶段=1
这是bufr:num_节点2
标记1=;令牌2=
标记1=;令牌2=
节点数=2
我是bufr:nonce 234567
标记1=;令牌2=
标记1=;令牌2=
nonce=234567
这是bufr:
阶段=1
nonce=234569
节点=3
您的代码包含:

token1 = strtok(str, " ");

if (strcmp(token2, "num_nodes") == 0){
    num_nodes = atoi(token1); 
    printf("num_nodes = %d\n", num_nodes);
}
您刚刚设置了
token1
,但继续比较
token2
?这可能会导致核心转储,至少在第一次到从未设置
token2
时是如此

最后,在循环结束后,出现核心转储的唯一原因是您在分配的内存边界之外到处践踏。原因目前还不清楚,但循环结构……奇怪,我们可以说

这是一个清理过的,没有崩溃的版本。您的原始版本还不错,但是
token2
的不确定状态令人担忧。一个版本的输出包含以下信息:

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
此代码使用命令行在Mac OS X 10.8.5和GCC 4.8.1上干净地编译:

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
请输入配置文件名
您输入了config.file
这是bufr:#评论
这是bufr:
这是bufr:第一阶段
标记1=;令牌2=
标记1=;令牌2=
阶段=1
这是bufr:num_节点2
标记1=;令牌2=
标记1=;令牌2=
节点数=2
我是bufr:nonce 234567
标记1=;令牌2=
标记1=;令牌2=
nonce=234567
这是bufr:
阶段=1
nonce=234569
节点=3

都德,您可以使用libconfig读取配置文件。使用libconfig实现这一点比编写算法更容易

这里您可以看到一个示例:


都德,您可以使用libconfig读取配置文件。使用libconfig实现这一点比编写算法更容易

这里您可以看到一个示例:


关于循环结构,您是对的,它不是最干净的,但在for循环的一次迭代后,我复制了一个token1,即token2=token1,然后在第二次迭代中使用它来检查上一次迭代中读取的令牌,并相应地更新变量。我担心的是第一次迭代,当
token2
未设置时。我正在探索代码;我只想说,目前,我得到的版本工作起来没有太多麻烦-但我在去任何地方之前设置了
token2=“”
(访问未初始化的变量会导致灾难)。同意你的观点,你做到了。只做了token2=“”,分割错误就消失了。不知道到底是什么原因造成的,除了非初始化之外,您还有其他想法吗?您使用的是准随机(或至少是不确定)内存位置执行strcmp()。如果记忆是可读的,它本不应该造成太大的伤害,但你正在如履薄冰。当我使用我的答案中显示的选项编译您的原始代码时,我收到了如下警告:
cfg.c:69:11:警告:此函数中未初始化的情况下可能会使用“stage”[-Wmaybe uninitialized]
printf(“stage=%d\n”,stage)
cfg.c:35:27:警告:此函数中可能未初始化就使用了“令牌2”[-Wmaybe uninitialized]
位于
if(strcmp(令牌2,“num_节点”)==0){
。我修正了这些。你对循环结构的看法是正确的,它不是最干净的,但在for循环的一次迭代后,我复制了一个token1,即token2=token1,然后在第二次迭代中使用它来检查上一次迭代中读取的令牌,并相应地更新变量。我担心的是第一次迭代,当
token2
未设置时。我正在探索代码;可以说,目前,我得到的版本工作起来没有太多麻烦-但我在去任何地方之前设置了
token2=“”
(访问未初始化的变量是一个灾难的秘诀)。同意你的观点,你做到了。刚才doken2=“”