在这个程序中,我想将结构写入database.dat
文件中。 但是在获取输入和名称后,终端显示Segmentation fault (core dumped)
。我尝试了不同的方法来修复它,但每次都是相同的情况。
#include <stdio.h>
#include <stdlib.h>
struct movie {
char name[20];
int g1, g2, g3;
};
void main() {
int i, j, n;
struct movie info[30];
FILE *database;
database = fopen("/media/heatclif/Vivek/C\ Programs/ESD/database.dat", "w");
scanf("%d", &n); //No of inputs
for (i = 0; i < n; ++i) {
scanf("%[^n]s", info[i].name);
scanf("%d", &info[i].g1);
scanf("%d", &info[i].g2);
scanf("%d", &info[i].g3);
fwrite(&info[i], sizeof(info[i]), 1, database);
}
fclose(database);
}
有几个问题:
试试这个:
#include <stdio.h>
struct movie
{
char name[20];
int g1, g2, g3;
};
int main()
{
int i, n;
struct movie info; // you don't need an array here
FILE *database;
database = fopen("output", "w");
if (database == NULL) // check if the file could be opened
{
printf("Cannot open filen"); // if not, display error message
return 1; // and quit
}
scanf("%d", &n); // No of inputs
for (i = 0; i<n; ++i)
{
scanf("%s", info.name); // "%[^n]s" is wrong here
scanf("%d", &info.g1);
scanf("%d", &info.g2);
scanf("%d", &info.g3);
fwrite(&info, sizeof(info), 1, database);
}
fclose(database);
}
这应该可以解决问题,确保您输入了正确的数据库路径.dat或者将 dat 文件移动到与代码相同的文件夹中,并在打开文件时仅提供文件名"database.dat"。 此外,使用 fprintf 将结构元素输出到文件。
#include <stdio.h>
#include<stdlib.h>
struct movie
{
char name[20];
int g1,g2,g3;
};
void main()
{
int i,j,n;
struct movie info[30];
FILE *database;
database=fopen("database.dat","w");
if (database == NULL) // check fi file is open or not.
{
printf("Errorn");
exit(1);
}
scanf("%d",&n); //No of inputs
for(i=0;i<n;++i)
{
scanf("%s",info[i].name); `enter code here`// replace "%[^n]s" by %s
scanf("%d",&info[i].g1);
scanf("%d",&info[i].g2);
scanf("%d",&info[i].g3);
fprintf(database,"%s",info[i].name); // write to file using fprintf
fprintf(database,"%d",info[i].g1);
fprintf(database,"%d",info[i].g2);
fprintf(database,"%d",info[i].g3);
}
fclose(database);
}
您需要管理员权限才能写入程序文件文件夹。 请尝试以下代码片段 它有效。我试过了。
#include <stdio.h>
#include <stdlib.h>
struct movie
{
char name[10];
int g1,g2,g3;
};
int main(void) {
int n,i,j;
// printf("!!!Hello World!!!n");
// fflush(stdout);
struct movie list[30];
FILE *fptr;
fptr = fopen("C:/Users/yadhu/database.dat","w");
if(fptr == NULL) {
printf("File opening failedn");
fflush(stdout);
return 0;
}
// printf("Enter number of inputsn");
// fflush(stdout);
scanf("%d",&n);
for(i = 0; i < n; i++)
{
scanf("%s",list[i].name);
scanf("%d%d%d",&list[i].g1,&list[i].g2,&list[i].g3);
fwrite(&list[i],sizeof(list[i]),1,fptr);
}
return EXIT_SUCCESS;
}
在行scanf("%[^]s", info[i].name(; 从输入缓冲区读取字符并将其存储到临时变量中。
scanf("%c",&temp);
scanf("%[^n]s", info[i].name);
当我们输入一个整数值并按回车键读取下一个值时,编译器将 Enter 或 null 存储到字符串的第一个字符中,字符串输入终止。
scanf("%d", &n); //No of inputs
在此行之后,当您点击输入编译器存储输入或空作为 info[i].name 第一个字符。在这里,我们从输入缓冲区读取一个字符并将其存储到临时变量中,从而在读取字符串之前清除输入缓冲区。
这条线有两个问题
scanf("%[^n]s", info[i].name);
首先,它有一个额外的"s",这就是为什么你发现它不起作用,因为它在你的输入中寻找一个实际的"s"。格式字符串应该只是%[^n]
.
其次,它不能确保输入的字符串适合可用空间。
做你想做的事情的一个可能更好的方法是使用fgets
fgets(info[i].name,20,stdin);
这将在一行文本中读取,但将其限制为最多 19 个字符(始终有一个插槽用于存储NUL
终止字符(。如果遇到n
它将停止,但会将其包含在字符串中,因此如果存在,则需要将其删除。
if(strchr(info[i].name,'n')) // See if there is a `n` in the string
{
*(strchr(info[i].name,'n'))=' '; // Replace with a NUL if there is
}
您还应该检查fopen
的返回结果,并确保在继续之前打开文件。
if (database == NULL) // check if the file could be opened
{
printf("Cannot open file: %sn",strerror(errno));
return 1;
}
当您开始读取第二个条目时,您也会遇到问题,因为您没有清除输入缓冲区,因为在第三个数字之后会有一个n
。同样,fgets
可以在这里提供帮助。
声明一个新字符串来存储该行
char buffer[100];
然后将对scanf
的调用替换为以下内容。它将像以前一样读取整行,然后sscanf
提取出 3 个数字。它还检查它是否确实找到了 3 个数字,如果没有,您可以报告错误或任何您认为需要的数字。
fgets(buffer,100,stdin);
if(sscanf(buffer,"%d%d%d",&info[i].g1,&info[i].g2,&info[i].g3)!=3)
{
// Did not get 3 numbers - handle situation appropriately.
}
您可能还需要执行类似的操作,以便在读取n
值后清除输入缓冲区。
由于除了写出数据之外,您似乎没有使用info
因此将其作为数组也没有多大意义。只需将info
声明为简单结构并删除数组索引,就意味着您写出的条目数量不会受到限制。
文件名在database = fopen("/media/heatclif/Vivek/C\ Programs/ESD/database.dat", "w");
中似乎不正确,但您不会测试失败fopen
返回值。因此,如果database
NULL
,则后面的调用fwrite(&info, sizeof(info), 1, database);
具有未定义的行为。
另请注意,scanf("%[^n]s", info[i].name);
中有一个额外的"s"。 相反,您应该编写scanf("%19[^n]", info[i].name);
以防止潜在的缓冲区溢出,并测试scanf
的返回值以检测无效输入。