C语言 将结构写入文件,在接受 1 个输入后出现分段错误



在这个程序中,我想将结构写入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返回值。因此,如果databaseNULL,则后面的调用fwrite(&info, sizeof(info), 1, database);具有未定义的行为。

另请注意,scanf("%[^n]s", info[i].name);中有一个额外的"s"。 相反,您应该编写scanf("%19[^n]", info[i].name);以防止潜在的缓冲区溢出,并测试scanf的返回值以检测无效输入。

相关内容

  • 没有找到相关文章

最新更新