c - C使用结构从C中的文本文件中读取记录
问题描述
我正在尝试从名为 lib.txt 的文本文件中提取记录。我的程序是一个非常简单的基于图书馆的管理程序,我必须打印给定出版商或部门的所有书籍。我的代码是:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
struct Books
{
char name[100];
char author[100];
char publisher[100];
double price;
char branch[100];
};
typedef struct Books Books;
void main()
{
int a = 0,b=0,ch,i;
char *pb = (char *)malloc(100*sizeof(char));
Books *bk;
FILE *fp;
fp = fopen("lib.txt","r");
if(fp == NULL)
{
fprintf(stderr,"\n Error to open the file \n");
exit(1);
}
while(1)
{
if(feof(fp))
{
break;
}
char c;
c = fgetc(fp);
if(c=='\n')
{
a++;
}
}
a++;
bk = (Books *)malloc(a*sizeof(Books));
while(fread(&bk[b],sizeof(Books),1,fp)) //Even tried individual character extraction but it is not working
{
b++;
if(b==a)
{
break;
}
}
for(i=0;i<a;i++)
{
printf("%s",bk[i].name);
}
printf("1. Display books supplied by a particular publisher \n");
printf("2. Display books in a particular branch \n");
printf("3. Exit");
printf("\n");
printf("Enter your choice : ");
scanf("%d",&ch);
switch(ch)
{
case 1:
{
printf("Enter the name of publisher \n");
scanf(" %s",pb);
printf("\nName\tAuthor\tPublisher\tPrice\tBranch\n");
for(i=0;i<a;i++)
{
if(strcmp(bk[i].publisher,pb)==0)
{
printf("%s\t%s\t%s\t%.2lf\t%s \n",bk[i].name,bk[i].author,bk[i].publisher,bk[i].price,bk[i].branch);
}
}
fflush(pb);
break;
}
case 2:
{
printf("Enter the name of branch \n");
scanf(" %s",pb);
printf("\nName\tAuthor\tPublisher\tPrice\tBranch\n");
for(i=0;i<a;i++)
{
if(strcmp(bk[i].publisher,pb)==0)
{
printf("%s\t%s\t%s\t%.2lf\t%s \n",bk[i].name,bk[i].author,bk[i].publisher,bk[i].price,bk[i].branch);
}
}
fflush(pb);
break;
}
case 3:
{
return;
}
default:
{
printf("Invalid choice");
}
}
free(bk);
free(pb);
fclose(fp);
getch();
}
文件 lib.txt 以相同的顺序包含以下行,如下所示:
Abc1 A1 P1 23.0 B1
Abc2 A2 P2 23.0 B2
Abc3 A3 P3 23.0 B3
Abc4 A4 P2 23.0 B4
Abc5 A5 P2 23.0 B5
Abc6 A6 P6 23.0 B6
Abc7 A7 P2 23.0 B7
哦,它们是由标签分隔的。甚至尝试使用空格但没有变化。该程序编译正常,但未生成所需的输出。任何人都可以请帮忙吗?编辑:甚至尝试提取单个字符,然后拆分为子字符串,但失败了。请帮忙
解决方案
这是我的做法:
首先,定义一些函数来帮助你读取输入(你也可以在其他程序中使用它们):
int readint(int *i)
{
char buffer[255];
if (!fgets(buffer, 255, stdin)) {
fprintf(stderr, "stdin error\n");
return 0; // failed
}
buffer[strcspn(buffer, "\n")] = '\0';
if (sscanf(buffer, "%d", i) != 1)
return 0; // failed
return 1; // success
}
char *readstr(char *str, int size)
{
if (!fgets(str, size, stdin)) {
fprintf(stderr, "stdin error\n");
return NULL;
}
str[strcspn(str, "\n")] = '\0';
return str;
}
然后你的main()
:
int main()
{
// 1. Attempt to open file
// ------------------------------------------------------------------------
FILE *fp = fopen("lib.txt", "r");
if(!fp) {
fprintf(stderr, "Error to open the file\n");
return 1;
}
// 2. Read file text
// ------------------------------------------------------------------------
int lines_count = 7; // Depends on how many lines you have
Books *bk = malloc(lines_count * sizeof(*bk));
if (!bk) {
fclose(fp);
return 0;
}
char line[255];
int i = 0;
while(fgets(line, sizeof line, fp)) {
line[strcspn(line, "\n")] = '\0'; // Remove \n read by fgets()
char name[100];
char author[100];
char publisher[100];
double price;
char branch[100];
sscanf(line, "%[^\t]\t%[^\t]\t%[^\t]\t%lf\t%[^\t]", name, author, publisher, &price, branch);
strcpy(bk[i].name, name);
strcpy(bk[i].author, author);
strcpy(bk[i].publisher, publisher);
bk[i].price = price;
strcpy(bk[i].branch, branch);
i++;
}
fclose(fp);
// 3. User input
// ------------------------------------------------------------------------
printf("1. Display books supplied by a particular publisher\n");
printf("2. Display books in a particular branch\n");
printf("3. Exit");
printf("\n");
printf("Enter your choice: ");
int ch;
readint(&ch); // Ignored error checking for the sake of simplicity
char pb[100];
switch(ch)
{
case 1:
printf("Enter the name of publisher: ");
readstr(pb, sizeof(pb));
printf("\nName\tAuthor\tPublisher\tPrice\tBranch\n");
for(i = 0; i < lines_count; i++)
if(!strcmp(bk[i].publisher, pb))
printf("%s\t%s\t%s\t%.2lf\t%s \n", bk[i].name, bk[i].author, bk[i].publisher, bk[i].price, bk[i].branch);
break;
case 2:
printf("Enter the name of branch: ");
readstr(pb, sizeof(pb));
printf("\nName\tAuthor\tPublisher\tPrice\tBranch\n");
for(i = 0; i < lines_count; i++)
if(!strcmp(bk[i].publisher, pb))
printf("%s\t%s\t%s\t%.2lf\t%s \n",bk[i].name,bk[i].author,bk[i].publisher,bk[i].price,bk[i].branch);
break;
case 3:
return 0;
default:
printf("Invalid choice");
}
free(bk);
}
确保lib.txt
包含制表符,而不是空格。您应该验证您的编辑器是否正在用空格替换制表符。
有几点需要考虑:
main()
应该总是返回int
,不是void
。- 用于
fgets()
读取用户的输入并sscanf()
对其进行解析。你应该尽量避免使用scanf()
。
推荐阅读
- sharepoint - 如何在 PowerApps 上显示 subFloder 的项目?
- python - 如何从 id = 1 计算并将第一列命名为“Id”
- javascript - 用 d3.js 加载巨大的 Json 89000++ 行,这导致我加载速度非常慢,几乎杀死了 chrome
- javascript - CRM 自定义活动不返回输出参数
- reactjs - 虚拟 dom 在内存中是什么意思?
- java - 通知适配器、Activity/Fragment 或 POJO 以接收来自 API(改造)的实时消息?
- mongodb - 如何查询给定日期范围的 mongoDB?
- assembly - 程序已在 8086 中将控制权交还给操作系统
- react-native-maps - 我可以在 react-native-maps 中的多边形上显示小点吗
- c# - 如何在多台计算机上在 c# 上运行 exe