我试图逐个读取文件中的整数,并将其作为一行读入程序中。列号。
我的文件内容是:
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),哎呀。
答案 0 :(得分:3)
第一列打印为(0, 0)
,因为atoi
失败。请不要使用atoi
,而应使用strtol
,这样您就可以检查转换是否成功。
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);
}
答案 1 :(得分:1)
由于您正在处理单个数字,因此您可以使用line[0]-'0'
将行[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);
}
使用此功能,您可以将行拆分为两个值作为行和列。
file1:
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
CODE:
#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)
答案 2 :(得分:0)
fgets()
会读取\n
字符
如果不是,则在下一次读取操作中将读取\n
。
由于您的呼叫是fgets(line, 2, fp);
,因此只读取1个字符,而第2个字符填充空字符。所以:line [0] =='3'和line [1] =='\ 0'。
行尾将在稍后阅读,因此while()
循环内的第一次阅读操作就是:"\n"
。这会产生atoi
的任意结果(在您的情况下为零)。
考虑到:
fgets(line,N,fp)从文件fp中读取stdin中最多N-1个字符, 包括\ n,如果可能的话。结果排成一列,总是如此 最后的房间为\ 0字符。