我的程序接受用户输入并将其存储在我已定义为结构的记录数组中: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.");
}
}
答案 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;
/* ... */
}
请勿将calloc
与realloc
混淆。如果您需要进一步说明,请阅读手册。
不要忘记将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');
或者,您可以通过添加对realloc
和memcpy
的调用来重新发明轮子并执行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。
这就解释了为什么会发生这种情况。奥拉夫建议的修复,链表,是一个很好的。