首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在C中读取文件的最后一行

在C中读取文件的最后一行
EN

Stack Overflow用户
提问于 2022-05-02 10:54:24
回答 2查看 96关注 0票数 0

我试图思考如何读取文件的最后一行的逻辑,但我无法给出答案。ACCOUNTNUM信息是一个结构。我的.dat文件已经有3个acc号码了。在这里,我想知道如何得到最后一个帐号/行,即2022-3。

这是函数

代码语言:javascript
运行
复制
LastAccountNumber(){
    ACCOUNTNUM info;
    file = fopen("acctNumbers.dat","r");
    char firstAcc[50]="2022-1";//ignore this I was gonna compare this with the last line.
    
    while((fread(&info,sizeof(struct accountNum),1,file))==1){
            printf("\nAcc No %s",info.sAccountNum);
    }
        
    }
    
}

这是我的结构

代码语言:javascript
运行
复制
struct accountNum{
    int sequence;
    char sAccountNum[16];
};
typedef struct accountNum ACCOUNTNUM;

acctNumbers.dat文件的内容。

代码语言:javascript
运行
复制
2022-1       ú·   2022-2       ú·   2022-3       ú·
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-05-02 12:17:56

您可以在循环中调用fread,直到它返回0为止,然后打印最后一个记录读:

代码语言:javascript
运行
复制
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct accountNum
{
    int sequence;
    char sAccountNum[16];

} ACCOUNTNUM;

int main( void )
{
    FILE *fp;
    ACCOUNTNUM info;
    bool success = false;

    //open file and verify that it is open
    fp = fopen( "acctNumbers.dat", "r" );
    if ( fp == NULL )
    {
        fprintf( stderr, "Error opening file!\n" );
        exit( EXIT_FAILURE );
    }

    //skip to last record
    while( ( fread( &info, sizeof info, 1, fp) ) == 1 )
    {
        //set variable to indicate that we have found at
        //least one record
        success = true;
    }

    //print last record, if it exists
    if ( success )
        printf( "Acc No: %s\n", info.sAccountNum );
    else
        printf( "No records found.\n" );

    //cleanup
    fclose( fp );
}

但是,只有当您确信最后一个fread不会执行部分读取时,即当您确信文件大小是sizeof(ACCOUNTNUM)的确切倍数时,这才能保证工作。因为如果fread确实执行了部分读取,那么缓冲区内容将是不确定的。

如果不能排除部分读取的可能性,则可以使用两个缓冲区进行读取,并交替使用它们:

代码语言:javascript
运行
复制
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct accountNum
{
    int sequence;
    char sAccountNum[16];

} ACCOUNTNUM;

int main( void )
{
    FILE *fp;
    ACCOUNTNUM info[2];
    int current_index = 0;
    bool success = false;
    size_t ret;

    //open file and verify that it is open
    fp = fopen( "acctNumbers.dat", "r" );
    if ( fp == NULL )
    {
        fprintf( stderr, "Error opening file!\n" );
        exit( EXIT_FAILURE );
    }

    for (;;) //infinite loop, equivalent to while(1)
    {
        //read record from file
        ret = fread( &info[current_index], sizeof *info, 1, fp);

        //swap buffer index
        current_index = current_index == 0 ? 1 : 0;

        //restart loop if successful
        if ( ret == 1 )
        {
            //set variable to indicate that we have found at
            //least one record
            success = true;

            continue;
        }

        //break out of loop
        break;
    }

    //print last record, if it exists
    if ( success )
        printf( "Acc No: %s\n", info[current_index].sAccountNum );
    else
        printf( "No records found.\n" );

    //cleanup
    fclose( fp );
}

或者,您可以使用单个缓冲区,通过交换第二个和第三个函数参数来改变调用函数fread的方式,以便检测是否发生了部分读取。如果确实发生这种情况,则可以打印错误消息并终止程序。

代码语言:javascript
运行
复制
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct accountNum
{
    int sequence;
    char sAccountNum[16];

} ACCOUNTNUM;

int main( void )
{
    FILE *fp;
    ACCOUNTNUM info;
    bool success = false;
    size_t ret;

    //open file and verify that it is open
    fp = fopen( "acctNumbers.dat", "r" );
    if ( fp == NULL )
    {
        fprintf( stderr, "Error opening file!\n" );
        exit( EXIT_FAILURE );
    }

    //read one record per loop iteration
    while ( ( ret = fread( &info, 1, sizeof info, fp) ) != 0 )
    {
        //verify that no partial read occurred
        if ( ret != sizeof info )
        {
            fprintf( stderr, "Error: Partial read detected!\n" );
            exit( EXIT_FAILURE );
        }

        //set variable to indicate that we have found at
        //least one record
        success = true;
    }

    //print last record, if it exists
    if ( success )
        printf( "Acc No: %s\n", info.sAccountNum );
    else
        printf( "No records found.\n" );

    //cleanup
    fclose( fp );
}
票数 2
EN

Stack Overflow用户

发布于 2022-05-02 11:34:33

您正在逐个读取记录并将其存储在info中,循环结束时存储在info中的元素ACCOUNTNUM完全是文件中的最后一条记录,下面的代码对您的记录做了轻微的修改,说明了这一点:

代码语言:javascript
运行
复制
#include <stdio.h>

struct accountNum {
    int sequence;
    char sAccountNum[16];
};
typedef struct accountNum ACCOUNTNUM;
代码语言:javascript
运行
复制
int LastAccountNumber(ACCOUNTNUM* info) {

    int success = 0;
    FILE* file = fopen("acctNumbers.dat", "rb");
    if (file == NULL) {
        return -1;  // Allows you to document different types of errors
    }
    while ((fread(info, sizeof(struct accountNum), 1, file)) == 1) {
        success = 1;
    }
    fclose(file);
    return success;
}

int main() {
    ACCOUNTNUM N[] = {{123, "2022-1"}, {111, "2022-2"}, {321, "2022-3"}};
    FILE* file = fopen("acctNumbers.dat", "wb");

    fwrite(N, 1, sizeof N, file);
    fclose(file);

    ACCOUNTNUM info;

    if (LastAccountNumber(&info) == 1) //if -1 couldn't open file, 0 no record read
        printf("\nAcc No %s", info.sAccountNum);
}

将产出:

代码语言:javascript
运行
复制
Acc No 2022-3

这正是文件中的最后一个元素。

现场样本:https://onlinegdb.com/q760Ow1vQc

注意,您应该验证fopen的返回值,以确认对该文件的正确访问。还建议您在完成该文件后关闭该文件。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72085673

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档