2010-11-21 93 views
0

我有下面的代碼不起作用:字符串::找到返回值爲-1時,它的預期返回值0 [C++]

string line; 
string line_sub; 
size_t open_tag_start; 
const string open_tag = "<image>"; 
const int open_len = open_tag.length() + 1; 

open_tag_start = line.find(open_tag); 
line_sub = line.substr(open_tag_start, open_len); 

當我嘗試運行此代碼,我得到以下錯誤:

 
terminate called after throwing an instance of 'std::out_of_range' 
what(): basic_string::substr 
Aborted (core dumped) 

我已經想通了,這個錯誤發生,因爲line.find線的-1值返回變量open_tag_start。我可以通過將0的值硬編碼到變量open_tag_start來糾正問題,但我需要這種通用算法,以便能夠在行中的任意點找到標記,因此它必須是變量。任何人都可以看到我在這裏做錯了嗎?

這裏有一些更多的信息。

我這段代碼的目標,如果從string line提取string line_sub,其中確實包含一個字符串,而當我設size_t open_tag_start = 0,我能夠編譯和執行代碼,並觀察預期的輸出。 line不是空的,我的問題是,當我更換

line_sub = line.substr(open_tag_start, open_len); 

line_sub = line.substr(0, open_len); 

我的問題解決了,我可以編譯和執行代碼。

這是我的程序的簡短版本,其中只包含導致問題的部分。試圖編譯這段代碼將產生上面詳述的錯誤信息。該文件rss.xml是engadget.com http://www.engadget.com/rss.xml

#include <iostream> 
#include <string> 
#include <sstream> 
#include <fstream> 
#include <cstring> 
using namespace std; 

void get_tag_contents(ifstream& rssfile, string line, string open_tag); 

int main() 
{ 
    const string open_tag = "<image>"; 

    ifstream rssfile; 
    rssfile.open("rss.xml"); 
    string line; 

    getline(rssfile, line, '\n'); 
    get_tag_contents(rssfile, line, open_tag); 

    return 0; 
} 

void get_tag_contents(ifstream& rssfile, string line, string open_tag) 
{ 
    const int open_len = open_tag.length() + 1; 
    size_t open_tag_start; 
    string line_sub; 

    open_tag_start = line.find(open_tag); 
    line_sub = line.substr(open_tag_start, open_len); 
} 
+0

請發佈一個簡短的,自包含的程序來編譯和演示問題。在你省略的任何代碼中都有一個重要的細節。 – 2010-11-21 19:38:19

+0

我用代碼更新了我的問題。 – 2010-11-21 19:57:03

回答

3

RSS提要除非你忽略了一些代碼,line是一個空字符串,所以當然find失敗。這是你的期望,是錯誤的,而不是find函數—就是這樣!

請注意,使用C++字符串時,不需要補償'\0'。擺脫+ 1

+2

...因爲size_t是無符號的,所以它不返回'-1',它返回'string :: npos'。 – bgporter 2010-11-21 19:11:59

+0

@bgporter - 儘管如此,string :: npos在標準中被定義爲值爲-1。 – 2010-11-21 19:20:22

+1

@PigBen:從技術上講,它不是 - 也不能 - 被定義爲值爲-1,因爲這在值的範圍之外可表示爲「size_type」。它被定義爲一個初始值爲'-1'的'size_type',所以它的值爲'-1'_after_轉換爲size_type,它是一個很大的正數。 – 2010-11-21 19:25:34

2

如果在字符串中找不到子字符串,則find()方法將返回std::string::npos,它是值爲-1的size_type。當你撥打substr()並且open_tag_start等於-1時,這就是拋出out_of_range錯誤的原因。

+2

從技術上講,'std :: string :: size_type'不能取值爲'-1',因爲它是一個無符號類型。 'std :: string :: npos'是可表示爲'size_type'的最大數字,與'-1'轉換爲'size_type'相同,但不是'-1'。 – 2010-11-21 19:22:19

+0

我說我的問題錯了,我提供了一個更新,使事情更清晰一點。 – 2010-11-21 19:36:25

0

那麼,你確定line包含<image>?有一點需要考慮的是<ImaGe>可能會以某種方式被大寫。另外,我不太明白你想要做什麼,因爲line_sub(假設你的代碼有效)只會返回enter code here和之後的下一個字符。你想達到什麼目的?

請記住清理您的返回值。如果查找返回-1,則處理該問題或拋出錯誤。

1

正如其他人已經注意到,你必須檢查find()的返回值,以防搜索失敗。

std::string line("this is <image> a test"); 
std::string line_sub; 
const std::string open_tag = "<image>"; 

size_t open_tag_start = line.find(open_tag); 

if (open_tag_start != std::string::npos) 
{ 
    line_sub = line.substr(open_tag_start, open_tag.length()); 
} 

std::cout << line << "\n" << line_sub << "\n";