Сначала вы не можете прочитать файл с его заголовком, используя scanf , который вы даете, потому что Код несовместим с первым %d
, поэтому вам нужно пропустить первые 2 строки
Предупреждение: %
отсутствует в вашем printf для печати кода, поэтому код рассматривается как строка %s
с неопределенным поведением (обычно сбой)
Но как я могу прочитать код без другого содержимого, такого как Имя, Доход
Конечно, если вы используете scanf , вы также читаете другие поля, еслиэто реальная проблема?Вы также можете прочитать строку за строкой как строки ( fgets или getline ) и посмотреть начало, если у вас есть ожидаемый код, и в этом случае управлять оставшейся частью строки для извлеченияполя при необходимости и т. д.
Другой способ, если содержимое файла очень отформатировано, - изменить указатель файла, используя fseek , чтобы считывать только коды, ожидаемые (см.предложение в конце моего ответа).
как читать, если код имеет начальный 0 как этот?
Я не понимаю scanf прочитайте это хорошо, это не восьмеричное, потому что есть 008. Если присутствие 0 слева важно, не управляйте кодом как числом, а как строкой как в файле, так и когда задан код для поиска
Ваш код хорошо читает ваш входной файл:
#include <stdio.h>
int bypassLine(FILE * fp)
{
int c;
for (;;) {
c = fgetc(fp);
if (c == EOF)
return 0;
if (c == '\n')
return 1;
}
}
int main()
{
FILE * fp = stdin;
int code_t;
char buffer[64];
double inc_t, personal, pension_t, health_t, depend_t, gift_t, taxable_t, tax_t, net_t;
if (!bypassLine(fp) || !bypassLine(fp))
puts("too short file");
else {
while (fscanf(fp, " %3d%s%lf%lf%lf%lf%lf%lf%lf%lf%lf", &code_t, buffer, &inc_t, &personal, &pension_t, &health_t, &depend_t, &gift_t, &taxable_t, &tax_t, &net_t) == 11) {
printf(" %03d%20s%11.0lf%9.0lf%10.0lf%8.0lf%10.0lf%11.0lf%11.0lf%10.0lf%10.0lf\n", code_t, buffer, inc_t, personal, pension_t, health_t, depend_t, gift_t, taxable_t, tax_t, net_t);
}
}
}
Компиляция и выполнение:
pi@raspberrypi:/tmp $ gcc -pedantic -Wextra f.c
pi@raspberrypi:/tmp $ cat f
Code Name Income Allow Pens Ins Depend Charity Taxable Tax Net
------------------------------------------------------------------------------------------------------------------------
008 John 100000 4000 5000 1000 3200 1000 85800 20280 79720
001 Doe 50000 4000 0 500 1600 0 43900 7725 42275
pi@raspberrypi:/tmp $ ./a.out < f
008 John 100000 4000 5000 1000 3200 1000 85800 20280 79720
001 Doe 50000 4000 0 500 1600 0 43900 7725 42275
pi@raspberrypi:/tmp $
Обратите внимание, что нет защиты от переполнения при чтениистрока в scanf просто с %s
, если лучше использовать %63s
, потому что я измерил буфер 64
Небольшое изменение для поиска кода, все еще используя ваш scanf , давая имя файла и ожидаемый код в аргументе:
#include <stdio.h>
int bypassLine(FILE * fp)
{
int c;
for (;;) {
c = fgetc(fp);
if (c == EOF)
return 0;
if (c == '\n')
return 1;
}
}
int main(int argc, char ** argv)
{
if (argc != 3)
printf("usage : %s <file> <code>\n", *argv);
else {
FILE * fp;
int code_t, expected;
char buffer[64];
double inc_t, personal, pension_t, health_t, depend_t, gift_t, taxable_t, tax_t, net_t;
if ((fp = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "cannot open '%f'\n", argv[1]);
return -1;
}
if (!bypassLine(fp) || !bypassLine(fp)) {
fprintf(stderr, "too short file '%s'\n", argv[1]);
fclose(fp);
return -1;
}
if (sscanf(argv[2], "%d%c", &expected, buffer) != 1) {
fprintf(stderr, "invalid code '%s'\n", argv[2]);
}
else {
while (fscanf(fp, " %3d%63s%lf%lf%lf%lf%lf%lf%lf%lf%lf", &code_t, buffer, &inc_t, &personal, &pension_t, &health_t, &depend_t, &gift_t, &taxable_t, &tax_t, &net_t) == 11) {
if (code_t == expected) {
printf(" %03d%20s%11.0lf%9.0lf%10.0lf%8.0lf%10.0lf%11.0lf%11.0lf%10.0lf%10.0lf\n", code_t, buffer, inc_t, personal, pension_t, health_t, depend_t, gift_t, taxable_t, tax_t, net_t);
fclose(fp);
return 0;
}
}
fprintf(stderr, "code %d not found in '%s'\n", expected, argv[1]);
}
fclose(fp);
return -1;
}
}
Компиляция и выполнение:
pi@raspberrypi:/tmp $ gcc -pedantic -Wextra f.c
pi@raspberrypi:/tmp $ ./a.out ./f 2
code 2 not found in './f'
pi@raspberrypi:/tmp $ ./a.out ./f 8
008 John 100000 4000 5000 1000 3200 1000 85800 20280 79720
pi@raspberrypi:/tmp $
Другой способ с использованием fseek для прямого перехода от кода к коду в файле:
#include <stdio.h>
int bypassLine(FILE * fp)
{
int c;
for (;;) {
c = fgetc(fp);
if (c == EOF)
return 0;
if (c == '\n')
return 1;
}
}
int main(int argc, char ** argv)
{
if (argc != 3)
printf("usage : %s <file> <code>\n", *argv);
else {
FILE * fp;
int code_t, expected;
char buffer[64];
double inc_t, personal, pension_t, health_t, depend_t, gift_t, taxable_t, tax_t, net_t;
if ((fp = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "cannot open '%f'\n", argv[1]);
return -1;
}
if (!bypassLine(fp) || !bypassLine(fp)) {
fprintf(stderr, "too short file '%s'\n", argv[1]);
fclose(fp);
return -1;
}
if (sscanf(argv[2], "%d%c", &expected, buffer) != 1) {
fprintf(stderr, "invalid code '%s'\n", argv[2]);
}
else {
long offset = ftell(fp);
while (fscanf(fp, " %03d", &code_t) == 1) {
if (code_t == expected) {
/* extract the other fields */
if (fscanf(fp, "%63s%lf%lf%lf%lf%lf%lf%lf%lf%lf", buffer, &inc_t, &personal, &pension_t, &health_t, &depend_t, &gift_t, &taxable_t, &tax_t, &net_t) == 10) {
printf(" %03d%20s%11.0lf%9.0lf%10.0lf%8.0lf%10.0lf%11.0lf%11.0lf%10.0lf%10.0lf\n", code_t, buffer, inc_t, personal, pension_t, health_t, depend_t, gift_t, taxable_t, tax_t, net_t);
fclose(fp);
return 0;
}
else {
fprintf(stderr, "code %d found but cannot read next fields\n", code_t);
fclose(fp);
return -1;
}
}
/* the lines are supposed having all the times 114 characters newline included */
offset += 114;
if (fseek(fp, offset, SEEK_SET) == -1) {
fprintf(stderr, "error when going at offset %d of '%s'\n", offset, argv[1]);
fclose(fp);
return -1;
}
}
fprintf(stderr, "code %d not found in '%s'\n", expected, argv[1]);
}
fclose(fp);
return -1;
}
}
Компиляция и выполнение:
pi@raspberrypi:/tmp $ gcc -pedantic -Wextra f.c
pi@raspberrypi:/tmp $ cat f
Code Name Income Allow Pens Ins Depend Charity Taxable Tax Net
------------------------------------------------------------------------------------------------------------------------
008 John 100000 4000 5000 1000 3200 1000 85800 20280 79720
001 Doe 50000 4000 0 500 1600 0 43900 7725 42275
pi@raspberrypi:/tmp $ ./a.out ./f 8
008 John 100000 4000 5000 1000 3200 1000 85800 20280 79720
pi@raspberrypi:/tmp $ ./a.out ./f 1
001 Doe 50000 4000 0 500 1600 0 43900 7725 42275
pi@raspberrypi:/tmp $ ./a.out ./f 11
code 11 not found in './f'