我正在尝试从usb-devices获取输出并解析它以将其分配给一个简单的结构。但是,我只是无法让fscanf正确读取输出中的值。这是有问题的功能:
struct Devices* getDevices() {
int pipes[2];
pid_t pid;
if (pipe(pipes)==-1)
die("Failed to create pipe");
if ((pid = fork()) == -1)
die("Could not fork process");
if(pid == 0) {
dup2 (pipes[1], STDOUT_FILENO);
close(pipes[0]);
close(pipes[1]);
execl("/bin/usb-devices", "usb-devices", (char *)0);
}
else {
close(pipes[1]);
wait(NULL);
}
FILE *rawList = fdopen(pipes[0],"r");
if (rawList == NULL)
die("Failed to open file");
fpos_t pos;
int pos_init = 0;
struct Devices *deviceList = malloc(sizeof(struct Devices));
if(!deviceList) die ("Memory error");
int i;
int conn;
int iBus = -1;
int iPort = -1;
for (i = 0; !feof(rawList); i++) {
if (pos_init) fsetpos(rawList, &pos);
conn = fscanf(rawList, "T: Bus=%d Lev=%*d Prnt=%*d Port=%d Cnt=%*d Dev#= %*d Spd=%*d MxCh= %*d",
&iBus, &iPort);
if (!conn) {
printf("bus%d port%d num %i", iBus, iPort, i);
deviceList->devNum[i].set = 1;
deviceList->devNum[i].bus = iBus;
deviceList->devNum[i].port = iPort;
fgetpos (rawList,&pos);
pos_init = 1;
}
}
fclose(rawList);
return deviceList;
}
快速解释应该发生的事情。我正在创建一个管道,所以我可以抓取我正在运行的命令的输出,然后在它运行后我尝试将它放在一个名为rawList的流中通过fdopen。然后,我为结构我malloc一块内存,我将分配我得到的值。
然后,在for循环中,它应检查以“T:”开头的行,其中包含我想要的数据,然后它应该采用usb-devices的输出给我的整数并将其分配给struct每台设备。最后,它应该保存它停止读取的点,以便它可以继续从那里读取以找到我正在寻找的下一行。
printf在那里试图弄清楚发生了什么。它最终打印“-1”,这是在for循环之前分配的值,这告诉我fscanf没有为我的变量赋值。 “我”只是指望程序段错误并最终退出。我不确定该值是否有意义,但Valgrind一直告诉我5个上下文中有77408个错误(main只是运行这个函数,代码中唯一的其他东西是struct声明,die函数和main本身)
当这个过程终于退出时,Valgrind给了我这个:
==11278== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==11278== Access not within mapped region at address 0x55F0040
==11278== at 0x108C7A: getDevices (usbDeviceList.c:77)
==11278== by 0x108D4C: main (usbDeviceList.c:103)
第77行就是这个
deviceList->devNum[i].set = 1;
打印的“i”的最后一个值是15644。
任何和所有帮助都表示赞赏,我已经四处询问,似乎没有人知道发生了什么。我将列出我用来写这篇文章的SO资源:
easy way to parse a text file?
更新
根据要求,这是结构:
struct deviceData {
int set;
int bus;
int port;
char manufacturer[MAX_LENGTH_U];
char product[MAX_LENGTH_U];
};
struct Devices {
struct deviceData devNum[MAX_DEVICES_U];
};
答案 0 :(得分:0)
fscanf()
实际上有效时,您的代码不会发出任何输出。每the fscanf()
documentation:
返回值
成功完成后,这些功能将返回数字 成功匹配并分配输入项目。 ...
这个循环错了:
for (i = 0; !feof(rawList); i++) {
if (pos_init) fsetpos(rawList, &pos);
// if this works, it returns 2
conn = fscanf(rawList, "T: Bus=%d Lev=%*d Prnt=%*d Port=%d Cnt=%*d Dev#= %*d Spd=%*d MxCh= %*d",
&iBus, &iPort);
if (!conn) {
// these only get called if conn is zero!
printf("bus%d port%d num %i", iBus, iPort, i);
deviceList->devNum[i].set = 1;
deviceList->devNum[i].bus = iBus;
deviceList->devNum[i].port = iPort;
fgetpos (rawList,&pos);
pos_init = 1;
}
}
正如评论中所指出的,管道上的fsetpos()
是无用的。