promotion image of download ymail app
Promoted
Anonymous
Anonymous asked in 電腦與網際網路程式設計 · 2 decades ago

string的問題

#include<iostream>

#include<cstdlib>

#include<ctime>

#include<string>

using namespace std;

void main()

{

string s;

srand(time(NULL));

cout<<"產生亂數:";

for(int i=0; i<7; i++)

{

s[i]=(char)(rand()%10+48); //似乎是char轉型時錯了?

cout<<s[i];

}

cout<<endl;

}

這上面的程式用C++編譯時沒有錯誤,可是執行exe檔時卻跑出windows小視窗說出現錯誤....

#include<iostream>

#include<cstdlib>

#include<ctime>

#include<string>

using namespace std;

void main()

{

char s[7];//這邊改成char宣告就正確了

srand(time(NULL));

cout<<"產生亂數:";

for(int i=0; i<7; i++)

{

s[i]=(char)(rand()%10+48);

cout<<s[i];

}

cout<<endl;

}

結果我把上面的宣告改char就完全可以執行了。

我想知道為什麼會這樣?string 跟 char 之間的差別?

如果前提是用string宣告,那下面轉型時應該怎麼修改?

2 Answers

Rating
  • Lv 7
    2 decades ago
    Favorite Answer

    第一個跑時出現問題不是轉型的問題. 因為轉不轉型都沒關係. 如果你沒轉型的話,C++會自動轉型. 第一個程式的問題是你的s在宣告時沒有講要多少個記憶體空間. 在微軟C++裡如果你沒要記憶體空間, 它不會自動給你. 所以在你把(char)(rand()%10+48)存進s[i]的時候, 因為沒有記憶體空間所以微軟C++不知道要存進哪裡, 只好找你麻煩, 在跑程式的時後顯示錯誤出來.

    有以下三種解法(我只想到三種)

    1. 把string s;改成string s="1234567";就好了

    2. 在string s;之後加s.resize(7);就好了

    3. 把s[i]=(rand()%10+48);改成s+=(rand()%10+48);就好了

    簡單來說你第一個程式是犯了一個C++很普遍的錯誤.

    在C++的世界裡, 不管要存什麼東西, 你一定要先向電腦要記憶體空間. 如果沒要而存的話就會有麻煩.

    舉例

    void main() {

    char *p;// 沒要記憶體空間

    *p = 'A';// 存入, 問題來了

    }

    string 跟 char 之間的差別, 我想Wayne講的都差不多了. 最主要的是string是動態的配置記憶空間.也就是說當記憶空間不夠時, string會主動向電腦要. Char *是需要你自己向電腦要.

    Source(s): Myself
    • Commenter avatarLogin to reply the answers
  • 2 decades ago

      在C++中,字串是由資料型態為 char構成的一維陣列,而且字串的結尾處有一個無法顯示的空字元 '\0' 作為結束記號,稱為 C-style string(C風格的字串)。可由下列方式宣告:

      char s1[20] = "Hello, 您好!"; //陣列式的宣告

      char ps2 = "Hello, 您好!"; //指標式的宣告

      char s3[10] = {'G','o','!','\0'}; //列舉式的宣告

    或是使用自動設定字元陣列長度的語法:

      char s4[] = "Hello, 您好!";

      char s5[] = {'G','o','!','\o'};

      使用 C-style string 要隨時注意儲存字串所需的記憶空間是否足夠,特別是結尾處有沒有加上 '\0'。

      C++在 STL(標準樣板程式庫)中定義了一個物件導向的 string 類別,可以動態的配置記憶空間,讓使用者不用自行處理這些惱人的細節。此外,這個類別有完整的成員函數,並且透過運算子重載,提供了許多方便的運算子。

      這個物件導向的 string 類別在使用前要在程式開頭處加上

      #include <string>

    =====以上節錄於張耀仁著《C++程式設計》=====

      因為C++是一種嚴謹的程式語言,所以資料型態的使用錯誤會有很大的影響。上述程式碼執行之所以會錯誤,我想或許是因為資料型態使用不當的關係,但話說回來,我在自己的電腦上用Visual C++ .NET來進行測試,結果卻是無誤。不過既然你有問題的話,我就給你一個函式,能將 string物件轉換成 C-style string。因為老實說,在這裡你其實並不需要使用到 string物件,最好是使用C-style string。

    =====以下節錄自張耀仁著《C++程式設計》=====

    使用 C_str() 成員函數將字串物件轉換為 C-style 字串:

      string S1("Filename");

      const char* pSc;

      pSc = S1.c_str();

      這時 pSc 雖然可以視為 C-style 字串,但它只是指向原先 S1物件內字元陣列的指標,並沒有另外複製產生新字串。所以只要 S1的內容改變,pSc 所代表的字串也會跟著改變。此外,由於 c_str() 的轉換結果是屬於資料型態「const char*」因此無法直接由「char*」的指標節收:

      char* pS2; // pS2 為「char*」的指標

      pS2 = S1.c_str(); //錯誤!

      所以我們可以透過 strcpy() 將 S1 的內容複製到字元陣列 char[] 或者是字元陣列指標 char*(指標的所代表的位置必須有足夠的空間),這種複製是真的製作完成副本,不會因為 S1的內容變動而改變。

      string S1("Filename");

      char CS[10];

      char* pS = new char[S1.length() + 1];

      strcpy(CS, S1.c_str());

      strcpy(pS, S1.c_str());

    Source(s): 張耀仁著《C++程式設計》
    • Commenter avatarLogin to reply the answers
Still have questions? Get your answers by asking now.