我对C还是很陌生,所以请原谅这个愚蠢的问题。我有以下这段代码从文本文件中读取第三行,即数字38。我将其分配给while循环内的int,但是,当在while循环外访问此变量时,会得到不同的结果。这是我的代码:
int main() {
FILE* file = fopen("blocks.txt", "r");
char line[256];
int number;
int i = 0;
while (fgets(line, sizeof(line), file)) {
i++;
if (i == 3)
{
number = line;
//prints 38
printf("%s", line);
}
}
//prints something random!
printf("%d", number);
fclose(file);
getchar();
return 0;
}
对不起,如果它含糊,可能会被删除,但是请给我一些帮助哈哈!
答案 0 :(得分:2)
即使在第一次打印后,您的while循环仍保持运行。 char
数组line
在gets(line, sizeof(line), file)
行中不断更新。
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *file = fopen("blocks.txt", "r");
char line[256];
long int number;
int i = 0;
char *stopped;
/*keeps updating line till fget returns a failed response*/
while (fgets(line, sizeof(line), file))
{
i++;
if (i == 3)
{
number = (int)strtol(line, &stopped, 10);
if (!*stopped)
{ /* handle error */
printf("Error in strtol\n");
return -1;
}
//prints 38
printf("%s", line);
}
}
/*Once the while loop ends it will have the last
line of the file block.txt*/
printf("%ld", number);
fclose(file);
getchar();
return 0;
}
atoi的洞穴
我们本可以使用 atoi 。但是atoi
是不安全的,并且可能导致许多粗心的错误。参见link。您应该使用strtol
将字符串转换为long int
。
答案 1 :(得分:1)
您的困惑来自循环内打印line
,然后尝试在循环后打印number
。 line
的类型为char[256]
,访问时将转换为简单的char*
。 number
的类型为int
。您无法将char*
分配给int
。
为了将line
中的ASCII数字转换为整数number
,可以使用sscanf
(在此情况下适当),也可以使用strtol
(或可以手动进行模和除法转换。
在这里,您可以使用面向行输入功能fgets
正确读取一行输入(很好)。您只需要将line
中的ASCII数字转换为整数。您可以使用sscanf
来做到这一点,例如:
while (fgets(line, sizeof(line), file)) {
i++;
if (i == 3) {
if (sscanf (line, "%d", &number) != 1) {
fputs ("error: no integer at start of line 3\n", stderr);
return 1;
}
printf ("number inside loop : %d\n", number);
break; /* no reason to read further */
}
}
(注意:通过将返回值与请求的转换次数进行比较,以sscanf
来验证转换-验证每次读取或转换)
注意,请勿硬编码文件名或数字。 main()
接受参数,argc
保留存在的参数计数(始终至少有1
个参数,即可执行文件的名称),而argv
是您的参数向量(指向每个参数的指针数组,最后一个参数之后的下一个指针设置为NULL
。)将文件名作为参数传递给程序。您还可以有条件地将程序设置为从作为第一个参数提供的文件名中读取,或者如果没有提供参数,则默认情况下从stdin
中读取。
完全将其放入,您可以这样做:
#include <stdio.h>
int main (int argc, char **argv) {
/* read from file given as 1st argument (stdin by default) */
FILE* file = argc > 1 ? fopen (argv[1], "r") : stdin;
char line[256];
int number = 0, /* initialize number - what if you have a 2-line file */
i = 0;
while (fgets(line, sizeof(line), file)) {
i++;
if (i == 3) {
if (sscanf (line, "%d", &number) != 1) {
fputs ("error: no integer at start of line 3\n", stderr);
return 1;
}
printf ("number inside loop : %d\n", number);
break; /* no reason to read further */
}
}
fclose(file); /* close file - read operations done */
if (i == 3) /* validate 3 lines read from file */
printf ("number outside loop: %d\n", number);
else
fputs ("error: less than 3-lines in file.\n", stderr);
getchar();
return 0;
}
示例输入文件
$ cat dat/3line.txt
10
20
38
40
使用/输出示例
$ ./bin/readline3 dat/3line.txt
number inside loop : 38
number outside loop: 38
仔细检查一下,如果还有其他问题,请告诉我。
答案 2 :(得分:0)
在C中,变量的类型很重要。 line
的类型为char[256]
,表示它是256个字符的数组,在这种情况下,足以容纳行的长度。
但是,number
是int
。 C努力以合理的方式转换类型,但是它对“合理”的定义不是您自己的。它将在内存中找到line
的地址存储到number
中。然后,在while循环内的printf
中,告诉它使用"%s"
进行打印,意思是“将其当作内存中一堆字符的地址进行处理”,事实证明是这样,这样就可以了。
在while循环之外,您使用"%d"
,它表示“将其打印为数字”。从技术上讲,它是一个数字,但不是38。这个数字对您没有意义,即使对于C语言专家也不是那么重要。
要解决此问题,您需要将字符串实际转换为数字(如果您想对它进行数学运算),或者只是将其存储为文本,不要假装它是数字。要将其转换为数字,请使用atoi()
。
您应该在编译器上启用警告,以便它会告诉您将来是否要进行此类操作。根据您的编译方式,您可以在IDE中更改某些设置(例如Visual Studio或Eclipse),也可以在编译器命令行中添加一些内容,例如使用gcc -Wall -Wextra -pedantic
而不只是gcc