2009-08-01 6 views
10

私はC++の初心者です。私は関数のoutパラメータとしてcharポインタを持つことを試みています。しかし、関数の変更は主関数に反映されません。私は間違って何をしていますか?C++関数の出力パラメータとしてcharポインタを持つ方法

void SetName(char *pszStr) 
{ 
    char* pTemp = new char[10]; 
    strcpy(pTemp,"Mark"); 
    pszStr = pTemp; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    char* pszName = NULL; 
    SetName(pszName); 
    cout<<"Name - "<<*pszName<<endl; 
    delete pszName; 
    return 0; 
} 

答えて

48

あなたのポインタはスタックにコピーされており、スタックポインタを割り当てています。ポインターを変更する場合は、ポインターをポインタに渡す必要があります。

void SetName(char **pszStr) 
{ 
    char* pTemp = new char[10]; 
    strcpy(pTemp,"Mark"); 
    *pszStr = pTemp; // assign the address of the pointer to this char pointer 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    char* pszName = NULL; 
    SetName(&pszName); // pass the address of this pointer so it can change 
    cout<<"Name - "<<*pszName<<endl; 
    delete pszName; 
    return 0; 
} 

これで問題は解決します。


ただし、ここに他の問題があります。まず、印刷する前にポインタを間接参照しています。あなたは配列全体を印刷したいので、これは、あなたのポインタは文字の配列へのポインタで、間違っています:

cout<<"Name - "<<pszName<<endl; 

あなたは今だけの最初の文字が印刷されますが何をしています。 Alsoは、あなたは、アレイを削除するdelete []を使用する必要があります。

delete [] pszName; 

大きな問題は、しかし、あなたのデザインです。

そのコードはCではなくC++であり、標準ではありません。まず、あなたが探している機能はmainです:

int main(int argc, char * argv[]) 

第二に、あなたはreferences代わりのポインタを使用する必要があります。

void SetName(char *& pszStr) 
{ 
    char* pTemp = new char[10]; 
    strcpy(pTemp,"Mark"); 
    pszStr = pTemp; // this works because pxzStr *is* the pointer in main 
} 

int main(int argc, char * argv[]) 
{ 
    char* pszName = NULL; 
    SetName(pszName); // pass the pointer into the function, using a reference 
    cout<<"Name - "<<pszName<<endl; 
    delete pszName; 
    return 0; 
} 

それはさておきを、それはあなたができる場合だけで物事を返すために、通常は良いでしょう:

char *SetName(void) 
{ 
    char* pTemp = new char[10]; 
    strcpy(pTemp,"Mark"); 
    return pTemp; 
} 

int main(int argc, char * argv[]) 
{ 
    char* pszName = NULL; 
    pszName = SetName(); // assign the pointer 
    cout<<"Name - "<<pszName<<endl; 
    delete pszName; 
    return 0; 
} 

これをすべて改善するものがあります。 C++はstring classがあります

std::string SetName(void) 
{ 
    return "Mark"; 
} 

int main(int argc, char * argv[]) 
{ 
    std::string name; 

    name = SetName(); // assign the pointer 

    cout<<"Name - "<< name<<endl; 

    // no need to manually delete 
    return 0; 
} 

したい場合は、これはすべて、簡略化することができ、もちろん場合:

#include <iostream> 
#include <string> 

std::string get_name(void) 
{ 
    return "Mark"; 
} 

int main(void) 
{ 
    std::cout << "Name - " << get_name() << std::endl;   
} 

あなたは物事をより読みやすくするために書式設定で動作するはずです。あなたのオペレータ挟んスペースができます:ちょうど英語の単語の間にスペースなどの

cout<<"Name - "<<pszName<<endl; 

cout << "Name - " << pszName << endl; 

は、sodoesspacesbetweenyouroperatorsに役立ちます。 :)

+2

+1は、直接の問題に答えて、コードの大きな問題を明らかにします。 –

+0

ありがとうGMan。それは本当に有益だった。 – Mark

+0

問題はありません:) – GManNickG

2

あなたが書いているのはC++ではなく、mallocではなくnewを使用するCコードで、freeではなくdeleteです。本当にC++コードを記述したい場合は、もう一度やり直してください。現代の熟語C++を教えてくれるAccelerated C++のような本を読んでください。

+0

これは正確に質問に答えるものではありませんが、それは良い提案です... – Zifre

+2

質問の最後の行は「私は間違っていますか?私の答えはこれを正確に扱っていると思います。 –

+0

提案していただきありがとうございます。私は間違いなく本を読むでしょう。 – Mark

4

C++とタグ付けされているので、std :: string参照を渡して入力してみましょう。

void GetName(std::string &strName) 
{ 
    strName = "Mark"; 
} 

それとも単にのstd ::文字列を返す:

std::string GetName2() 
{ 
    return "Mark"; 
} 

、その後、あなたが任意のメモリを解放を心配する必要はありませんので、

std::string strName, strName2; 
GetName(strName); 
strName2 = GetName2(); 
assert(strName == "Mark"); 
assert(strName2 == "Mark"); 
//strName.c_str() returns the const char * pointer. 

のようにそれを呼び出します。

+0

そして#includeを含めることを忘れないでください :) –

7

この場合、ポインタの参照を使用することもできます。また、元のコードにある他の2つのバグを知りたい場合もあります(コードスニペットのコメントを参照してください)。

void SetName(char *& pszStr) 
{ 
    char* pTemp = new char[10]; 
    strcpy(pTemp,"Mark"); 
    pszStr = pTemp; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    char* pszName = NULL; 
    SetName(pszName); 

    // Don't need '*' in front of pszName. 
    cout<< "Name - " << pszName << endl; 

    // Needs '[]' to delete an array. 
    delete[] pszName; 
    return 0; 
} 
+0

配列の削除にいいキャッチ。 – GManNickG

関連する問題