我正在做一个简单的项目,以读取input.txt
文本文件并显示一些有关它的基本统计信息。该文件应该与公司大楼的入口有关。文件就是这样的:
1 ; Visitor ; 10 ; 19 ; 2
2 ; 1 ; Worker ; 8 ; 0
3 ; 2 ; Director ; 12 ; 19
4 ; 5 ; Worker ; 18 ; 22
5 ; Visitor ; 8 ; 0 ; 3
格式为= ID;同伴(如果有雇员);类型;入场时间;退出时间;服务(如果有访客)
我得到了正确读取文件的程序(我想),它正确读取了第一个工作程序,但是当到达第二个工作程序时,它读取了ID并突然以Segmentation fault (core dumped)
退出。
如果我不知道发生了什么,而其他具有相同错误的问题也无济于事,那么如果我有更多知识的人可以提供帮助,我将非常感激。
代码如下:
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef enum { false, true } bool;
char * removeSpaces(char *line) {
int counter = 0,i=0;
while (line[i]!='\0'){
if (line[i] == ' '){
i++;
} else{
line[counter] = line[i];
counter++;
i++;
}
}
return(line);
line[counter] = '\0';
}
int main (int argc, char *argv[]){
FILE * fp;
char * line = NULL;
char field[30];
size_t len = 0;
ssize_t read;
bool flag = false;
int i=0,j=0,k=0,counter=0; //variables to count on loops
fp = fopen("input.txt", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, fp)) != -1) {
printf("%s", line);
if(strstr(line, "Worker") != NULL) { //determine the entrance type
line = removeSpaces(line);
printf("\nWORKER READ\n");
i = 0;
while(line[i] != ';'){ //Read ID
field[i] = line[i]; //saves the content of the field (all between ';')
i++;
}
field[i] = '\0';
printf("\nID: ");
for(i=0;field[i] != '\0';i++){
printf("%c",field[i]);
}
//memset(field,0,strlen(field));
i = 0; j = 0;
while(flag != true){ //Read Companions
if(line[i] == ';'){
flag = true; //keeps skipping the string till it finds the right field
}
if(flag == true){
j = i+1;
while(line[j] != ';'){
field[k] = line[j]; //saves the content of the field (all between ';')
j++; k++;
}
}
i++;
}
field[k] = '\0';
printf("\nCOMPANIONS: ");
for(i=0;field[i] != '\0';i++){
printf("%c",field[i]); //prints what the number of companions read
}
//memset(field,0,strlen(field));
i = 0; j = 0; k = 0; flag = false;
while(flag != true){ //Read Type
if(line[i] == ';'){
counter++;
if(counter == 2){
flag = true; //keeps skipping the string till it finds the right field
}
}
if(flag == true){
j = i+1;
while(line[j] != ';'){
field[k] = line[j]; //saves the content of the field (all between ';')
j++; k++;
}
}
i++;
}
field[k] = '\0';
printf("\nTIPO: ");
for(i=0;field[i] != '\0';i++){
printf("%c",field[i]); /prints the type of entrance read
}
//memset(field,0,strlen(field));
i = 0; j = 0; k = 0; flag = false; counter = 0;
while(flag != true){ //Read Entrance Time
if(line[i] == ';'){
counter++;
if(counter == 3){
flag = true; //keeps skipping the string till it finds the right field
}
}
if(flag == true){
j = i+1;
while(line[j] != ';'){
field[k] = line[j]; //saves it
j++; k++;
}
}
i++;
}
field[k] = '\0';
printf("\nENTRANCE: ");
for(i=0;field[i] != '\0';i++){
printf("%c",field[i]);
}
i = 0; j = 0; k = 0; flag = false; counter = 0;
while(flag != true){ //Read Exit Time
if(line[i] == ';'){
counter++;
if(counter == 4){
flag = true;
}
}
if(flag == true){
j = i+1;
while(line[j] != ';'){
field[k] = line[j];
j++; k++;
}
}
i++;
}
field[k] = '\0';
printf("\nSAIDA: ");
for(i=0;field[i] != '\0';i++){
printf("%c",field[i]);
}
printf("\n\n");
i = 0; j = 0; k = 0; flag = false;
memset(field,0,strlen(field));
} else if(strstr(line, "Director") != NULL){
//TODO
} else if(strstr(line, "Visitor") != NULL){
//TODO
}
}
return 0;
}
答案 0 :(得分:1)
尽管我建议在编写复杂的解析代码时建议使用sscanf
或fscanf
,但对于您的编码技能来说,学习如何编写解析器也非常有用。在将代码调整为使用fgets
而不是getline
以便可以对其进行编译之后,在此循环中遇到了一个错误:
while ( flag != true )
{ //Read Type
if ( line[i] == ';' ) // <<<< Fault when i = 2488
{
counter++;
if ( counter == 2 )
{
flag = true; //keeps skipping the string till it finds the right field
}
}
if ( flag == true )
{
j = i + 1;
while ( line[j] != ';' )
{
field[k] = line[j]; //saves the content of the field (all between ';')
j++; k++;
}
}
i++;
}
您要在不参考实际行长的情况下递增i,因此在某些时候您正在访问一个您不拥有的内存地址。
编译代码时,应启用所有警告。您的编译器应警告您一些错误。您应该看到的重要内容之一是removeSpaces
函数中第27行的“ Unreachable code ...”:
return(line);
line[counter] = '\0'; // This never executed.
请参见http://pubs.opengroup.org/onlinepubs/009696699/functions/fgets.html
答案 1 :(得分:0)
sscanf
可用于解析line
中的值。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char *argv[]){
FILE * fp;
char * line = NULL;
char id[30];
char companions[30];
char type[30];
char entrance[30];
char depart[30];
size_t len = 0;
ssize_t read;
fp = fopen("input.txt", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, fp)) != -1) {
printf("%s", line);
if(strstr(line, "Worker") != NULL) { //determine the entrance type
printf("\nWORKER READ\n");
if ( 5 == sscanf ( line, "%29s ; %29s ; %29s ; %29s ; %29s"
, id, companions, type, entrance, depart)) {
printf("\nID: %s", id);
printf("\nCOMPANIONS: %s", companions);
printf("\nTIPO: %s", type);
printf("\nENTRANCE: %s", entrance);
printf("\nSAIDA: %s", depart);
printf("\n\n");
}
else {
printf ( "problem parsing Worker\n");
}
} else if(strstr(line, "Director") != NULL){
//TODO
} else if(strstr(line, "Visitor") != NULL){
//TODO
}
}
return 0;
}