Хотя я не могу поверить, что они на самом деле все еще преподают Кобол (под маской Си), я помогу вам, поскольку, в отличие от тех, кто обращается за помощью, вы фактически добавили немало работа: -)
Хитрость заключается в том, чтобы не печатать после каждого обновления, а подождать, пока номер счета не изменится, распечатать предыдущие окончательные сведения.
И, поскольку вы достигнете конца файла транзакции при обработке последней учетной записи, вам придется сделать это еще раз после выхода из цикла.
Вот подробные шаги.
Введите еще три переменные, char lastname[30]
, int lastaccount
и double lastbalance
. Убедитесь, что lastaccount
инициализирован на -1
.
Тогда ваш код может поймать переходы номера счета, просто проверив значения lastaccount
и account
. Хранение всех трех полей обеспечивает распечатку сведений о предыдущей учетной записи, даже если вы уже прочитали сведения о новой учетной записи.
Перед matches = 1
вставить следующий код:
if (lastaccount != account) {
if (lastaccount != -1)
printf(" %-10d%-10s%.2lf\n", lastaccount, lastname, lastbalance);
lastaccount = account;
strcpy (lastname, name);
}
Вам также нужно будет включить string.h
, чтобы получить прототип для strcpy
.
Это отлавливает переходы номера счета и распечатывает данные о последнем (если, конечно, последний не был номером счета -1
, конечно, поскольку это означает, что - это предыдущего). Но независимо от того, печатает он или нет, он настроен на следующий переход.
Сразу после balance = total
добавить lastbalance = balance;
. Это сохранит самый последний баланс текущего счета, чтобы его можно было распечатать при переходе.
В отличие от номера и имени счета, это необходимо делать для каждой транзакции , а не для каждой учетной записи . Это связано с тем, что учетная запись / имя для учетной записи не изменяются, а для конечного баланса (для каждой транзакции).
За пределами цикла, непосредственно перед fclose (cfPtr2);
, введите код:
if (lastaccount != -1)
printf(" %-10d%-10s%.2lf\n", lastaccount, lastname, lastbalance);
Это распечатывает детали для окончательного счета, предполагая, что они были обработаны вообще. Как упоминалось ранее, это необходимо, потому что вы достигнете конца файла, не выполнив переход из-за измененного номера учетной записи.
И, пожалуйста, в качестве окончательного запроса:
- избавьтесь от
conio.h
и используйте getchar()
вместо getch()
.
- , если возможно, ditch Turbo C и использовать
gcc
- это , так что намного лучше: -)
- не
fflush(stdin)
.
- использовать канонический
int main (void) ...
.
- вернуть что-то из
main
(хотя я думаю, что это ослаблено в последующих версиях стандарта).
Я не буду публиковать свой действительный код (если вы не гарантируете, что это не домашняя работа), но следующая расшифровка показывает, что этих изменений должно быть достаточно, чтобы исправить ваши текущие проблемы:
$ cat clients.dat
1 Pax 4.2
2 Roger 0
$ cat transactions.dat
1 1/2/3 112.3
1 2/3/4 -22.1
2 3/4/5 7
$ ./qq
Account Name Balance
|----------------------------------|
1 Pax 94.40
2 Roger 7.00
Что бы это ни стоило, я не уверен, что полностью согласен с трактовкой файла трансакции как основного элемента. Поскольку ваша задача - скопировать файл учетной записи с необходимыми изменениями (как указано в файле транзакции), я бы предпочел обработать файл учетной записи как основной блок.
Мне так кажется чище.
И, в целях полноты, вот код, который я придумал. Я бы не советовал сдавать это как задание, поскольку есть множество вещей, которые могут снизить вашу оценку, вещи, которые гораздо менее значимы в реальном мире, но о которых у преподавателей есть особая пчела :-) несколько точек возврата, используя #define
вместо enum
и т. д.
#include <stdio.h>
#include <string.h>
#define HDR_LINE 0
#define HDR_FULL 1
static void outHeader (int withHeading) {
printf ("+-%-6s-+-%-10s-+-%-6s-+-%-6s-+-%-6s-+\n",
"------", "----------", "------", "------", "------");
if (withHeading)
printf ("| %-6s | %-10s | %-6s | %-6s | %-6s |\n",
" Acct ", " Name ", " Date ", "Amount", "Balnce");
}
static void closeFiles (FILE *pfCli, FILE *pfTxn, FILE *pfNew) {
if (pfCli) fclose (pfCli);
if (pfTxn) fclose (pfTxn);
if (pfNew) fclose (pfNew);
}
static int openFiles (FILE **pfCli, FILE **pfTxn, FILE **pfNew) {
*pfCli = *pfTxn = *pfNew = NULL;
if ((*pfCli = fopen ("clients.dat", "r")) == NULL) {
printf ("File clients.dat could not be opened\n");
closeFiles (*pfCli, *pfTxn, *pfNew);
return 0;
}
if ((*pfTxn = fopen ("transactions.dat", "r")) == NULL) {
printf ("File transactions.dat could not be opened\n");
closeFiles (*pfCli, *pfTxn, *pfNew);
return 0;
}
if ((*pfNew = fopen ("clientupdate.dat", "w")) == NULL) {
printf ("File clientupdate.dat could not be opened\n");
closeFiles (*pfCli, *pfTxn, *pfNew);
return 0;
}
return 1;
}
static void outCli (int acct, char *nm, double bal, char *ind) {
if (acct == -1)
printf ("| %6s | %-10s | %6s | %6s | %6.2lf | %s\n",
"", nm, "", "", bal, ind);
else
printf ("| %6d | %-10s | %6s | %6s | %6.2lf | %s\n",
acct, nm, "", "", bal, ind);
}
static void outTxn (char *date, double amt, double bal) {
printf ("| %6s | %10s | %-6s | %6.2lf | %6.2lf |\n",
"", "", date, amt, bal);
}
static void getTxn (FILE *fh, int *acct, char *date, double *amt) {
if (feof (fh))
*acct = -1;
else
fscanf (fh, "%d%s%lf\n", acct, date, amt);
}
static void getCli (FILE *fh, int *last, int *acct, char *nm, double *bal) {
if (*last != -1)
outCli (-1, "", *bal, "-->");
*last = *acct;
fscanf (fh, "%d%s%lf\n", acct, nm, bal);
}
int main (void) {
int cli_acct, txn_acct, last_acct = -1;
char txn_date[10], cli_nm[10];
double cli_bal, txn_amt;
FILE *fCli, *fTxn, *fNew;
// Open all files, output header and load up first transaction.
if (!openFiles (&fCli, &fTxn, &fNew))
return 1;
outHeader (HDR_FULL);
getTxn (fTxn, &txn_acct, txn_date, &txn_amt);
// Process every account.
while (!feof (fCli)) {
// Bring in an account and print starting balance.
getCli (fCli, &last_acct, &cli_acct, cli_nm, &cli_bal);
outHeader (HDR_LINE);
outCli (cli_acct, cli_nm, cli_bal, "<--");
// While account is not yet up to txn, output and read new.
while (cli_acct < txn_acct) {
fprintf (fNew, "%d %s %.2lf\n", cli_acct, cli_nm, cli_bal);
outCli (-1, "", cli_bal, "-->");
outHeader (HDR_LINE);
fscanf (fCli, "%d%s%lf\n", &cli_acct, &cli_nm, &cli_bal);
outCli (cli_acct, cli_nm, cli_bal, "<--");
}
// If they don't match, you have a orphan transaction.
if ((cli_acct != txn_acct) && (txn_acct != -1)) {
printf ("Orphan transaction for account # %d\n", txn_acct);
closeFiles (fCli, fTxn, fNew);
return 1;
}
// While account and transaction match, process transaction lines.
while (cli_acct == txn_acct) {
cli_bal = cli_bal + txn_amt;
outTxn (txn_date, txn_amt, cli_bal);
if (feof (fTxn))
txn_acct = -1;
else
fscanf (fTxn, "%d%s%lf\n", &txn_acct, &txn_date, &txn_amt);
}
fprintf (fNew, "%d %s %.2lf\n", cli_acct, cli_nm, cli_bal);
}
// Output final lines if needed.
if (last_acct != -1)
outCli (-1, "", cli_bal, "-->");
outHeader (HDR_LINE);
// Close all files and exit successfully.
closeFiles (fCli, fTxn, fNew);
return 0;
}
Учитывая clients.dat
из:
0 Mary 99.9
1 Pax 4.2
2 Bob 7
4 Roger 0
5 Nobody 9
и transactions.dat
из:
1 1/2/3 112.3
1 2/3/4 -22.1
4 3/4/5 7
это выводит:
+--------+------------+--------+--------+--------+
| Acct | Name | Date | Amount | Balnce |
+--------+------------+--------+--------+--------+
| 0 | Mary | | | 99.90 | <--
| | | | | 99.90 | -->
+--------+------------+--------+--------+--------+
| 1 | Pax | | | 4.20 | <--
| | | 1/2/3 | 112.30 | 116.50 |
| | | 2/3/4 | -22.10 | 94.40 |
| | | | | 94.40 | -->
+--------+------------+--------+--------+--------+
| 2 | Bob | | | 7.00 | <--
| | | | | 7.00 | -->
+--------+------------+--------+--------+--------+
| 4 | Roger | | | 0.00 | <--
| | | 3/4/5 | 7.00 | 7.00 |
| | | | | 7.00 | -->
+--------+------------+--------+--------+--------+
| 5 | Nobody | | | 9.00 | <--
| | | | | 9.00 | -->
+--------+------------+--------+--------+--------+
и создает clientupdate.dat
из:
0 Mary 99.90
1 Pax 94.40
2 Bob 7.00
4 Roger 7.00
5 Nobody 9.00
Не стесняйтесь использовать этот код для любых целей, кроме как выдавать его за домашнее задание.