2016-03-25 5 views
-2

Я пытаюсь прочитать каждое слово строку. Я хочу, чтобы строка входила и первое слово вышло, потом я обработаю ее, потом вторую и так далее. Но Интернет не помогает мне, я знаю, что это, вероятно, прямо под моим носом, но я не могу понять это!Прочитайте каждое слово в строке C++

string lex(string filecontent) { 

string t = filecontent; 
getline(cin, t); 

istringstream iss(t); 
string word; 

while (iss >> word) { 
    return word; 
} 

} 
int main() { 
    string data = load_file(); // Returns a string of words 
    cout << data; 
    cout << lex(data); 
    getchar(); 
} 

Прямо сейчас это работает ... вроде него печатает много случайного бред и сумасшедших персонажей, файл я Рединг выхода нормально проверить это на соиЬ < < данных, и это то, что я ожидать. Есть идеи?

+0

Я не могу сказать, что такое ** iss >> слово ** должно быть? –

+1

Почему getline (cin, t) после того, как вы установили t, чтобы иметь содержимое вашего файла? – Pooya

+1

код не является семантически правильным, вы возвращаетесь в цикле while, так что фактически цикл while выполняется только один раз – Pooya

ответ

0

Вот решение, я думаю, что вы ищете:

int main() { 
    string data = load_file(); // Returns a string of words 

    istringstream iss(data); 

    while(iss) 
    { 
     string tok; 
     iss >> tok; 
     cout << "token: " << tok << endl; 
     //you can do what ever you want with the token here 

    } 
} 
0

Посмотрите на это, она должна помочь вам.

main.cpp

#include "stdafx.h" 
#include "Utility.h" 

int main() { 
    using namespace util; 

    std::string fileName("sample.txt"); 

    if (fileName.empty()) { 
     std::cout << "Missing or invalid filename." << std::endl; 
     return RETURN_ERROR; 
    } 

    std::string line; 
    std::vector<std::string> results; 
    std::fstream fin; 

    // Try To Open File For Reading 
    fin.open(fileName.c_str(), std::ios_base::in); 
    if (!fin.is_open()) { 
     std::cout << "Can not open file(" << fileName << ") for reading." << std::endl; 
     return RETURN_ERROR; 
    } 

    // Read Line By Line To Get Data Contents Store Into String To Be Parsed 
    while (!fin.eof()) { 
     std::getline(fin, line); 
     // Parse Each Line Using Space Character As Delimiter 
     results = Utility::splitString(line, " "); 

     // Print The Results On Each Iteration Of This While Loop 
     // This Is Where You Would Parse The Data Or Store Results Into 
     // Class Objects, Variables Or Structures. 
     for (unsigned u = 0; u < results.size(); u++) { 
      std::cout << results[u] << " "; 
     } 
     std::cout << std::endl; 
    } 

    // Close File Pointer 
    fin.close(); 

    // Now Print The Full Vector Of Results - This Is To Show You That Each 
    // New Line Will Be Overwritten And That Only The Last Line Of The File Will 
    // Be Stored After The While Loop. 
    std::cout << "\n-------------------------------------\n"; 
    for (unsigned u = 0; u < results.size(); u++) { 
     std::cout << results[u] << " "; 
    } 

    Utility::pressAnyKeyToQuit(); 
    return RETURN_OK; 
} // main 

sample.txt

Please help me parse this text file 
It spans multiple lines of text 
I would like to get each individual word 

stdafx.h - Некоторые из них включают в себя файлы, которые не могут быть необходимы, они здесь для меня есть которое требует их.

#ifndef STDAFX_H 
#define STDAFX_H 

#include <Windows.h> 

#include <stdio.h> 
#include <tchar.h> 
#include <conio.h> 

#include <string> 
#include <sstream> 
#include <fstream> 
#include <iostream> 
#include <iomanip> 
#include <vector> 
#include <array> 
#include <memory> 

#include <queue> 
#include <functional> 

#include <algorithm> 

// User Application Specific 
// #include "ExceptionHandler.h" - One Of My Class Objects Not Used Here 

namespace util { 

enum ReturnCode { 
    RETURN_OK = 0, 
    RETURN_ERROR = 1, 
}; // ReturnCode 

extern const unsigned INVALID_UNSIGNED; 
extern const unsigned INVALID_UNSIGNED_SHORT; 

} // namespace util 

#endif // STDAFX_H 

stdafx.cpp

#include "stdafx.h" 

namespace util { 

const unsigned INVALID_UNSIGNED = static_cast<const unsigned>(-1); 
const unsigned INVALID_UNSIGNED_SHORT = static_cast<const unsigned short>(-1); 

} // namespace util 

Utility.h

#ifndef UTILITY_H 
#define UTILITY_H 

namespace util { 

class Utility { 
public: 

    static void pressAnyKeyToQuit(); 

    static std::string toUpper(const std::string& str); 
    static std::string toLower(const std::string& str); 
    static std::string trim(const std::string& str, const std::string elementsToTrim = " \t\n\r"); 

    static unsigned  convertToUnsigned(const std::string& str); 
    static int   convertToInt(const std::string& str); 
    static float  convertToFloat(const std::string& str); 

    static std::vector<std::string> splitString(const std::string& strStringToSplit, const std::string& strDelimiter, const bool keepEmpty = true); 

private: 
    Utility(); // Private - Not A Class Object 
    Utility(const Utility& c); // Not Implemented 
    Utility& operator=(const Utility& c); // Not Implemented 

    template<typename T> 
    static bool stringToValue(const std::string& str, T* pValue, unsigned uNumValues); 

    template<typename T> 
    static T getValue(const std::string& str, std::size_t& remainder); 

}; // Utility 

#include "Utility.inl" 

} // namespace util 

#endif // UTILITY_H 

Utility.inl

// ---------------------------------------------------------------------------- 
// stringToValue() 
template<typename T> 
static bool Utility::stringToValue(const std::string& str, T* pValue, unsigned uNumValues) { 
    int numCommas = std::count(str.begin(), str.end(), ','); 
    if (numCommas != uNumValues - 1) { 
     return false; 
    } 

    std::size_t remainder; 
    pValue[0] = getValue<T>(str, remainder); 

    if (uNumValues == 1) { 
     if (str.size() != remainder) { 
      return false; 
     } 
    } 
    else { 
     std::size_t offset = remainder; 
     if (str.at(offset) != ',') { 
      return false; 
     } 

     unsigned uLastIdx = uNumValues - 1; 
     for (unsigned u = 1; u < uNumValues; ++u) { 
      pValue[u] = getValue<T>(str.substr(++offset), remainder); 
      offset += remainder; 
      if ((u < uLastIdx && str.at(offset) != ',') || 
       (u == uLastIdx && offset != str.size())) 
      { 
       return false; 
      } 
     } 
    } 
    return true; 
} // stringToValue 

Utility.cpp

#include "stdafx.h" 
#include "Utility.h" 

namespace util { 

// ---------------------------------------------------------------------------- 
// pressAnyKeyToQuit() 
void Utility::pressAnyKeyToQuit() { 
    std::cout << "\nPress any key to quit" << std::endl; 
    _getch(); 
} // pressAnyKeyToQuit 

// ---------------------------------------------------------------------------- 
// toUpper() 
std::string Utility::toUpper(const std::string& str) { 
    std::string result = str; 
    std::transform(str.begin(), str.end(), result.begin(), ::toupper); 
    return result; 
} // toUpper 

// ---------------------------------------------------------------------------- 
// toLower() 
std::string Utility::toLower(const std::string& str) { 
    std::string result = str; 
    std::transform(str.begin(), str.end(), result.begin(), ::tolower); 
    return result; 
} // toLower 

// ---------------------------------------------------------------------------- 
// trim() 
// Removes Elements To Trim From Left And Right Side Of The str 
std::string Utility::trim(const std::string& str, const std::string elementsToTrim) { 
    std::basic_string<char>::size_type firstIndex = str.find_first_not_of(elementsToTrim); 
    if (firstIndex == std::string::npos) { 
     return std::string(); // Nothing Left 
    } 

    std::basic_string<char>::size_type lastIndex = str.find_last_not_of(elementsToTrim); 
    return str.substr(firstIndex, lastIndex - firstIndex + 1); 
} // trim 

// ---------------------------------------------------------------------------- 
// getValue() 
template<> 
float Utility::getValue(const std::string& str, std::size_t& remainder) { 
    return std::stof(str, &remainder); 
} // getValue <float> 

// ---------------------------------------------------------------------------- 
// getValue() 
template<> 
int Utility::getValue(const std::string& str, std::size_t& remainder) { 
    return std::stoi(str, &remainder); 
} // getValue <int> 

// ---------------------------------------------------------------------------- 
// getValue() 
template<> 
unsigned Utility::getValue(const std::string& str, std::size_t& remainder) { 
    return std::stoul(str, &remainder); 
} // getValue <unsigned> 

// ---------------------------------------------------------------------------- 
// convertToUnsigned() 
unsigned Utility::convertToUnsigned(const std::string& str) { 
    unsigned u = 0; 
    if (!stringToValue(str, &u, 1)) { 
     std::ostringstream strStream; 
     strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to unsigned"; 
     throw strStream.str(); 
    } 
    return u; 
} // convertToUnsigned 

// ---------------------------------------------------------------------------- 
// convertToInt() 
int Utility::convertToInt(const std::string& str) { 
    int i = 0; 
    if (!stringToValue(str, &i, 1)) { 
     std::ostringstream strStream; 
     strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to int"; 
     throw strStream.str(); 
    } 
    return i; 
} // convertToInt 

// ---------------------------------------------------------------------------- 
// convertToFloat() 
float Utility::convertToFloat(const std::string& str) { 
    float f = 0; 
    if (!stringToValue(str, &f, 1)) { 
     std::ostringstream strStream; 
     strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to float"; 
     throw strStream.str(); 
    } 
    return f; 
} // convertToFloat 

// ---------------------------------------------------------------------------- 
// splitString() 
std::vector<std::string> Utility::splitString(const std::string& strStringToSplit, const std::string& strDelimiter, const bool keepEmpty) { 
    std::vector<std::string> vResult; 
    if (strDelimiter.empty()) { 
     vResult.push_back(strStringToSplit); 
     return vResult; 
    } 

    std::string::const_iterator itSubStrStart = strStringToSplit.begin(), itSubStrEnd; 
    while (true) { 
     itSubStrEnd = search(itSubStrStart, strStringToSplit.end(), strDelimiter.begin(), strDelimiter.end()); 
     std::string strTemp(itSubStrStart, itSubStrEnd); 
     if (keepEmpty || !strTemp.empty()) { 
      vResult.push_back(strTemp); 
     } 

     if (itSubStrEnd == strStringToSplit.end()) { 
      break; 
     } 

     itSubStrStart = itSubStrEnd + strDelimiter.size(); 
    } 

    return vResult; 

} // splitString 

} // namspace util 

В моей маленькой служебной библиотеке У меня есть функция, которая будет разделить строку, которая может использовать любой разделитель, который определяет пользователь. Он будет искать первое вхождение этого символьного разделителя, и он сохранит все перед ним в строку, и он вытолкнет эту строку в вектор строк, и он будет продолжать это для каждого появления этого символа до тех пор, пока он не закончит синтаксический анализ полная строка, которая передается ему. Затем он вернет вектор строк обратно пользователю. Это очень полезно при анализе текстовых файлов или даже просто данных с длинными строками, которые необходимо разбить. Теперь, если есть случай, когда вы разбираете текстовый файл и говорите, что вам нужно иметь более одного слова в виде одной строки, это можно сделать, но вам нужно больше работать с вашей стороны. Например, текстовый файл может иметь личную запись в одной строке.

LastName, FirstName MiddleInitial Age Phone# Address 
Cook, John S 33 1-888-323-4545 324 Complex Avenue 

А вы хотели бы, чтобы 324 Complex Avenue, чтобы быть в одной строке и вы не хотите, запятая сохраненную после последнего имени.Ваша структура в коде, чтобы хранить эту информацию может выглядеть следующим образом:

struct PersonalRecord { 
    std::string firstName; 
    std::string lastName; 
    char middleInitial; 
    unsigned age; 
    std::string phoneNumber; 
    std:string address; 
}; 

Что вы должны сделать после того, как вы читаете эти строки в из файла на той же итерации цикла в то время как вы должны сделать многократный разбор.

Сначала вы должны начать с использования временной строки и вектора строк и использовать функцию утилиты splitString с разделителем, являющимся запятой. Таким образом, это спасло бы 2 строки в временном векторе строк, которые были бы первым: Кук, а второй - остальная часть строки после запятой, включая ведущее пространство. Причина, по которой у вас есть временная строка и временный вектор строк, заключается в том, что вам нужно будет вывести значения по мере необходимости. Таким образом, в этом случае нам нужно было бы сделать следующее, но сначала, как мы разрешаем случай с несколькими словами одной строкой? Мы можем изменить строку текста в текстовом файле, чтобы быть заключен в двойные кавычки, как, например:

текстовый файл

Cook, John S 33 1-888-323-4545 "324 Complex Avenue" 
Evens, Sue A 24 1-888-323-6996 "128 Mission Rd" 
Adams, Chris B 49 1-777-293-8234 "2304 Helms Drive" 

Затем разобрать его с этой логикой потока или алгоритма.

main.cpp

#including "stdafx.h" 
#including "Utility.h" 

int main() { 
    using namespace util; 

    std::string strFilename("personalRecord.txt"); 
    std::ifstream file; 

    std::string strLine; 
    std::vector<std::string> vTemp; 
    std::vector<std::string> vResult; 

    std::vector<PersonalRecord> vData; 

    // Open File For Reading 
    file.open(strFilename.c_str()); 
    // Check For Error Of Opening File 
    if (!file.is_open()) { 
     std::cout << "Error opening file (" << strFilename << ")" << std::endl; 
     return RETURN_ERROR; 
    } 

    // Continue Until End Of File 
    while(!file.eof()) { 
     // Get Single Full Line Save To String 
     std::getline(file, strLine); 

     // Check For Comma 
     vTemp = Utility::splitString(strLine, ","); 
     // Save First String For Laster 
     std::string lastName = vTemp[0]; 

     // Split String Using A Double Quote Delimiter Delimiter 
     vTemp = Utility::splitString(vTemp[1], "\""); 

     // Check To See If vTemp Has More Than One String 
     if (vTemp.size() > 1) { 
      // We Need To Use Pop Back To Account For Last Double Quote 
      vTemp.pop_back(); // Remove Last Double Quote 
      std::string temp = vTemp.back(); 
      vTemp.pop_back(); // Remove Wanted String From vTemp. 

      // At This Point We Need To Parse vTemp Again Using Space Delimiter 
      vResult = Utility::splitString(vTemp[0], " "); 

      // Need To Account For Leading Space In Vector 
      vResult[0].erase(); 
      // Need To Account For Last Space In Vector 
      vResult.pop_back(); 

      // Now We Can Push Our Last String Back Into vResult 
      vResult.push_back(temp); 

      // Replace The First String " " With Our LastName 
      vResult[0] = lastName; 

     } else if (vTemp.size() == 1) { 
      // Just Parse vTemp Using Space Delimiter 
      vResult = Utility::splitString(vTemp[0], " "); 
     } 


     // Print Out Results For Validity 
     for (unsigned u = 0; u < vResult.size(); u++) { 
      std::cout << vResult.at(u) << " "; 
     } 
     std::cout << std::endl; 

     // Here Is Where You Would Populate Your Variables, Structures Or Classes On Each Pass Of The While Loop. 
     // With This Structure There Should Only Be 8 Entries Into Our vResult 
     PersonalRecord temp; 
     temp.lastName  = vResult[0]; 
     temp.firstName  = vResult[1]; 
     temp.middleInitial = vResult[2][0]; 
     temp.age   = Utility::convertToUnsigned(vResult[3]); 
     temp.phoneNumber = vResult[4]; 
     temp.address  = vResult[5]; 

     vData.push_back(temp); 
    } // while 

    // Close File 
    file.close(); 

    std::cout << std::endl << std::endl; 

    // Print Using Structure For Validity 
    std::cout << "---------------------------------------\n"; 
    for (unsigned u = 0; u < vData.size(); u++) { 
     std::cout << vData[u].lastName << " " 
        << vData[u].firstName << " " 
        << vData[u].middleInitial << " " 
        << vData[u].age << " " 
        << vData[u].phoneNumber << " " 
        << vData[u].address << std::endl; 
    } 

    Utility::pressAnyKeyToQuit(); 
    return RETURN_OK; 
} // main 

Таким образом, и рассмотрение и должно быть принято при разборе текста или строки. Вы должны учитывать каждый символ, включая возвращаемые каретки, пробелы и т. Д. Таким образом, необходимо учитывать формат, в котором записывается текстовый файл. Да splitString() также будет анализировать вкладки, вам просто нужно будет использовать «\ t» для вкладок и т. Д. Просто помните, что он будет делать раскол в каждом случае. Поэтому, если у вас есть предложение с двоеточием «:» в нем, но затем вы решите использовать двоеточие в качестве разделителя между значениями, он также разделит это предложение. Теперь у вас могут быть разные правила для каждой строки текста из файла, и если вы знаете, в какой строке вы находитесь, вы можете проанализировать каждую строку соответственно. Вот почему большинство людей предпочитают писать свой код для чтения и разбора двоичных файлов, потому что его гораздо проще программировать, а затем писать текстовый синтаксический анализатор.

Я решил использовать структуру PersonalRecord, чтобы показать вам, как вы можете извлекать строки из строки текста и преобразовывать их в базовые типы, такие как int, float или double, используя некоторые из моих других функций в моем классе Utility. Все методы в этом классе объявляются как static, а конструктор - private, поэтому имя класса действует как обертка или пространство имен, так сказать. Вы не можете создать экземпляр Utility util; // invalid object. Просто включите заголовочный файл и используйте имя класса с оператором разрешения области :: для доступа к любой из функций и убедитесь, что вы используете namespace util.

Смежные вопросы