2016-03-21 75 views
-4

編輯:解決方案必須針對Microsoft Visual Studio 2012進行編譯。String.length woes

我想使用已知的字符串長度來聲明另一個長度相同的字符串。

推理是第二個字符串將作爲對第一個字符串的操作的容器,對於第一個字符串必須是非易失性的。

例如

const string messy "a bunch of letters"; 

string dostuff(string sentence) { 
    string organised NNN????? // Idk, just needs the same size. 
    for (x = 0; x < NNN?; x++) { 
     organised[x] = sentence[x]++; // Doesn't matter what this does. 
    } 
} 

在上述兩種情況下,聲明和退出條件,NNN?代表'凌亂'的長度。

如何在編譯時發現長度?

+0

'std :: string'具有'append' /'+ ='。 – Michael

+0

Michael。我不明白?我不想追加任何東西。我想在編譯時導出字符串長度。您的示例在編譯時如何工作? –

回答

2

std::string有兩個constructors它可以符合你的目的。

第一,一個拷貝構造:

string organised(sentence); 

第二,構造它接受一個字符和計數。你可以用一個臨時字符初始化一個字符串。

string organised(sentence.length(), '_'); 

或者,您可以:

  • 使用空字符串和append(+=)的文字把它作爲你走,或者
  • 使用std::stringstream爲了同樣的目的。

stringstream可能會更有效率。總體而言,如果長度已知,我更喜歡複製構造函數。

+0

那麼,到目前爲止,我剛剛完成了「string stringname = CONSTANTSTRING;」這很煩人,因爲我不需要甚至不想分配它,我只是想分配相同的內存,內容是無關緊要的,它只是一個容器。我也想在循環中使用x = 0的長度來改變stringlength。我如何在編譯時找到長度? –

+0

也許這個問題會更適合你的需求http://stackoverflow.com/questions/12541739/determining-the-length-of-a-string-literal – Rotem

+0

這種作品,但它有點不。 我喜歡避免定義,如果我可以,這是不好的做法。即使我做了,雖然我不能在sizeof預處理器指令中使用該定義,但我不知道爲什麼。它迫使我使用完整的字符串文字。如果答案顯示它指向我,它並不起作用。這無論如何都會使用#define,因爲我無法使用它。 我打過堆棧交換嗎?似乎沒有人能夠回答這個問題,儘管這聽起來像是一個非常基本的問題? –

1

std::string不是編譯時類型(它不能是constexpr),所以你不能直接使用它來確定編譯時的長度。

你可以初始化一個constexprchar[],然後在使用sizeof

constexpr char messychar[] = "a bunch of letters"; 
// - 1 to avoid including NUL terminator which std::string doesn't care about 
constexpr size_t messylen = sizeof(messychar)/sizeof(messychar[0]) - 1; 
const string messy(messychar); 

和使用,但坦率地說,這是相當醜陋的;該長度將是編譯時間,但organized需要使用countchar構造函數,該函數仍將在每次調用時執行,只分配和初始化僅在循環中替換內容。

雖然它不是編譯的時候,你會避免初始化成本只要使用reserve+=建立新的string,它與#define可以在一個醜陋的,但可能有效的方式完成:

constexpr char messychar[] = "a bunch of letters"; 
constexpr size_t messylen = sizeof(messychar)/sizeof(messychar[0]) - 1; 
// messy itself may not be needed, but if it is, it's initialized optimally 
// by using the compile time calculated length, so there is no need to scan for 
// NUL terminators, and it can reserve the necessary space in the initial alloc 
const string messy(messychar, messylen); 

string dostuff(string sentence) { 
    string organised; 
    organized.reserve(messylen); 
    for (size_t x = 0; x < messylen; x++) { 
     organised += sentence[x]++; // Doesn't matter what this does. 
    } 
} 

這避免了多次設置organised的值,每次調用分配多次(如果初始構建執行的話可能會多次),並且只執行一次讀寫通道sentence,沒有完整讀取,然後讀取/寫或諸如此類。它還使循環約束成爲編譯時間值,因此編譯器有機會展開循環(雖然不能保證這一點,即使發生這種情況,也可能沒有幫助)。

另請注意:在你的例子中,你改變了sentence,但它被值接受,所以你要改變本地副本,而不是調用者副本。如果需要調用者值的變異,請通過引用接受它,如果不需要變異,請通過const引用來避免在每次調用時都複製(我理解示例代碼是填充符,只是提到了這一點)。

+0

注意:所有這一切都假定編譯器沒有用'std :: string'做一些聰明的事情,這不一定是有效的假設;鑑於'std :: string'的重要性,編譯器超越語言標準的要求並使'std :: string'的某些特性像'constexpr'一樣對全局'const std :: string單曲。所以,所有的醜陋可能都沒有給你帶來任何好處;我強烈建議避免編譯時間計算的困擾,直到你有強有力的瓶頸證據。 – ShadowRanger

+0

這是非常豐富的信息,我一定會使用它,謝謝。關於整個項目的真正需要的是它必須針對MSVS 2012進行編譯。:-(你不需要告訴我這是多麼的悲慘,我已經知道了。2012幾乎沒有C++ 11的特性,所以我們期待這意味着我必須扔掉很多在我的Unix C++ 14系統上運行良好的東西,這也意味着......我不能使用constexpr。:-(Any C++ 98兼容變體的想法? –

+0

@GeorginaDavenport:如果'constexpr'不存在,那麼你被'#define'常量或宏所困住,例如'const char messychar [] =「一堆字母」; ','#define MESSYLEN(sizeof(messychar)/ sizeof(messychar [0]) - 1)',然後在'C++ 11代碼的messylen'的相同位置使用'MESSYLEN'(或者自定義內聯不是那麼純粹,但是如果你想要編譯時間的行爲,那麼在pre-C++ 11中就沒有那麼多的保證了。 – ShadowRanger