用c语言更新随机访问文件

用c语言更新随机访问文件,c,C,我想在C中完成以下操作 我有一个包含一些记录的随机访问数据文件 记录的格式如下: Acct# First Name Last Name Balance 0 "" "" 0.0 0 "" "" 0.0 0 "" "" 0.0 05 Joe Costanza 0.50 0

我想在C中完成以下操作

我有一个包含一些记录的随机访问数据文件

记录的格式如下:

Acct#  First Name     Last Name    Balance
0     ""             ""             0.0
0     ""             ""             0.0
0     ""             ""             0.0
05    Joe             Costanza      0.50
 0     ""             ""             0.0
 0     ""             ""             0.0
 0     ""             ""             0.0
19    Jason           Bourne        58.00
0     ""              ""            0.0
0     ""             ""             0.0
42    Andy            Der          -15.12
0     ""             ""             0.0
0     ""             ""             0.0
我想从所有账号为非零的记录的余额中减去一个金额,并将新的更新余额写入这些记录的文件中

这就是我迄今为止为实现上述目标所做的努力

#include <stdio.h>

struct clientData 
{ 
int acctNum;          
char lastName[15];  
char firstName[10]; 
double balance;       
};

void textFile(FILE *readPtr);

int main(void)
{ 
     FILE *cfPtr;

     struct clientData client = {0, "", "", 0.0};

     double serviceCharge = 5.0;

     cfPtr = fopen("credit.dat", "rb+");

     fread(&client, sizeof(struct clientData), 1, cfPtr);

     client.balance -= serviceCharge;

     fseek(cfPtr,(client.acctNum - 1) * sizeof(struct clientData)
     , SEEK_CUR);

     fwrite(&client, sizeof(struct clientData), 1, cfPtr);

     fclose(cfPtr);

     return 0;
}
在代码的这一点上,您还没有阅读任何内容。没什么

您已经打开了文件,您已经检查了是否已经到达了文件的末尾,但是还没有代码可以从文件中读取任何内容,因此您的
if
条件只是在开始时检查初始化的结构

如果在循环的顶部读取输入,则对输入进行循环通常效果最佳。(也有例外,但这看起来不像其中之一。)

尝试将此作为循环的起点:

while(fread(&client, sizeof(struct clientData), 1, filePtr)) {
    if (client.acctNum) {
        client.balance -= charge;
        fseek(filePtr, - sizeof(struct clientData), SEEK_CUR);
        if (1 != fwrite(&client, sizeof(struct clientData), 1, filePtr))
            perror("Error writing to file");
    }
}
错误处理可能会得到改进;也许整个编辑过程应该中止。(文件上的强制记录锁定可能会导致某些写入失败,而某些写入成功,但这不太可能。)

更新


您的
fseek()
调用基于帐号乘以
struct clientData
的大小来确定新文件位置。只有当您的记录已排序,没有跳过任何数字,并且它从
0
开始并向上运行时,此操作才有效。(您的示例输入文件未排序;您甚至在‘有效记录’的中间有一个记录< <代码> 0”/代码>帐号。因此,切换到<代码> fScript(…,SekkurCr)< /C> >。

< P>除了您的代码中的逻辑错误,Salnod指出,您永远不会<代码> FFLUHUE()>代码>您的文件流或<代码> FLUSEL()它。您所做的任何更新都可能保留在流缓冲区中,并在程序终止时丢失。

这是当前显示的代码的相关部分:

 cfPtr = fopen("credit.dat", "rb+");
 fread(&client, sizeof(struct clientData), 1, cfPtr);
 client.balance -= serviceCharge;
 fseek(cfPtr,(client.acctNum - 1) * sizeof(struct clientData), SEEK_CUR);
 fwrite(&client, sizeof(struct clientData), 1, cfPtr);
我将假设函数返回值的错误检查是“不需要的”;它应该在那里,但它会使事情稍微复杂化。然而,我不相信自己在没有错误检查的情况下编写一个程序——太多的事情会对我的口味(和痛苦的经历)产生影响

  • 将偏移量为0的记录读取到文件中。然后更新余额,根据相对于当前头寸的客户账号查找头寸,然后写回数据
另外,我们可以讨论您正在使用的二进制数据格式的智慧;目前这已经足够了

以下是“有效”的代码:

#include <stdio.h>

struct clientData 
{ 
    int acctNum;          
    char lastName[15];  
    char firstName[10]; 
    double balance;       
};

static void print_client(struct clientData *data)
{
    printf("%04d %-15s %-15s %6.2f\n", data->acctNum, data->lastName,
           data->firstName, data->balance);
}

int main(void)
{ 
    FILE *cfPtr;
    struct clientData client = {0, "Me", "Mine", 50.0};
    double serviceCharge = 5.0;

    /* Initialize */
    cfPtr = fopen("credit.dat", "wb");
    fwrite(&client, sizeof(struct clientData), 1, cfPtr);
    fclose(cfPtr);

    /* Update */
    cfPtr = fopen("credit.dat", "rb+");
    fread(&client, sizeof(struct clientData), 1, cfPtr);
    print_client(&client);
    client.balance -= serviceCharge;
    fseek(cfPtr, 0, SEEK_SET);
    fwrite(&client, sizeof(struct clientData), 1, cfPtr);
    fclose(cfPtr);

    /* Validate */
    cfPtr = fopen("credit.dat", "rb");
    fread(&client, sizeof(struct clientData), 1, cfPtr);
    fclose(cfPtr);
    print_client(&client);

    return 0;
}
#包括
结构客户端数据
{ 
int acctNum;
char lastName[15];
charfirstname[10];
双平衡;
};
静态无效打印_客户端(struct clientData*data)
{
printf(“%04d%-15s%-15s%6.2f\n”,数据->账户,数据->姓氏,
数据->名字,数据->余额);
}
内部主(空)
{ 
文件*cfPtr;
struct clientData client={0,“Me”,“Mine”,50.0};
双倍服务费=5.0;
/*初始化*/
cfPtr=fopen(“贷方数据”、“wb”);
fwrite(和client,sizeof(struct clientData),1,cfPtr);
fclose(cfPtr);
/*更新*/
cfPtr=fopen(“贷方数据”、“rb+”);
fread(和客户机,sizeof(struct clientData),1,cfPtr);
打印客户机(&客户机);
client.balance-=服务费;
fseek(cfPtr,0,SEEK_SET);
fwrite(和client,sizeof(struct clientData),1,cfPtr);
fclose(cfPtr);
/*证实*/
cfPtr=fopen(“贷方数据”、“rb”);
fread(和客户机,sizeof(struct clientData),1,cfPtr);
fclose(cfPtr);
打印客户机(&客户机);
返回0;
}

这也有效…它不会跳过0个客户端ID,因为它不会生成任何客户端ID。但你可以应付

#include <stdio.h>

struct clientData 
{ 
    int acctNum;          
    char lastName[15];  
    char firstName[10]; 
    double balance;       
};

static void print_client(const struct clientData *data)
{
    printf("%04d %-15s %-15s %6.2f\n", data->acctNum, data->lastName,
           data->firstName, data->balance);
}

/* Initialize file */
static void init_file(const char *filename)
{
    FILE *cfPtr = fopen(filename, "wb");
    int i;
    for (i = 1; i <= 30; i++)
    {
        struct clientData client = { i, "", "", i * 50.0};
        sprintf(client.lastName, "Me (%d)", i);
        sprintf(client.firstName, "Mine (%d)", i);
        fwrite(&client, sizeof(struct clientData), 1, cfPtr);
    }
    fclose(cfPtr);
}

static void print_file(const char *filename)
{
    struct clientData client;
    FILE *cfPtr = fopen(filename, "rb");
    while (fread(&client, sizeof(struct clientData), 1, cfPtr) == 1)
        print_client(&client);
    fclose(cfPtr);
}

int main(void)
{ 
    FILE *cfPtr;
    double serviceCharge = 5.0;
    const char *filename = "credit.dat";
    struct clientData client;

    init_file(filename);
    printf("Post-initialization: %s\n", filename);
    print_file(filename);

    /* Update */
    cfPtr = fopen(filename, "rb+");
    while (fread(&client, sizeof(struct clientData), 1, cfPtr) == 1)
    {
        client.balance -= serviceCharge;
        fseek(cfPtr, -1 * (long)sizeof(struct clientData), SEEK_CUR);
        fwrite(&client, sizeof(struct clientData), 1, cfPtr);
        fseek(cfPtr, 0, SEEK_CUR);
    }
    fclose(cfPtr);

    printf("Post-update: %s\n", filename);
    print_file(filename);

    return 0;
}
#包括
结构客户端数据
{ 
int acctNum;
char lastName[15];
charfirstname[10];
双平衡;
};
静态无效打印_客户端(const struct clientData*data)
{
printf(“%04d%-15s%-15s%6.2f\n”,数据->账户,数据->姓氏,
数据->名字,数据->余额);
}
/*初始化文件*/
静态void init_文件(常量字符*文件名)
{
文件*cfPtr=fopen(文件名,“wb”);
int i;

对于(i=1;i您有
cfPtr
(未声明;已打开但未使用)、
filePtr
(未声明也未打开,但已写入)和
readPtr
(未声明也未打开,但从中读取)。此代码无法编译。请向我们展示您使用的实际代码,并告诉我们它执行了什么操作以及您希望它执行的操作。如果过多的不同名称的文件变量表明您的代码的某个版本多次尝试打开同一个文件,从一个版本读取,然后写入另一个版本,请不要这样做,如果您真的必须这样做,则在写入文件和尝试读取文件之间刷新文件。我希望我们学到了一个重要的教训,关于基于剪切粘贴的问题:)我发现了另一个问题,稍后进行了更新。@user695752,两种方法:1在
fseek(3)中继续使用
(client.acctNum-1)
:(a)您必须确保您的记录以数字顺序排序,从
1开始,并且不能跳过输入文件中的任何数字。(b)您必须使用
SEEK\u SET
.2,或者您可以使用
SEEK\u CUR
而不使用任何
client.acctNum
scaling,只需备份刚才读取的一条记录。如果程序运行到完成,则
exit(3)
将刷新并关闭所有
stdio(3)
streams。但好的建议还是少一点,因为错误确实会发生,从而妨碍完全执行。:@user695752:我们尽量不给人太多的麻烦。您可以编写一个带有循环的函数来创建多个记录,而不是我的代码所写的一个记录——您必须有一种方法来创建文件,然后才能更新它。您需要更改记录编号以符合您的约定
#include <stdio.h>

struct clientData 
{ 
    int acctNum;          
    char lastName[15];  
    char firstName[10]; 
    double balance;       
};

static void print_client(struct clientData *data)
{
    printf("%04d %-15s %-15s %6.2f\n", data->acctNum, data->lastName,
           data->firstName, data->balance);
}

int main(void)
{ 
    FILE *cfPtr;
    struct clientData client = {0, "Me", "Mine", 50.0};
    double serviceCharge = 5.0;

    /* Initialize */
    cfPtr = fopen("credit.dat", "wb");
    fwrite(&client, sizeof(struct clientData), 1, cfPtr);
    fclose(cfPtr);

    /* Update */
    cfPtr = fopen("credit.dat", "rb+");
    fread(&client, sizeof(struct clientData), 1, cfPtr);
    print_client(&client);
    client.balance -= serviceCharge;
    fseek(cfPtr, 0, SEEK_SET);
    fwrite(&client, sizeof(struct clientData), 1, cfPtr);
    fclose(cfPtr);

    /* Validate */
    cfPtr = fopen("credit.dat", "rb");
    fread(&client, sizeof(struct clientData), 1, cfPtr);
    fclose(cfPtr);
    print_client(&client);

    return 0;
}
#include <stdio.h>

struct clientData 
{ 
    int acctNum;          
    char lastName[15];  
    char firstName[10]; 
    double balance;       
};

static void print_client(const struct clientData *data)
{
    printf("%04d %-15s %-15s %6.2f\n", data->acctNum, data->lastName,
           data->firstName, data->balance);
}

/* Initialize file */
static void init_file(const char *filename)
{
    FILE *cfPtr = fopen(filename, "wb");
    int i;
    for (i = 1; i <= 30; i++)
    {
        struct clientData client = { i, "", "", i * 50.0};
        sprintf(client.lastName, "Me (%d)", i);
        sprintf(client.firstName, "Mine (%d)", i);
        fwrite(&client, sizeof(struct clientData), 1, cfPtr);
    }
    fclose(cfPtr);
}

static void print_file(const char *filename)
{
    struct clientData client;
    FILE *cfPtr = fopen(filename, "rb");
    while (fread(&client, sizeof(struct clientData), 1, cfPtr) == 1)
        print_client(&client);
    fclose(cfPtr);
}

int main(void)
{ 
    FILE *cfPtr;
    double serviceCharge = 5.0;
    const char *filename = "credit.dat";
    struct clientData client;

    init_file(filename);
    printf("Post-initialization: %s\n", filename);
    print_file(filename);

    /* Update */
    cfPtr = fopen(filename, "rb+");
    while (fread(&client, sizeof(struct clientData), 1, cfPtr) == 1)
    {
        client.balance -= serviceCharge;
        fseek(cfPtr, -1 * (long)sizeof(struct clientData), SEEK_CUR);
        fwrite(&client, sizeof(struct clientData), 1, cfPtr);
        fseek(cfPtr, 0, SEEK_CUR);
    }
    fclose(cfPtr);

    printf("Post-update: %s\n", filename);
    print_file(filename);

    return 0;
}