c - C二进制文件不更新/读取
问题描述
下面我提供了我的代码。我将根据提供的帐号“存款”。姓名、帐号和余额都在下面的“accounts.dat”文件中。
Herman T Travis 3 $500
Sam L Travis 1 $40
Henry O Billiam 2 $6000
我不确定它是我创建文件的方式(使用简单的 vi 编辑器)还是我的代码中的问题,但是当我运行它并将帐号和余额提供给程序时不会报告新的余额文件。有什么建议么?
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char first[15];
char middle[2];
char last[15];
float balance;
long int acct;
} data;
int main() {
int choice = -1, i = 0, n = 0;
long int number;
double amount;
FILE *aPtr;
data accounts[50];
aPtr = fopen("accounts.dat", "ab+");/* Opens file for read/write; appends to file if exist */
if (aPtr == NULL) {
printf("File could not be opened");
exit(1);
}
fseek(aPtr, 0, SEEK_SET); /* Moving pointer to start of file*/
while (fread(accounts + 1, sizeof(data), 1, aPtr) == 1) /* Read and store info in file, into accounts array */
i++;
n = i; /* Num. of records in file */
do {
printf("Select Option\n" );
printf("0: Exit\n1: Deposit\n2: Withdrawl\n3: Add Account\n4: Remove Account\n5: Balance Inquiry\n6: View Accounts\n: ");
scanf("%d", &choice);
switch (choice) {
case 0: /* Exit */
fclose(aPtr);
break;
case 1: /* Deposit*/
fseek(aPtr, 0, SEEK_SET);
printf("Enter account number:\n");
scanf("%ld", &number);
printf("Enter amount to be deposited:\n");
scanf("%lf", &amount);
for (i = 0; i < n; i++) {
if (accounts[i].acct == number) {
accounts[i].balance = accounts[i].balance + amount;
fseek(aPtr, i * sizeof(data), SEEK_SET); /* Pointer goes to accountlocation in file*/
fwrite(accounts + i, sizeof(data), 1, aPtr); /* Write modified account into file */
break;
}
}
if (i == n) {
printf ( "Account does not exist\n" );
}
break;
}
} while (choice != 0);
return 0;
}
解决方案
正确填充结构是此答案的重点。
您的文件的命名约定表明它应该是一个二进制文件(即.dat
行业中常用的二进制文件)。但是你显示的内容清楚地表明它是一个文本文件,所以在下面的例子中,我使用 data.txt 作为文件名。由于它是一个文本文件,并且包含定义明确的行字段,因此将内容解析为结构将非常简单
文件的格式是严格定义的,并使用空格作为分隔符。这一切都可以,但是选择一个可见的分隔符,通常不用于字段内容,例如逗号:,
在不使用字段时会更容易,例如没有中间名时。但这不是必需的,以下示例将使用空格分隔符。
如果您愿意在此实现中使用fgets()
and strtok()
(几乎没有错误检查/处理),它提供了一个使用数据文件内容填充结构的示例:
typedef struct
{
char first[15];
char middle[2];
char last[15];
float balance;
long int acct;
}DATA;
const char filename[] = {".\\data.txt"};
int lineCount(const char *fname);
DATA * populateData(int lines, const char *fname);
int main(void)
{
int lines = lineCount(filename);//count number of accounts in file (lines in file)
DATA *data = populateData(lines, filename);//Create and populate data structure
if(data)
{
; //use data here
free(data); //free data memory when finished using it.
}
return 0;
}
int lineCount(const char *fname)
{
int count=0;
char line[260];
FILE *fp = fopen(fname, "r");
if(fp)
{
while(fgets(line, 260, fp)) count++;
fclose(fp);
}
return count;
}
DATA * populateData(int lines, const char *fname)
{
int i;
char *tok;
char *endPtr;
char line[260];
DATA *data = calloc(lines, sizeof(*data ));
if(data)
{
FILE *fp = fopen(fname, "r");
if(fp)
{
for(i=0;i<lines;i++)
{
if(fgets(line, 260, fp))
{
//get first name
tok = strtok(line, " ");
if(tok)
{
strcpy(data[i].first, tok);
//get Middle name
tok = strtok(NULL, " ");
if(tok)
{
strcpy(data[i].middle, tok);
//get last name
tok = strtok(NULL, " ");
if(tok)
{
strcpy(data[i].last, tok);
//get balance
tok = strtok(NULL, " ");
if(tok)
{
data[i].acct = atoi(tok);
//get acct
tok = strtok(NULL, "$");
if(tok)
{
data[i].balance = strtod(tok, &endPtr);
}
}
}
}
}
}
}
fclose(fp);
}
}
return data;
}
推荐阅读
- java - 最大堆插入和排序 Java
- xodus - 实体的元数据未定义
- c# - 设置变量给我一个 NullReferenceException
- flutter - Dart 检查字符串列表中的部分字符串是否包含元素
- google-apps-script - 如何通过 Google Docs ID 或 URL 获取 Google Drive 位置?
- node.js - 为什么 get/post 方法会抛出 Unauthorized (401) ERR?
- javascript - 您将如何在单词搜索求解器中实现垂直单词查找?
- google-apps-script - 在工作表的多个选项卡中打开到今天的日期
- amazon-web-services - 如何在不破坏池的情况下使 Cognito 用户池电子邮件属性可变?
- python - Asyncio 不会在 Python 中同时运行所有任务。尝试批量导出csv文件