我编写了一个采用以下概念的程序:
我创建了一个整数x
传递给函数的地址和一个文件名,所述函数打开文件(如果可用),扫描第一行并设置pX
指向的值等于扫描线。
只有它不起作用,我不知道自己做错了什么。据我所知,下面的代码通常是如何实现它的,但我不确定我是否没有正确地使用scanf()
指针或什么。
void foo() {
char input[20] = "test.txt";
int x = 1;
bar(input, &x);
}
void bar(char *fileName, int *pX) {
FILE *fp = fopen(fileName, "r");
char *buffer = malloc(15 * sizeof(int));
fgets(buffer, 15, fp);
scanf(buffer, "%d", *pX);
free(buffer);
fclose(fp);
}
答案 0 :(得分:2)
更改行:
scanf(buffer, "%d", *pX);
到:
sscanf(buffer, "%d", pX);
您需要使用sscanf函数来完成您的工作。
scanf
和sscanf
都将指针作为参数。 pX
的类型为int *
,因此指向int
的指针应该适合您。您传递的内容*pX
是此指针的内容,换句话说是int
。
另外,更改行:
char *buffer = malloc(15 * sizeof(int));
到:
char *buffer = malloc(15 * sizeof(char));
或简单地说:
char *buffer = malloc(15);
if (buffer == NULL){
...
}
答案 1 :(得分:1)
首先,C中没有pass-by-reference,函数参数都是按值传递的。通过传递指向数据的指针,我们模拟实现与引用传递相同的效果,但这并不意味着C具有任何传递参考概念。
那说,问题似乎是
scanf(buffer, "%d", *pX);
^^^^
其中
当前语法无效并调用undefined behavior。可能你需要sscanf()
。
px
已经是指向int
的指针。传递px
将是正确和足够的。
故事的道德:启用编译器警告并注意它们。他们是有原因的。启用适当的警告后,您应该看到类似
的内容警告:格式
%d
需要int *
类型的参数,但参数3的类型为int
[-Wformat=
]
最后,
fopen()
的返回值是否成功。scanf()
的返回值以确保扫描成功。fgets()
的返回值以确保成功...基本上,检查所有库调用的返回值,以确保它们按预期工作。
答案 2 :(得分:1)
您错误地使用scanf()
:直接使用scanf
解析标准输入或使用sscanf()
解析fgets()
读取的字符串。此外,pX
已经是指向int
的指针,sscanf()
期望存储它转换的int
值,直接传递它:sscanf(buffer, "%d", pX);
以下是修改后的版本:
int bar(const char *fileName, int *pX) {
char buffer[15];
FILE *fp = fopen(fileName, "r");
int success = 0;
if (fp != NULL) {
fgets(buffer, sizeof buffer, fp);
if (sscanf(buffer, "%d", pX) == 1)
success = 1;
fclose(fp);
}
return success;
}
void foo(void) {
int x = 1;
bar("test.txt", &x);
/* do something with x */
}
注意:
buf
是不必要的,只需将其设置为具有自动存储功能的本地阵列即可。 char *buffer = malloc(15 * sizeof(int));
不正确:您为15 int
而不是15个字符分配空间,根据定义,这些字符的大小为1。使用目标类型的大小以避免任何不一致:
char *buffer = malloc(15 * sizeof(*buffer));
始终检查malloc()
的返回值,以避免潜在的未定义行为。
fp
读取而不检查fopen
是否成功可能存在未定义的行为。filename
指向的数组内容,将其设为const char *
。bar
返回成功指标可能很有用。gcc -Wall -Wextra -Werror
或clang -Weverything -Werror
可能已经发现scanf
中的错误。