2

我正在尝试从文件中一一读取整数,并将其作为行号和列号读入程序。

我的文件内容是:

3
2 1
2 2
2 3

我的代码:

fgets(line, 2, fp);
livecells = atoi(line);
fprintf(stderr, "\n%i live cells\n", livecells);    

while ( !feof(fp) ) 
{
  fgets(line, 5, fp);

  alive_row = atoi(&line[0]);
  alive_column = atoi(&line[2]);

  fprintf(stderr, "\n Cell: (%i)(%i)", alive_row, alive_column);       
}

其中line是存储fgets内容的字符数组(字符串),alive_row和alive_column是整数。

但由于某种原因,输出是:

3 live cells

 Cell: (0)(0)
 Cell: (2)(1)
 Cell: (2)(2)
 Cell: (2)(3)
 Cell: (2)(3)

问题是,为什么第一个单元格会打印出 (0)(0)?我不知道为什么要打印出来......如果它很明显很抱歉......

编辑:很明显,最后重复的单元格 (2)(3),哎呀。

4

3 回答 3

3

第一列打印为(0, 0),因为atoi失败。请不要使用atoi,而是使用strtolwhich 将使您能够检查转换是否成功。

失败的原因atoi是因为你有一个额外的\n字符,因为fgets(fgets(line, 2, fp);你只读取一个字符 - 因为你传递了 2 作为缓冲区大小,并且缓冲区的 1 个元素是为\0字符保留的。只需使用足够大的缓冲区来读取整行,并在那里传递缓冲区的大小。

为了修复其他错误,请不要使用feof. 而是检查fgets返回值以查看它从文件中读取了多少个字符(或者,如果您真的想feof在调用后进行检查fgets)。

while (  fgets(line, sizeof(line), fp) > 0) 
{
  char* end;

  alive_row = strtol(&line[0], &end, 10);

  // If the end points to the &line[0], then no 
  // characters were converted!     
  if(end == &line[0])
  {
      printf("strtol failed!\n");
      return 0;
  }

  alive_column = strtol(&line[2], &end, 10);

  // If the end points to the &line[2], then no 
  // characters were converted!     
  if(end == &line[2])
  {
      printf("strtol failed!\n");
      return 0;
  }

  fprintf(stderr, "\n Cell: (%i)(%i)", alive_row, alive_column);       
}

我们有一个检查&line[0] == end,因为传递给的第二个参数strtol

引用 char* 类型的对象,其值由函数设置为 str 中数值之后的下一个字符。

如果字符串中没有数值,此指针将指向您尝试转换的字符串的开头。

如果您不知道位数是 1 还是 2 或任何位数,您仍然可以strtol在这里帮助您:

while (  fgets(line, sizeof(line), fp) > 0) 
{
  char* end;
  char* tmp;

  alive_row = strtol(&line[0], &end, 10);

  // If the end points to the &line[0], then no 
  // characters were converted!     
  if(end == &line[0])
  {
      printf("strtol failed!\n");
      return 0;
  }

  // If the previous strtol converted the first number
  // end will point to the space character (the first character after the number).
  // So, just pass
  // end + 1 which should point to the second number
  tmp = end + 1;
  alive_column = strtol(tmp, &end, 10);

  // If the end points to the tmp, then no 
  // characters were converted!     
  // (this is why we used this tmp to place end + 1 - we need to 
  //  check for the success of the strtol).
  if(end == tmp)
  {
      printf("strtol failed!\n");
      return 0;
  }

  fprintf(stderr, "\n Cell: (%i)(%i)", alive_row, alive_column);       
}
于 2013-09-14T10:06:41.007 回答
1

由于您正在处理 j 个单个数字,因此您只需line[0]-'0' 将 line[0] 转换为整数。第一次扫描时只需扫描 5 个字节,以便文件流移动到下一行。

   #include<stdio.h>

    int main()
    {

    FILE *fp;
    int alive_row;
    int alive_column,livecells;


    char line[10];
    fp=fopen("file1","r");
    fgets(line,5 , fp);
    livecells = line[0]-'0';
    fprintf(stderr, "\n %i live cells\n", livecells);

    while ( fgets(line, 5, fp)!=NULL)
    {
    //  puts(line);
      alive_row = line[0]-'0';
      alive_column = line[2]-'0';

      fprintf(stderr,"\n Cell: (%i)(%i)\n", alive_row, alive_column);
    }
    fclose(fp);
    }

有了这个,您可以将行拆分为两个值,即行和列。

文件1:

12
2 1
2 2
2 3
50 5
30 20
5 30
30 330
3390 447
12 1234
0 0
1234 1
154 0 

代码:

#include<stdio.h>
#include<string.h>

int main()
{

    FILE *fp;
    int alive_row=0;    
    int alive_column=0,livecells;
    int column=0,i;

    char line[10];
    fp=fopen("file1","r");
    fgets(line,5, fp);       //read first line
    livecells = atoi(line); //convert into int
    fprintf(stderr, "\n %i live cells\n", livecells);

    while ( fgets(line, 12, fp)!=NULL)      //read next lines
        {
        for(i=0;i<strlen(line)-1;i++)      //loop to separate rows and columns , here if space occurs make flag column as 1
            {
            if(line[i]!=' ' && column!=1 )     
            alive_row = 10*alive_row+line[i]-'0'; //convert into integers
            else
                {
                if(line[i]==' ')
                i=i+1;
                alive_column=10*alive_column+line[i]-'0';
                column=1; //you can write this statement just above if but you need to add two brace 
                }
            }

        printf(" Cell:(%d)(%d)\n\n", alive_row, alive_column);
        alive_row=0;   //after every iteration just make these value to default. 
        alive_column=0;
        column=0;
        }
    fclose(fp);
}

输出

 12 live cells

 Cell:(2)(1)

 Cell:(2)(2)

 Cell:(2)(3)

 Cell:(50)(5)

 Cell:(30)(20)

 Cell:(5)(30)

 Cell:(30)(330)

 Cell:(3390)(447)

 Cell:(12)(1234)

 Cell:(0)(0)

 Cell:(1234)(1)

 Cell:(154)(0)
于 2013-09-14T10:13:12.640 回答
0

fgets()如果可能,读取\n字符。
如果不是,\n将在下一次读取操作中读取。

由于您的电话是fgets(line, 2, fp);,因此只读取了 1 个字符,而第 2 个字符则填充了空字符。所以:line[0] == '3' 和 line[1] == '\0'。

行尾将在稍后读取,因此while()循环内的第一个读取操作就是这样"\n":这会产生任意结果atoi(在您的情况下为零)。

考虑到:

fgets(line, N, fp) 从文件 fp 中读取最多 N - 1 个来自标准输入的字符,包括 \n,如果可能的话。结果排成一行,并且总是在最后为 \0 字符腾出空间。

于 2013-09-14T10:04:36.993 回答