在接受1次输入后,将结构写入文件,从而产生分段错误

时间:2018-06-19 07:50:32

标签: c segmentation-fault file-handling

在这个程序中,我想将结构写入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);
}

6 个答案:

答案 0 :(得分:0)

有几个问题:

试试这个:

#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 file\n");  // 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);
}

答案 1 :(得分:0)

这应该可以解决问题,确保输入正确的database.dat路径或将dat文件移动到与代码相同的文件夹中,然后输入文件名&#34; database.dat&#34;在打开文件时。 另外,使用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("Error\n");  
        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);
}

答案 2 :(得分:0)

您需要管理员权限才能写入程序文件文件夹。尝试下面的代码片段。我试过了。

   #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 failed\n");
            fflush(stdout);
            return 0;
        }

        //    printf("Enter number of inputs\n");
        //    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;
    }

答案 3 :(得分:0)

在行scanf之前(“%[^ \ n] s”,info [i] .name);从输入缓冲区中读取一个字符并将其存储到临时变量中。

scanf("%c",&temp);
scanf("%[^\n]s", info[i].name);

当我们输入一个整数值并按Enter键来读取下一个值时,编译器会在字符串的第一个字符中输入或null,并且字符串输入终止。

 scanf("%d", &n);                        //No of inputs

当您点击输入编译器商店后输入或输入null作为info [i] .name第一个字符。这里我们从输入缓冲区读取一个字符并将其存储到临时变量中,从而在读取字符串之前清除输入缓冲区。

答案 4 :(得分:0)

此行存在两个问题

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'))='\0'; // Replace with a NUL if there is
}

您还应该检查fopen的返回结果,并确保在继续之前打开该文件。

if (database == NULL)   // check if the file could be opened
{
    printf("Cannot open file: %s\n",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声明为一个简单的结构并删除数组索引意味着您不会限制您写出的条目数。

答案 5 :(得分:0)

database = fopen("/media/heatclif/Vivek/C\\ Programs/ESD/database.dat", "w");中的文件名似乎不正确,但是您没有测试fopen的返回值是否失败。因此,如果fwrite(&info, sizeof(info), 1, database);database,则以后的调用NULL具有未定义的行为。

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