为什么我的文件输出会被覆盖?

时间:2015-05-30 01:53:39

标签: c file struct formatting

我的程序接受用户输入并将其存储在我已定义为结构的记录数组中:struct Record
用户输入是结构的字段。一切都符合错误,但似乎我无法正确格式化。我的程序一直要求用户输入,直到用户在被询问是否有记录时输入'n' 一旦没有更多的记录,程序就会循环创建的记录,并且文件打印出每个记录由选项卡间隔开,最后以下一条记录的换行符开头。但是,它不是以新行开始并以相同方式打印另一条记录,而是覆盖打印的上一条记录,并进一步标记下一条记录。
是什么导致这种情况发生?

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

struct Record
{
    char fname[51];
    char lname[51];
    char address[51];
    char city[51];
    char state[51];
    char zipcode[51];
    char phoneNumber[51];
};

int main()
{
    FILE *fileWriter;
    const char filename[] = "data.txt";
    char answer = 'y';
    int size = 1;
    int i = 0;
    struct Record *records;
    struct Record *records_temp = NULL;

    while(answer == 'y' || answer == 'Y')
    {
        struct Record *records_temp = calloc((size),sizeof(*records));         
        records = records_temp;
        printf("First Name: \n");
        scanf("%s", records[size-1].fname);

        printf("Last Name: \n");
        scanf("%s", records[size-1].lname);

        printf("Address: \n");
        scanf(" %[^\n]", records[size-1].address);

        printf("City: \n");
        scanf("%s", records[size-1].city);

        printf("State: \n");
        scanf("%s", records[size-1].state);

        printf("Zipcode: \n");
        scanf("%s", records[size-1].zipcode);

        printf("Phone Number: \n");
        scanf("%s", records[size-1].phoneNumber);
        //stores all record info

        printf("Are there anymore records? [y/n] ");
        scanf(" %c", &answer);
        if(answer == 'y' || answer == 'Y')
        {
            size++;
            printf("\n");
        }
    }
        //open file

    fileWriter = fopen(filename,"wb");

    if(fileWriter != NULL)
    {
        for(;i< size; i++)
        {
            fprintf(fileWriter,"%s\t",records[i].fname);
            fprintf(fileWriter,"%s\t",records[i].lname);
            fprintf(fileWriter,"%s\t",records[i].address);
            fprintf(fileWriter,"%s\t",records[i].city);
            fprintf(fileWriter,"%s\t",records[i].state);
            fprintf(fileWriter,"%s\t",records[i].zipcode);
            fprintf(fileWriter,"%s\n",records[i].phoneNumber);
        }
        free(records);
        fclose(fileWriter);
    }
    else
    {
        printf("Error opening file.");   
    }
}

4 个答案:

答案 0 :(得分:1)

我改变了一些你的代码,但我认为你应该在这里使用链表作为数据结构,它更简单,消耗更少的内存。 我做了一些尝试,一切顺利。 :) 希望能帮到你!!

$(function(){
    $("div#SearchBox").ready(function(){
    var selectsCount;
        $.getJSON("http://localhost/cms/publicity/list/jsonoptions/", function(result){
            selectsCount = (result.length);
        })
        alert(selectsCount);
    })
})

答案 1 :(得分:0)

使用其他a模式打开文件,如&#34;附加&#34;。我认为没有必要进一步解释什么是好事,对吧?

但是,实际问题似乎是覆盖了输入循环中已经存在的前一条记录的指针。这应该怎么样?只需完成该循环,并尝试按照程序的说明进行操作。

问题是你不能这样做。使用链接列表分配块。

答案 2 :(得分:0)

while(answer == 'y' || answer == 'Y')
{
    struct Record *records_temp = calloc((size),sizeof(*records));

    records = records_temp;
    ...
}

您是否意味着这个?

while(answer == 'y' || answer == 'Y')
{
    struct Record *records_temp = realloc(records, size * sizeof *records);
    if (records_temp == NULL)
    {
         /* Handle allocation error */
    }
    records = records_temp;
    /* ... */
}

请勿将callocrealloc混淆。如果您需要进一步说明,请阅读手册。

不要忘记将records初始化为NULL ...

如果您的关注点是优化,那么这里最重要的瓶颈就是您的文件输入/输出。这是不可避免的,除了研究setvbuf之外,你无能为力。下一个瓶颈将是对内核分配函数的底层调用。您可以通过减少分配函数来减少该瓶颈。例如,您可以通过每次加倍大小来增加数组,而不是添加1:

size_t size = 0;
int answer;
do {
    size_t index = size++;
    if ((index & size) == 0) {
        void *temp = realloc(array, (2 * index + 1) * sizeof *array);
        if (temp == NULL) {
            /* Handle allocation error */
        }
        array = temp;
    }

    puts("First Name:");
    scanf("%s", array[index].fname);

    /* snip */

    answer = getchar();
} while (answer != EOF && tolower(answer) == 'y');

或者,您可以通过添加对reallocmemcpy的调用来重新发明轮子并执行free在幕后执行的相同工作(并且可能会失去优化的一些好处)像你这样的代码:

while(answer == 'y' || answer == 'Y')
{
    struct Record *records_temp = calloc((size),sizeof(*records));
    if (records_temp == NULL)
    {
        /* Handle allocation error */
    }
    if (records != NULL)
    {
        memcpy(records_temp, records, (size - 1) * sizeof *records);
        free(records);
    }
    records = records_temp;
    /* ... */
}

P.S。万一你错过了第一次:不要忘记将records初始化为NULL ......

答案 3 :(得分:0)

我看到的最大问题是内存分配逻辑。第一次循环时,为1条记录和增量大小分配内存。第二次循环,你为另外2个记录分配内存,因为size == 2.第三次通过循环,你为3个记录分配内存,总共1 + 2 + 3 = 6。

这就解释了为什么会发生这种情况。奥拉夫建议的修复,链表,是一个很好的。

相关问题