从读取文件中的C / C最后n行++ [英] reading last n lines from file in c/c++

查看:325
本文介绍了从读取文件中的C / C最后n行++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看过很多帖子,但没有找到像我想要的。结果
我得到的输出错误:

I have seen many posts but didn't find something like i want.
I am getting wrong output :

ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ......  // may be this is EOF character

走进无限循环。

我的算法:


  1. 转到文件末尾。

  2. 1指针
  3. 降低位置,并通过读取字符
    字符。

  4. 退出,如果我们发现我们的10号线,或我们到达开头的文件。

  5. 现在,我会扫描整个文件直到EOF,并打印出来//不是在code语言实现的。

code:

#include<iostream>
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<string.h>

using namespace std;
int main()
{
    FILE *f1=fopen("input.txt","r");
    FILE *f2=fopen("output.txt","w");
    int i,j,pos;
        int count=0;
        char ch;
        int begin=ftell(f1);
        // GO TO END OF FILE
        fseek(f1,0,SEEK_END);
        int end = ftell(f1);
        pos=ftell(f1);

        while(count<10)
        {
            pos=ftell(f1);
            // FILE IS LESS THAN 10 LINES
            if(pos<begin)
                break;
            ch=fgetc(f1);
            if(ch=='\n')
                count++;
            fputc(ch,f2);
            fseek(f1,pos-1,end);
        }
    return 0;
}

UPD 1:

改code:现在刚1的错误 - 如果输入了线,如

changed code: it has just 1 error now - if input has lines like

3enil
2enil
1enil

it prints 10 lines only

line1
line2
line3ÿine1
line2
line3ÿine1
line2
line3ÿine1
line2
line3ÿine1
line2

PS:结果
1.在Windows上工作,在记事本++

PS:
1. working on windows in notepad++


  1. 这是不是功课

  1. this is not homework

我也想做到这一点,而无需使用任何更多的内存或使用STL的。

also i want to do it without using any more memory or use of STL.

我在练,以提高我的基本知识,所以请不要发布任何函数(如尾-5 TC)。

i am practicing to improve my basic knowledge so please don't post about any functions (like tail -5 tc.)

请有利于提高我的code。

please help to improve my code.

推荐答案

有一些与你的code问题。最多
重要的是,你从来不检查任何功能
成功了。并保存结果的 FTELL INT 不是
一个很好的主意。然后是测试 POS&L​​T;开始;
这一点,如果有错误时才会发生。而事实上,
你把龟etc 的结果在字符(这将导致
在信息的损失)。而事实上,在第一读你
做的是在文件的结尾,所以将失败(和一次流进入
错误状态,它就留在那里)。而事实上,你不能
可靠地做算术由 FTELL 返回的值(除
Unix下)如果该文件是在文本模式下打开。

There are a number of problems with your code. The most important one is that you never check that any of the functions succeeded. And saving the results an ftell in an int isn't a very good idea either. Then there's the test pos < begin; this can only occur if there was an error. And the fact that you're putting the results of fgetc in a char (which results in a loss of information). And the fact that the first read you do is at the end of file, so will fail (and once a stream enters an error state, it stays there). And the fact that you can't reliably do arithmetic on the values returned by ftell (except under Unix) if the file was opened in text mode.

喔,和没有EOF字符; 'Y'是一个完全有效的
字符(0xFF的拉美-1)。一旦指定的返回值
龟etc 到的字符,你已经失去了任何可能性,以测试
文件结尾。

Oh, and there is no "EOF character"; 'ÿ' is a perfectly valid character (0xFF in Latin-1). Once you assign the return value of fgetc to a char, you've lost any possibility to test for end of file.

我想补充一点,每次读向后一个字符是
极其低效。通常的解决办法是分配
一个足够大的缓冲区,再算上其中的的'\\ n'

I might add that reading backwards one character at a time is extremely inefficient. The usual solution would be to allocate a sufficiently large buffer, then count the '\n' in it.

编辑:

只需code的快速位给的理念是:

Just a quick bit of code to give the idea:

std::string
getLastLines( std::string const& filename, int lineCount )
{
    size_t const granularity = 100 * lineCount;
    std::ifstream source( filename.c_str(), std::ios_base::binary );
    source.seekg( 0, std::ios_base::end );
    size_t size = static_cast<size_t>( source.tellg() );
    std::vector<char> buffer;
    int newlineCount = 0;
    while ( source 
            && buffer.size() != size
            && newlineCount < lineCount ) {
        buffer.resize( std::min( buffer.size() + granularity, size ) );
        source.seekg( -static_cast<std::streamoff>( buffer.size() ),
                      std::ios_base::end );
        source.read( buffer.data(), buffer.size() );
        newlineCount = std::count( buffer.begin(), buffer.end(), '\n');
    }
    std::vector<char>::iterator start = buffer.begin();
    while ( newlineCount > lineCount ) {
        start = std::find( start, buffer.end(), '\n' ) + 1;
        -- newlineCount;
    }
    std::vector<char>::iterator end = remove( start, buffer.end(), '\r' );
    return std::string( start, end );
}

这是一个有点弱的错误处理;特别是,你
可能要到无法打开区分的
一个文件和任何其他错误。 (无其他错误的发生,
但你永远不知道。)

This is a bit weak in the error handling; in particular, you probably want to distinguish the between the inability to open a file and any other errors. (No other errors should occur, but you never know.)

此外,这是纯粹的Windows,并且假定实际
文件包含纯文本,不包含任何'\\ r'
不是一个CRLF的一部分。 (对于Unix,只是下降的旁边
最后一行。)

Also, this is purely Windows, and it supposes that the actual file contains pure text, and doesn't contain any '\r' that aren't part of a CRLF. (For Unix, just drop the next to the last line.)

这篇关于从读取文件中的C / C最后n行++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆