次のパスを受け取ったとします
char* path = "home/directory/file.txt"
file.txt
この文字列を処理しての親ディレクトリだけを取得するにはどうすればよいですか
"home/directory"
このように機能するものをコーディングしたいと思います
char* _get_ParentDir(char* file_path);
この関数は親のパスを返します。
次のパスを受け取ったとします
char* path = "home/directory/file.txt"
file.txt
この文字列を処理しての親ディレクトリだけを取得するにはどうすればよいですか
"home/directory"
このように機能するものをコーディングしたいと思います
char* _get_ParentDir(char* file_path);
この関数は親のパスを返します。
まず、関数にアンダースコアで始まる名前を付けないでください。このような識別子は実装用に予約されています。
説明に基づいて、最後の/
文字を null 文字に置き換えるだけです。
char *last_slash = strrchr(path, '/');
if (last_slash != NULL) {
*last_slash = '\0';
}
これにより、文字列がその場で変更されますが、関数が必要です。文字列へのポインタを返す関数を書くのは難しいです。文字列にスペースを割り当てることを心配する必要があります。次の 3 つの一般的なアプローチがあります。
関数で配列を宣言し、static
その最初の要素へのポインターを返します。問題: 関数を呼び出すたびに、以前の呼び出しで使用されたバッファが上書きされます。
結果が書き込まれるバッファーへのポインターを呼び出し元に渡させます。これにより、発信者にとって事態がより複雑になります。
を使用して関数にバッファーをmalloc()
割り当てさせます (割り当ての失敗を必ず確認してください)。これは機能しますが、呼び出し元がfree()
後でバッファーを処理する責任を負うことになります。
システムが、これを行う機能を提供している場合もあります。別の回答では、 のdirname()
関数について言及しています<libgen.h>
。これは POSIX で指定されていますが、C 標準では指定されていません。システムにそれがある場合とない場合があります。man ページ ( man 3 dirname
Unix ライクなシステムを使用している場合)、特に NOTES セクションを読む必要があります。
最後のスラッシュに「\0」を付けるだけで、元の文字列に意図しない副作用が生じる可能性があります。これを避けるには、別の文字列を作成する必要があります。
char* _get_ParentDir(char* file_path) {
char *c = strrchr(file_path, "/");
long n = c - file_path;
char *dir = malloc(n+1); // this will need to be freed later
dir[n] = 0;
memcpy(dir, file_path, n);
return dir;
}
const char* bname=path;
bname+=strlen(path);
while (bname>path && bname[-1]!='\\' && bname[-1]!='/')
--bname;
basename() 関数もありますが、私のバージョンは DOS と Unix/Linux パスの両方で動作します。
[編集: Ernest Friedman-Hill が以下のコメントを投稿したのとほぼ同時に、私が次の行を単独で投稿したことに言及したいと思います。その後、残りの回答を投稿しました。-phonetagger]
おっと...私はあなたの問題を逆に読みました。dirname() 関数が必要です。 #include <libgen.h>
または....
const char* dname = strdup(path);
const char* bname = dname;
if (dname)
{
bname+=strlen(path);
while (bname>dname && bname[-1]!='\\' && bname[-1]!='/')
--bname;
if (bname != dname)
bname[-1] = '\0';
else
{
bname = path;
free(dname);
dname = NULL;
}
}
このバージョンでは、dname に新しい文字列が割り当てられることに注意してください。必要な寿命に応じて、free() を使用する場合と使用しない場合があります。アプリケーションの実行中に必要な場合は、free() する必要はまったくありません。OS は、アプリケーションの終了時にプロセスの仮想アドレス空間全体を自動的に再利用します。
char* パスの割り当ては静的 const 文字列初期化子からのものであるため、strdup() が必要であることに注意してください。これは、プログラムの読み取り専用セクション (コンパイラによっては、おそらく .rodata) に割り当てられる可能性が最も高いです。