【问题标题】:fgets hangs in while loopfgets 挂在 while 循环中
【发布时间】:2013-10-14 20:07:30
【问题描述】:

已解决:在打开 qfile 之前关闭 infile 时已修复。

我正在尝试在 c 中处理两个文件。对于我在行中读取的第一个文件,然后处理字符串。我正在使用 fgets,但是当 while 循环处于最后一次迭代中时,它就会挂起。我有:

//Not complete code. While loop is all that is in method that uses the file. 
//File I/O error checking is in place, does not assume there is always a file in argv[2]
FILE *infile;
FILE *qfile;

struct tree{
    char *name;
    char *id;
    char *permission;
    struct tree *next;
 };
 struct tree *root;
 struct tree *current;

int main(int argc, char *argv[]){
 //proper file i/o error checking in place 
  infile = fopen(argv[1], "r");
  if(infile != NULL)
     fill();//process first file
   qfile = fopen(argv[2], "r");
   if(qfile != NULL)
      find();//process second file
   }

void fill(void){
   char buffer[256];
   int first = 1;
   while(fgets(buffer,sizeof(buffer),infile) != NULL)
   {
      if(first && buffer[0] == "X")
      {
         root = (struct tree *)malloc(sizeof(struct tree));
         current = root;
         process(buffer, current);
         first = 0;
      }
      else if(buffer[0] == 'F')//siblings
      {
         current->next = (struct tree *)malloc(sizeof(struct tree));
         current = current->next;
         process(buffer, current);
      }
}

void process(char buffer[], struct tree *current)
{
    char *left;
    char *right;
    left = buffer;
    right = buffer;
    while(*left == 'F')
    {
            left++;
    }
    while(*right != ':')
    {
            right++;/*
            if(*right == ' ')
                    continue;*/

    }

    //assign name to current node
    current->name = (char *)malloc(sizeof(char)*(right-left));
    strncpy(current->name, left, right-left);
    left = right + 1;
    while(*right != '=')
    {
            right++;
    }

    //assign property to current node
    current->property = (char *)malloc(sizeof(char)*(right-left));
    strncpy(current->property, left, right-left);

    left = right + 1;
    while(oright != '\n')
    t = (struct tree *)malloc(sizeof(struct tree));
                    current = root;
                    process(buffer, current);
                    //root->name = buffer;

                    first = 0;
            }
            else if(buffer[0] == 'F')//siblings
            {
                    current->next = (struct tree *)malloc(sizeof(struct tree));
                    current = current->next;
                    process(buffer, current);

    {       right++;}

    //assign value to current node
    current->value = (char *)malloc(sizeof(char)*(right-left));
    strncpy(current->value, left, right-left);
    printf("Name =%s\nProperty=%s\nValue=%s\n", current->name,current->property,current->value);
    }

它遍历整个文件,然后挂在 while 循环中。这仅处理第一个文件。当我不包含第二个文件(进程标准输入)时,它不会挂起。当它挂起时,它会检查所有条件并在循环底部停止。文件的最后一行本身就是一个换行符。

什么可能导致循环挂起?使用 64 位 linux。

编辑:适当的文件 I/O 检查到位。不完整的代码,因为我将问题缩小到填充()中的 while 循环。 fill() 只处理第一个文件。第二个文件由 find() 处理,另一种方法。问题仅与第一个文件有关。第一个文件只在 fill() 中使用。

EDIT2:贴出完整代码,打印语句用于跟踪。 很抱歉给大家带来了困惑。

【问题讨论】:

  • infile(文件指针)在发布的代码中未初始化
  • 它 (fgets) 只有在等待输入时才应该“挂起”。如果此输入来自交互式 STDIN/终端,请确保 关闭流 - 例如从终端输入数据时按 ^D(这会发送 EOF)。如果没有 EOF,steam 只会等待更多输入。
  • 输入来自文件,抱歉忘记包含在上面的代码中,但 infile 已初始化。
  • 我已经从标题中删除了“[已解决]”。表明您的问题已解决的方法是接受答案。如果现有答案都不能解决问题,请发布您自己的答案并接受它。

标签: c fgets


【解决方案1】:

首先总是检查 I/O

首先检查您的程序是否有足够数量的参数,因为您使用了argv[1] 然后检查你是否成功打开了文件

例如

if ( --argc )
{
  infile = fopen(argv[1], "r");
  if ( infile != NULL )
  {
    // do your fgets stuff
    fclose(infile);
  }
}

【讨论】:

  • I/O 错误检查到位。不想包含长代码。抱歉,如果最好的话,我可以粘贴整个代码。认为问题来自哪里的 sn-ps 就足够了,但我应该提到这一点。感谢您的回答。
【解决方案2】:

OP 使用fill(),在infile = fopen(argv[1], "r");qfile = fopen(argv[2], "r"); 之后都读取infile

OP 需要将流指针传递给fill() 函数。

OP 也调用find() 而不是预期的fill()。这是发帖时的错字还是问题?

int main(int argc, char *argv[]){
  FILE *infile;
  FILE *qfile;
 //proper file i/o error checking in place 
  infile = fopen(argv[1], "r");
  if(infile != NULL)
     fill(infile);//process first file
  FILE *qfile;
  qfile = fopen(argv[2], "r");
  if(qfile != NULL)
    fill(qfile);//process second file
  }
}

void fill(FILE *f){
   char buffer[256];
   while((fgets(buffer,sizeof(buffer),f)) != NULL)
   {
      if(first time && line isn't empty or newline)initialize struct;
      else if(not first time && line isn't empty or newline)connect structs;
   }
}

【讨论】:

  • infile 和 qfile 都在全局范围内,因为 main 执行对 infile 和 qfile 的第一次更改(包括文件打开)由于全局范围而被传递给其他函数。还是我完全不在基地?
  • @LHBD,当你使用qfile = fopen(argv[2], "r"); if(qfile != NULL) find();时,fill()怎么知道使用qfile而不是再次使用infile
  • fill() 仅使用 infile。 find() 只使用 qfile。每个函数运行一次。每个文本文件只处理一次。
  • @LHBD,文件名是什么?
  • @LHBD 怀疑我们需要看到真正的fill()
【解决方案3】:

在 main 中打开第二个文件之前关闭第一个文件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-06
    • 2021-12-31
    • 2022-01-26
    • 1970-01-01
    相关资源
    最近更新 更多