2016-04-28 6 views
0

これよりもc/C++で環境変数を通るパスを作る良い方法はありますか?は、c/C++で環境変数を通るパスを作る良い方法ですか?

char *S1 = std::getenv("SystemDrive"); 
char *S2 = std::getenv("USERNAME"); 
strcat(S1,"\\\\Users\\\\"); 
strcat(S1,S2); 
strcat(S1,"\\\\"); 
strcat(S1,"Documents"); 
+1

ここで 'strcat'が未定義の動作を引き起こしているのを無視して' std :: stringstream'を使用します。 – vu1p3n0x

答えて

1

なぜstd :: stringを使用しないのですか?

std::string s1 = std::getenv("SystemDrive"); 
s1 += "\\\\Users\\\\" + std::getenv("USERNAME") + "\\\\Documents"; 
0

正確に何が必要なのかよく分かりません。環境変数からパスを作成するのですか?またはシステムディレクトリの適切なパスを取得するには?後者の場合は、Win32 APIを使用することをお勧めします(例:SHGetFolderPathまたはSHGetKnownFolderPath)。

#include <Windows.h> 
#include <ShellAPI.h> 
#include <KnownFolders.h> 
#include <ShlObj.h> 

int main() 
{ 
    CoInitialize(NULL); 
    TCHAR* path = 0; 
    SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_SIMPLE_IDLIST, NULL, &path); 
    // use collected 'path' here 
    CoTaskMemFree(path); // free the TCHAR object allocated by SHGetKnownFolderPath 
    return 0; 
} 

上記のコードは、現在のユーザー "マイドキュメント"フォルダのパスを取得します。

2

私はこのようなユーザープロファイルディレクトリを取得することをお勧めします。

BOOL GetCurrentUserDir(LPTSTR lpszBuf, LPDWORD lpdwBuflen) 
{ 
    HANDLE hProcessToken; 

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hProcessToken)) 
     return FALSE; 

    if (!GetUserProfileDirectory(hProcessToken, lpszBuf, lpdwBuflen)) { 
     CloseHandle(hProcessToken); 
     return FALSE; 
    } 

    CloseHandle(hProcessToken); 
    return TRUE; 
} 

私はそうのように、この機能を使用する:あなたは、パスの残りの部分を追加することができ

WCHAR szLocalPath[MAX_PATH]; 
if (!GetCurrentUserDir(szLocalPath, &cchPath)) 
{ 
    //Handle the error 
} 

これは、特定の環境変数をカプセル化し、Win32 APIを使用します。これは、時間の経過とともに可搬性を維持する可能性が高くなります。

+0

'OpenProcessToken'が成功し、' GetUserProfileDirectory'が失敗した場合、 'hProcessToken'はどうなりますか? –

+0

良いキャッチ。ありがとうございます。 iPhoneで書式設定権を取得できません。あとで修正する必要があります – bodangly

1

複数の文字列を連結する一つの良い方法はsnprintfを使用することです:

char buf[0x10000]; 
int n = std::snprintf(buf, sizeof buf, "%s\\\\Users\\\\%s\\\\Documents", S1, S2); 
if(static_cast<size_t>(n) >= sizeof buf) 
    // Buffer is too small (if n > 0) or error 

snprintfがバッファをオーバーフローさせ、常にゼロ終了しないという事実は、危険な機能strcpyを行い、strncpy、不要strcat

+0

getenvを使用しないでください。 – Smash

+0

@Smash 'std :: getenv'で何が問題になっていますか? –

+0

@Smash Microsoftは、移植性のない 'getenv_s'のために' getenv'を廃止したことを知りました。しかし、 'getenv'は標準的なC関数であり、' std :: getenv'は最近C++に導入されました。マイクロソフトの非推奨はCおよびC++標準に反します。 –

-1

std::getenvは推奨されていません。

私は好きで何かを使用します。あなたは2つだけ(\\)、4 \\\\\)を必要としない

char* wSystemDrive = nullptr; 
size_t wSize = 0; 

bool wFree = true; 

if(_dupenv_s(&wSystemDrive,&wSize,"SystemDrive") != 0 || wSystemDrive == nullptr) 
{ 
    wFree = false; 

    wSystemDrive = "C:\\"; //or anything default you want to use 
} 

std::string wSysteDriveString(wSystemDrive); 

if(wFree) 
{ 
    free(wSystemDrive); 
} 

char* wUSERNAME = nullptr; 
wSize = 0; 

wFree = true; 

if(_dupenv_s(&wEnv,&wSize,"wUSERNAME") != 0 || wUSERNAME == nullptr) 
{ 
    wFree = false; 

    wUSERNAME = "User"; 
} 

std::string wUSERNAMEString(wUSERNAME); 

if(wFree) 
{ 
    free(wUSERNAME); 
} 

std::string wPath = wSystemDriveString + "\\Users\\" + wUSERNAMEString + "\\Documents" 

注意を。

+0

これは恐ろしいコードなので、C++ではこれをしないでください。 –

+0

それはなぜですか、これはまさにドキュメンテーションがhttps://msdn.microsoft.com/en-us/library/ms175774.aspxを示唆しているものであり、ここで示唆しているのと同じことですhttp://stackoverflow.com/questions/15916695/can-anyone-give-me-example-code-of-dupenv-s – Smash

+0

このようなルーチンタスクでは、コード行が多すぎるためです。 RAIIを使用していないため、漏れが起こりやすいです。例えば、 'std :: string'のいずれかのコンストラクタがこのコードをスローするとメモリがリークします。そのようなコードは、C++デストラクタが存在するようになった理由です。漏れを避けるために自動クリーンアップを行うのです。 –