C ++ Переписать файл, но пропустить все перед словом - PullRequest
6 голосов
/ 19 июня 2011

Я использую Visual C ++ Express 2010 ... и я очень плохо знаком с C ++.

Я хочу прочитать файл, затем удалить все перед словом "<- START ->"и перепишите файл с остальными.

Вот код, который я получил для чтения файла:

#include "stdafx.h"
#include <iostream>
#include <fstream>

using namespace std;

int main() {
  ifstream myReadFile;
  myReadFile.open("text.txt");
  char output[500];
  int found;
  int line;
  if (myReadFile.is_open()) {
    line = 0;
 while (!myReadFile.eof()) {
     myReadFile >> output;
     if(line > 20) {
         cout << output;
     }
     line++;
 }
}
myReadFile.close();
system("PAUSE");
return 0;
}

Большое спасибо заранее.

Ответы [ 5 ]

7 голосов
/ 19 июня 2011

Прежде всего, ваш while цикл неправильный.Фактически, такой цикл while равен почти всегда неверно.

Вы должны писать цикл следующим образом:

while (myReadFile >> output) 
{
     if (line > 20) {
         cout << output;
     }
     line++;
}

Ваш цикл while(!myReadFile.eof()) неправильный,поскольку флаг eof (или любой другой флаг сбоя) установлен после , попытка чтения из потока не удалась;это означает, что если попытка чтения не удалась, вы все равно выводите, потому что вы все еще находитесь внутри цикла, а остальная часть кода в цикле все еще выполняется, когда это на самом деле не должно.

Inмоя версия, однако, если попытка чтения (т.е. myReadFile >> output) не удалась, то возвращенный std::istream& неявно преобразуется в false, и цикл немедленно завершается.И если это не сработает, возвращенный поток неявно преобразуется в true.

Кстати, мне кажется, что вы хотите читать построчно, вместо этогоиз слова в слово.Если это так, то вы должны написать это как:

std::string sline; //this should be std::string
while (std::getline(myReadFile, sline))
{
     if (line > 20) {
         cout << sline;
     }
     line++;
}

Снова std::getline возвращает std::istream.Если чтение было успешным, возвращенный поток неявно преобразуется в true, и цикл продолжится, или, если он был неудачным, то неявно преобразуется в false ицикл выйдет.

2 голосов
/ 19 июня 2011
std::string file_contents = LoadFileAsString("text.txt");
std::string::size_type offset = file_contents.find("<--START-->");
std::ofstream("text.txt") << file_contents.c_str() + offset;

С LoadFileAsString, определенной следующим образом:

std::string LoadFileAsString(const std::string & fn)
{
    std::ifstream fin(fn.c_str());

    if(!fin)
    {
        std::string what = "LoadFileAsString() : Failed to open file \"";
        what += fn + '\"';
        throw std::runtime_error(what);
    }

    std::ostringstream oss;
    oss << fin.rdbuf();

    return oss.str();
}
1 голос
/ 19 июня 2011

Вот версия, которая не должна считывать весь файл в память. Примечание: использует C stdio, а не iostreams (только потому, что я знаю C stdio намного лучше); читает из стандартного ввода, пишет в стандартный вывод.

#include <stdio.h>

int
main(void)
{
    int c;
    enum { BOF, LT, D1, D2, S, T1, A, R, T2, D3, D4, GO } state = BOF;
    while ((c = getchar()) != EOF)
        switch (state)
        {
        case BOF: state = c == '<' ? LT : BOF; break;
        case LT:  state = c == '-' ? D1 : c == '<' ? LT : BOF; break;
        case D1:  state = c == '-' ? D2 : c == '<' ? LT : BOF; break;
        case D2:  state = c == 'S' ? S  : c == '<' ? LT : BOF; break;
        case S:   state = c == 'T' ? T1 : c == '<' ? LT : BOF; break;
        case T1:  state = c == 'A' ? A  : c == '<' ? LT : BOF; break;
        case A:   state = c == 'R' ? R  : c == '<' ? LT : BOF; break;
        case R:   state = c == 'T' ? T2 : c == '<' ? LT : BOF; break;
        case T2:  state = c == '-' ? D3 : c == '<' ? LT : BOF; break;
        case D3:  state = c == '-' ? D4 : c == '<' ? LT : BOF; break;
        case D4:  state = c == '>' ? GO : c == '<' ? LT : BOF; break;
        case GO:  putchar(c); break;
        }
    return 0;
}
0 голосов
/ 18 сентября 2011

Ну, здесь уже есть много ответов, но вот еще один.Он очень короткий, потому что он очень простой, он однопроходный, идеально переносимый и ничего не выделяет в куче.

#include <iterator>
#include <istream>
#include <ostream>

void strip_file_beginning( std::istream &in_s, std::ostream &out_s ) {
    std::istreambuf_iterator< char > in( in_s ), in_end;
    std::ostreambuf_iterator< char > out( out_s );
    static char const start_word[] = "<--START-->"; // mind the terminating '\0'

    for ( char const *pen = start_word; pen != start_word + sizeof start_word - 1
                                  && in != in_end; ++ in ) {
        if ( * in == * pen ) ++ pen;
        else pen = start_word;
    }

    std::copy( in, in_end, out );
}

http://ideone.com/zh9bd

0 голосов
/ 20 июня 2011

Вы не можете прочитать файл, затем удалить все до слова "<- START ->" и переписать файл с остальными , кроме как в памяти, как ответил Бенджамин.В противном случае вам нужен промежуточный файл.Во всех случаях вы должны обрабатывать различные условия ошибки.Это должно сделать это:

#include <iostream>
#include <fstream>
#include <string>
#include <cstdio>

using namespace std;

int main() 
{   
    if (rename("Text.txt", "Old.txt") == 0)
    {
        try
        {
            ifstream in("Old.txt");
            ofstream out("Text.txt");
            string line;
            while (getline(in, line))
            {
                size_t pos = line.find("<--START-->");
                if (pos != string::npos)
                {
                    string remain = line.substr(pos + 11);
                    if (remain.size())
                        out << remain << endl;
                    break;
                }
            }
            while (getline(in, line))
                out << line << endl;
        }
        catch (exception&)
        {
            remove("Text.txt");
            rename("Old.txt", "Text.txt");
            cerr << "Error processing file" << endl;
            return 1;
        }
        remove("Old.txt");
        return 0; 
    }
    cerr << "Error renaming file, access right?" << endl;
    return 2; 
} 

.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...