Прочитать файл и извлечь только определенную часть - PullRequest
1 голос
/ 25 ноября 2010
ifstream toOpen;
openFile.open("sample.html", ios::in); 

if(toOpen.is_open()){
    while(!toOpen.eof()){
        getline(toOpen,line);
        if(line.find("href=") && !line.find(".pdf")){   
                start_pos = line.find("href"); 
        tempString = line.substr(start_pos+1); // i dont want the quote
            stop_pos = tempString .find("\"");
                string testResult = tempString .substr(start_pos, stop_pos);
        cout << testResult << endl;
        }
    }

    toOpen.close();
}

То, что я пытаюсь сделать, это извлечь значение "href".Но я не могу заставить его работать.

РЕДАКТИРОВАТЬ:

Благодаря подсказке Тони я использую это:

if(line.find("href=") != std::string::npos ){   
    // Process
}

это работает !!

Ответы [ 2 ]

1 голос
/ 25 ноября 2010

Я бы не советовал пытаться разобрать HTML таким образом.Если вы не очень много знаете об источнике и совершенно уверены в том, как он будет отформатирован, есть вероятность, что все, что вы делаете, будет иметь проблемы.HTML является уродливым языком с (почти) противоречивой спецификацией, которая (например) говорит, что определенные вещи недопустимы - но затем продолжает рассказывать, как вам необходимо их интерпретировать в любом случае.

Хуже того, почти любой символ может (хотя бы потенциально) быть закодирован любым из по меньшей мере трех или четырех различных способов, поэтому если вы сначала не сканируете (и не выполняете) правильные преобразования (в правильном порядке), вы можете в конечном итоге пропустить законные ссылки и / или в том числе «фантомные» ссылки.

Возможно, вы захотите посмотреть ответы на этот предыдущий вопрос , чтобы получить предложения по использованию анализатора HTML.

0 голосов
/ 25 ноября 2010

Для начала вам может понадобиться несколько ярлыков в том, как вы пишете цикл над строками, чтобы сделать его более понятным. Вот обычный цикл чтения строки за раз с использованием iostreams C ++:

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

int main ( int, char ** )
{
    std::ifstream file("sample.html");
    if ( !file.is_open() ) {
        std::cerr << "Failed to open file." << std::endl;
        return (EXIT_FAILURE);
    }
    for ( std::string line; (std::getline(file,line)); )
    {
        // process line.
    }
}

Что касается внутренней части, обрабатывающей линию, то здесь есть несколько проблем.

  1. Не компилируется. Я полагаю, это то, что вы имели в виду под "Я не могу заставить это работать". Задавая вопрос, это та информация, которую вы, возможно, захотите предоставить, чтобы получить хорошую помощь.
  2. Существует путаница между именами переменных temp и tempString и т. Д.
  3. string::find() возвращает большое положительное целое число для обозначения недопустимых позиций (size_type без знака), поэтому вы всегда будете входить в цикл, если не найдено совпадение, начинающееся с позиции символа 0, в этом случае вы, вероятно, сделать хотите войти в цикл.

Вот простой тестовый контент для sample.html.

<html>
    <a href="foo.pdf"/>
</html>

Вставить следующее внутри цикла:

if ((line.find("href=") != std::string::npos) &&
    (line.find(".pdf" ) != std::string::npos))
{
    const std::size_t start_pos = line.find("href");
    std::string temp = line.substr(start_pos+6);
    const std::size_t stop_pos = temp.find("\"");
    std::string result = temp.substr(0, stop_pos);
    std::cout << "'" << result << "'" << std::endl;
}

Я действительно получаю вывод

'foo.pdf'

Однако, как отметил Джерри, вы, возможно, не захотите использовать это в производственной среде. Если это простое домашнее задание или упражнение по использованию библиотек <string>, <iostream> и <fstream>, то продолжайте такую ​​процедуру.

...