2016-11-30 45 views
0

我創建了一個名爲Employee的類,私有,我有一個Name作爲string。這裏是我的類聲明:在類的函數中創建字符串時出錯

class Employee 
{ 
    string Name; 
public: 
    Employee(); 
    void SetName(string); 
    void StringToEmployee(string); 
    ~Employee(); 
} 

這是StringToEmployee(string)方法的定義:

void Employee::StringToEmployee(string s) 
{ 
    char *first = s, *end = s+strlen(s), *last = NULL; 
    last = find(first, end, ','); 
    string temp(first, last- first); 
    SetName(temp); 
} 

當我調試的行string temp(first, last- first)出現的錯誤,它似乎編譯器不允許我構建方法中的新字符串。因爲我也改成了string temp;,然後temp.assign(first, last-first)。錯誤仍然存​​在。我怎麼能在一個方法中創建一個新的字符串?

+1

['std :: strlen'](http://en.cppreference.com/w/cpp/string/byte/strlen)函數是一個C函數。它需要一個C空字符串作爲輸入。即一個指向'char'的指針。請嘗試使用['std :: string'函數](http://en.cppreference.com/w/cpp/string/basic_string)。 –

+0

你究竟有什麼'string'定義爲第一位?你的[MCVE]其餘部分在哪裏(https://stackoverflow.com/help/mcve)?而且,什麼是錯誤? – Useless

回答

0

由於某種原因,您想將std::string設置爲char*。 從其他代碼來看,要與原char陣列工作,所以,你需要把正確的指針firstlast這樣的:

char *first = &s[0], *end = (&s[0]) + strlen(s.c_str()), *last = NULL; 

而且這一部分:

string temp(first, last- first); 

是不正確,因爲last - first是指針,而據我所知,你想使用std::string(const char*, size_t)的構造函數。相反,您使用的是基於迭代器的構造函數,並且系統正確地死去,因爲第一個指針比第二個指針大。

如您所見,您的方法很容易出錯。我建議重新做這部分代碼,使用迭代器,像這樣:

void Employee::StringToEmployee(string s) 
{ 
    auto found = find(s.begin(), s.end(), ','); 
    string temp(s.begin(), found); 
    SetName(temp); 
} 
1

您應該使用迭代器和採取的標準庫的功能優勢,而不是原始指針和C風格的字符串函數。這不僅會讓你更習慣和更容易理解C++代碼,但它也會隱含地解決你的許多錯誤。

首先,如下StringToEmployee實施應被改寫:

void Employee::StringToEmployee(std::string s) 
{ 
    const std::string temp(s.begin(), 
          std::find(s.begin(), s.end(), ','); 
    SetName(temp); 
} 

但是因爲你沒有修改s參數,不需要它的副本,你應該不斷引用傳遞:

void Employee::StringToEmployee(const std::string& s) 
{ 
    const std::string temp(s.begin(), 
          std::find(s.begin(), s.end(), ','); 
    SetName(temp); 
} 

此外,你應該考慮重新設計你的Employee類。目前,您有一個默認的構造函數,它會創建一個無效的Employee對象,然後您具有成員函數,允許您通過設置其成員將該無效的Employee對象轉換爲有效的對象。相反,你可以有一個構造函數,可以一步完成所有這些初始化。您的代碼不僅更清晰,更易於理解,而且效率更高!

也許是這樣的:

class Employee 
{ 
    std::string Name;       // name of this employee 

public: 
    Employee(const std::string& name);   // create Employee with specified name 
    void SetName(const std::string& newName); // change this employee's name 
    ~Employee(); 
}; 



Employee::Employee(const std::string& name) 
    : Name(s.begin(), std::find(s.begin(), s.end(), ',')) 
{ } 

void Employee::SetName(const std::string& newName) 
{ 
    Name = std::string(s.begin(), std::find(s.begin(), s.end(), ',')); 
} 

Employee::~Employee() 
{ } 

一對夫婦的快速說明:

  • 你會看到,我總是明確地寫出來std::每當我使用一個類從標準庫的命名空間。這是一個非常好的習慣,打出額外的5個字符並不難。這特別重要,因爲using namespace std;a really bad habit to get into
  • 我傳遞的對象(如字符串),我不需要修改或通過常量引用的方法的副本。這既容易推理,也可能更有效(因爲它避免了不必要的副本)。
  • 在構造函數的內部,我使用了看起來像一個有趣的語法,涉及冒號和一些括號。這被稱爲member initialization list,這是你應該習慣看的東西。這是類的構造函數初始化其成員變量的標準方式。
相關問題