これよりも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");
これよりも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");
なぜstd :: stringを使用しないのですか?
std::string s1 = std::getenv("SystemDrive");
s1 += "\\\\Users\\\\" + std::getenv("USERNAME") + "\\\\Documents";
正確に何が必要なのかよく分かりません。環境変数からパスを作成するのですか?またはシステムディレクトリの適切なパスを取得するには?後者の場合は、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;
}
上記のコードは、現在のユーザー "マイドキュメント"フォルダのパスを取得します。
私はこのようなユーザープロファイルディレクトリを取得することをお勧めします。
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を使用します。これは、時間の経過とともに可搬性を維持する可能性が高くなります。
'OpenProcessToken'が成功し、' GetUserProfileDirectory'が失敗した場合、 'hProcessToken'はどうなりますか? –
良いキャッチ。ありがとうございます。 iPhoneで書式設定権を取得できません。あとで修正する必要があります – bodangly
複数の文字列を連結する一つの良い方法は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
。
getenvを使用しないでください。 – Smash
@Smash 'std :: getenv'で何が問題になっていますか? –
@Smash Microsoftは、移植性のない 'getenv_s'のために' getenv'を廃止したことを知りました。しかし、 'getenv'は標準的なC関数であり、' std :: getenv'は最近C++に導入されました。マイクロソフトの非推奨はCおよびC++標準に反します。 –
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"
注意を。
これは恐ろしいコードなので、C++ではこれをしないでください。 –
それはなぜですか、これはまさにドキュメンテーションがhttps://msdn.microsoft.com/en-us/library/ms175774.aspxを示唆しているものであり、ここで示唆しているのと同じことですhttp://stackoverflow.com/questions/15916695/can-anyone-give-me-example-code-of-dupenv-s – Smash
このようなルーチンタスクでは、コード行が多すぎるためです。 RAIIを使用していないため、漏れが起こりやすいです。例えば、 'std :: string'のいずれかのコンストラクタがこのコードをスローするとメモリがリークします。そのようなコードは、C++デストラクタが存在するようになった理由です。漏れを避けるために自動クリーンアップを行うのです。 –
ここで 'strcat'が未定義の動作を引き起こしているのを無視して' std :: stringstream'を使用します。 – vu1p3n0x