我正在尝试逐行读取配置文件,然后将结果标记化并将结果存储到单独的变量中。我的配置文件如下所示
stage 1
num_nodes 2
nonce 234567
我需要分别对行中的每个值进行标记,因此例如在第一行“stage”中用于检查我是否从配置文件中读取了阶段值,然后将其值保存在变量中。我的令牌化似乎是正确的。但是,当我在标记化后尝试操纵变量时,它会给我一个分段错误。最多我可以成功地操作其中一个变量,即stage或num_nodes或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);
*/
}
答案 0 :(得分: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
的不确定状态令人担忧。输出的一个版本包括如下信息:
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);
}
此代码使用命令行在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
答案 1 :(得分:1)
老兄,您可以使用libconfig来读取配置文件。使用libconfig比使用算法执行此操作更容易。
http://www.hyperrealm.com/libconfig/
在这里你可以看到一个例子:
http://simplestcodings.blogspot.com.br/2012/02/libconfig-to-read-configuration-files.html