【问题标题】:difficulty with reading the last record from a .txt file in C难以从 C 中的 .txt 文件中读取最后一条记录
【发布时间】:2016-09-16 19:52:33
【问题描述】:

我正在用 C 语言编写一个程序,它从用户那里读取文件数据(名称、q1、q2、q3 的答案),并将数据存储在 .txt 文件中,并允许用户查看他们输入的数据.目前,我对允许数据查看最后一条记录的功能有困难。 这是我的代码:

struct pre_survey{
char name[20];
int q1;
int q2;
int q3;
};
struct pre_survey temp;
struct pre_survey get;

int main(){
while (pre_or_post!=0){

if(pre_or_post==1){
    printf("\n1. append(enter) data\n");
    printf("2. check first record\n");
    printf("3. check last record\n");
    printf("please select your choice\n");
    scanf("%d", &choice);

switch (choice){
    case 1: append();
            break;
    case 2: frst_record();
            break;
    case 3: last_record();
            break;}}

void append(){
    fp=fopen("pre-survey.txt", "a");
    printf("name\n");
    scanf("%s", &temp.name);
    printf("q1:\n");
    scanf("%d", &temp.q1);
    printf("q2:\n");
    scanf("%d", &temp.q2);
    printf("q3:\n");
    scanf("%d", &temp. q3);
    fprintf(fp, "%s %d %d %d", temp.name, temp.q1, temp.q2, temp.q3);
    fclose(fp);}

void last_record(){
    fp=fopen("pre-survey.txt", "r");
    fseek(fp, -sizeof(temp),SEEK_END);
    fscanf(fp, "%s %d %d %d", get.name, &get.q1, &get.q2, &get.q3);
    printf("name: %s\n", get.name);
    printf("q1: %d\n", get.q1);
    printf("q2: %d\n", get.q2);
    printf("q3:%d\n", get.q3);
    fclose(fp); 
}

现在,当我尝试查找最后一条记录时,会显示第一条记录的数据。我认为问题在于,当我检查 sizeof(temp) 为 32 时,以及当我使用

fp=fopen("pre-survey.txt", "r");
fseek(fp,0, 2);
size=ftell(fp);
printf("size:%d\n", size);

要检查整个文件的大小,它是 34。 因此,当我按 temp 的大小从文件末尾读取时,它会转到第一条记录。 但我不确定我在代码中做错了什么。

【问题讨论】:

  • main 的第一行是while (pre_or_post!=0)pre_or_post 没有定义,甚至没有修改以影响循环行为时,这不是一个很好的开始。请提供Minimal, Complete, and Verifiable example,它显示了您尝试过的内容。
  • @bonny 你需要写固定大小。
  • 随机访问和文本文件不能很好地结合在一起。
  • 发布的代码无法编译。 main() 函数末尾似乎至少缺少 2 行代码。
  • 为了便于阅读和理解: 1) 确保发布的代码在发布之前能够干净地编译。 2) 遵循公理:每行只有一个语句,并且(最多)每条语句有一个变量声明。 3) 始终缩进代码。在每个左大括号 '{' 后缩进。在每个右大括号 '}' 之前取消缩进。 4) 不要在任何其他代码语句之后在行尾隐藏右大括号'}'。

标签: c file-io fseek


【解决方案1】:

如果读取记录的位置为fseek, 记录必须是固定长度。

例如

void append(void){
    FILE *fp=fopen("pre-survey.txt", "a");
    printf("name\n");
    scanf("%19s", temp.name);
    printf("q1:\n");
    scanf("%d", &temp.q1);
    printf("q2:\n");
    scanf("%d", &temp.q2);
    printf("q3:\n");
    scanf("%d", &temp. q3);
    //32bit system MAX_INT : 2147483647 (10digits)
    //19char  2digit 2digit 2digit\n total:30 (windows:31(\n->CRLF)
    fprintf(fp, "%-20s%3d%3d%3d\n", temp.name, temp.q1, temp.q2, temp.q3);
    fclose(fp);
}

void last_record(void){
    FILE *fp=fopen("pre-survey.txt", "rb");
    //fseek(fp, -31, SEEK_END);//for windows
    fseek(fp, -30, SEEK_END);
    fscanf(fp, "%s %d %d %d", get.name, &get.q1, &get.q2, &get.q3);
    printf("name: %s\n", get.name);
    printf("q1: %d\n", get.q1);
    printf("q2: %d\n", get.q2);
    printf("q3: %d\n", get.q3);
    fclose(fp); 
}

【讨论】:

  • int 成员有 3 位或更多位时,您将无法扫描它们,因为没有分隔空格,并且当 4 位或更多位时,它也会破坏记录长度。
  • 2digits 只是一个例子。
  • 二进制文件:使用fwrite转储记录。
  • @WeatherVane 是的,但是在上一个问题中,OP 想要使用文本文件。
猜你喜欢
  • 1970-01-01
  • 2020-10-09
  • 1970-01-01
  • 2015-01-24
  • 2018-07-15
  • 1970-01-01
  • 2019-12-28
  • 2012-02-13
  • 1970-01-01
相关资源
最近更新 更多