2016-03-25 41 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(); 
} 

現在這個工程...排序它打印出大量的隨機胡言亂語和瘋狂的字符,該文件的我正在讀的輸出是好的我檢查這個在COUT < <數據,它是我期望。有任何想法嗎?

+0

我不能說什麼** iss >>行爲應該是? –

+1

爲什麼getline(cin,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大道是一個字符串也不想姓氏之後存儲的逗號。你的代碼來存儲這些信息結構可能是這樣的:

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

什麼,你必須做你讀,從您的文件這一行後的while循環相同的迭代,你必須做的是多重解析。

您將首先使用字符串的臨時字符串和向量開始,並使用實用函數splitString,其中的分隔符是逗號。所以這會在字符串的臨時向量中保存2個字符串,第一個是:Cook,第二個是包含前導空格的逗號後面的其餘行。您有temp字符串和temp字符串的原因是您需要在需要時彈出值。因此,在這種情況下,我們必須執行以下操作,但首先,我們如何將多個單詞解析爲一個字符串?我們可以改變文本行的文本文件用雙引號括起來這樣:

文本文件

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結構向您展示如何從一行文本中提取字符串,並使用我的Utility類中的一些其他函數將它們轉換爲基本類型,如int,float或double。這個類中的所有方法都聲明爲靜態的,並且構造函數是私有的,所以類名可以用作包裝器或命名空間。您無法創建Utility util; // invalid object的實例。只需包含頭文件,並使用範圍解析運算符::的類名稱來訪問任何函數,並確保您使用的是namespace util

相關問題