我有一个包含以下内容的文件:
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
如果输入的代码与文件中的代码相同,我想打印一条记录。
这是我的代码:
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);
printf("\n");
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);
`
但不起作用。
因此,我正在考虑使用fscanf
来读取代码,然后打印包含该代码的行。但是,如何在没有其他内容(例如Name
,Income
,...)的情况下读取代码,以及如何读取代码的前导0呢?
答案 0 :(得分:1)
首先,您不能使用您提供的 scanf 读取文件的标题,因为 Code 与第一个%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 $
请注意,仅使用%s
来读取 scanf 中的字符串时,就无法防止溢出,如果最好使用%63s
,因为我调整了 buffer < / em> 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'
答案 1 :(得分:0)
如果输入的代码与文件中的代码相同,我想打印一条记录。
如果您的目标只是打印“代码”与用户提供的某些值匹配的记录(又称行),则您的方法似乎过于复杂,因为无需扫描所有字段。
只需使用fgets
来读取行,然后检查Code值并进行打印(如果匹配)。
类似的东西:
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
int main(int argc, char* argv[]){
if (argc != 2)
{
printf("Wrong usage...\n");
return 1;
}
int code_to_print = atoi(argv[1]);
int code_read;
FILE* fp = fopen("db.txt", "r");
if (!fp)
{
printf("File error...\n");
return 1;
}
char buf[1024];
while (fgets(buf, sizeof buf, fp))
{
if (sscanf(buf, "%d", &code_read) == 1 && code_read == code_to_print)
{
printf("%s", buf);
}
}
fclose(fp);
}
使用如下程序:
./prog 8
..如何读取代码是否以0开头?
如果前导零很重要,则您无法使用%d
进行扫描,因为这将“删除”零。相反,您需要将代码作为单词进行扫描。喜欢:
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
int main(int argc, char* argv[]){
if (argc != 2)
{
printf("Wrong usage...\n");
return 1;
}
char code_read[4] = {0};
FILE* fp = fopen("db.txt", "r");
char buf[1024];
while (fgets(buf, sizeof buf, fp))
{
if (sscanf(buf, "%3s", code_read) == 1 && strcmp(code_read, argv[1]) == 0)
{
printf("%s", buf);
}
}
fclose(fp);
}
使用如下程序:
./prog 008