• ベストアンサー

ファイル名である文字列からbasenameを取得したい

ファイル名である文字列からbasenameを(スマートに)取得したいです。 Perlでは何も考えなくてもできたのですが、C(もしくはC++)では次のようなやりかたしか思いつきません。 これでできているので問題ないのですが、何だかモヤモヤします。 また、このやり方では拡張子はピリオド含めて4文字であること前提なのもモヤモヤの原因です。 Perlのようにもっとスマートなやりかたはないでしょうか? --------------------------------- char filename[] = "test.dat"; char basename[128]; strncpy(basename, filename, strlen(filename)-4); basename[strlen(filename)-4] = '\0'; ---------------------------------

  • ooss
  • お礼率82% (14/17)

質問者が選んだベストアンサー

  • ベストアンサー
  • MrBan
  • ベストアンサー率53% (331/615)
回答No.3

拡張子がないとか、base自体に.を含むとか、考えると、例えばVCなら_splitpath関数を使うのが一番スマートかも。 C++ならstd::string::find_last_ofで.を探して、 std::string::substrやiterator等の組み合わせで部分文字列を抽出するとか。

ooss
質問者

お礼

_splitpath関数ですか。知らなかったのでちょっと調べてみます。 VC以外はダメなんですかね? ちょっとそこのところが躊躇されますが、自分はVCなので使ってみます。 スマートそうな匂いがしています。

その他の回答 (4)

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.5

最後のピリオドを探すのであれば、strrchrを使えば一発でできますが、foo.tar.gzのようなファイル名の場合、本当にそれでよいのか、いまいち不安が残りますね。

回答No.4

   発展・・・かな? #include <stdio.h> #include <string.h> int main(void) { char filename[] = "test0.test1.test2.dat"; char *pch, *temp; pch = NULL; for(temp = filename; (temp = strchr(temp, '.')) != NULL; temp ++) pch = temp; if(pch != NULL) *pch = '\0'; printf("%s", filename); return 0; }  

ooss
質問者

お礼

ありがとうございます。 strchrも検討してみます。

回答No.2

  #include <stdio.h> #include <string.h> int main(void) { char filename[] = "test.dat"; char *pch; if((pch = strchr(filename, '.')) != NULL) *pch = '\0'; printf("%s", filename); return 0; }  

回答No.1

1.ファイルネームが格納された文字列を先頭から順に一文字ずつピリオドかどうかをチェックする。 2.ピリオドでない場合はベースネームを格納する文字列にその文字をコピー、ピリオドの場合は'\0'を書き込んで関数を抜ける っていうのはどうでしょう?

ooss
質問者

お礼

ありがとうございます。 この方法が一番オーソドックスで自然かもしれないです。

関連するQ&A

  • perlでファイルの拡張子を除いた文字列の取得

    perlでファイルの拡張子を除いた文字列を取得するにはどうすればいいんでしょうか? foo.txt --> foo aaa.pl --> aaa splitを使用して @array = split(/./,<filename>) $value = $array[0] としてもうまく取得できないんですが。。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • ファイル名を正規表現にかける際の文字コードについて

    Windows XP, ActivePerl5.8.8 です。 windows 上にあるファイルの名前に沿ってフォルダに振り分けしたく、 以下のようなコードを書きましたが、 ファイル名に日本語の「ソ」などがある場合に 処理がおかしくなります。 文字コードの問題だと思いますが、どうすれば解決できるでしょうか。 ++++ここからソース++++++ #!c:/perl/bin/perl.exe use 5.008; use strict; use warnings; use File::Basename; use File::Copy; use File::Path; my $newdir = "C:/tmp"; for my $filename ( @ARGV ){ main($filename); print "complete.\n"; } sub main{ my ($filename) = @_; my($basename, $basedir) = fileparse($filename); my($name1, $name2, $ext) = $basename =~ /^(.*) - (.*)(\.[a-zA-Z0-9]+)$/; mkdir "${newdir}/${name1}"; File::Copy::copy( "${filename}", "${newdir}/${name1}/${basename}" ) or die "${filename} : Cannot copy"; } 1;

    • ベストアンサー
    • Perl
  • 文字列の途中から途中までを抽出

    文字列の一部を抽出したいときのプログラムです。 絶対条件は ・文字列はchar*型 ・ある文字で区切られた区間を抽出 です。 以下のコードだとstrncpyの部分でsegmantation faultになってしまいます。 -------------------------- char array[10] = "abcd/efgh"; char* str0 char* str1; char* str2; int = len; str0 = array; len = strstr(str0, "/") - str0; strncpy(str1, str0, len); str2 = array + len + 1; -------------------------- 各変数が str1 = abcd str2 = fghi となるようにしたいです。 char str1[10];などにすればいいのですが、それ以外の方法でお願いします。

  • 文字列について

    textファイルをいくつかに分割して保存しようと思い、以下のプログラムを作りましたが、うまくいきません。 予定では "0000.txt", "0001.txt", ....と文字列を生成するはずです。 #include <stdio.h> #include <string.h> #define LENGTH 4 //番号の桁数 void filename(int n) {    char name[LENGTH +4 +1];    char text[5] = ".txt";    int i;    for(i = 0; i <= LENGTH; i++)       name[i] = '0';    i = LENGTH;    //自然数を文字列に変換    do{       name[i] = (char)(n%10 + 48);       i--;       n /= 10;    }while(n != 0 && i >= 0);    strcat(name, text);    printf("filename:%s", name); } int main(void) {    int i;    for(i = 0; i < 5; i++){       filename(i);       printf("\n");    }    return 0; } 実行結果は filename:00000@.txt filename:00001.txt filename:00002.txt filename:00003.txt filename:00004.txt このように、文字化けしています。 何が原因なのでしょうか。 よろしくお願いします。

  • ファイルから文字列を読み出して、比較する方法

    ./log.dat に以下のように数行のログが記録されています。 文字列a<>ipアドレスa 文字列b<>ipアドレスb 文字列c<>ipアドレスc 上記ログ内に$wordに指定された文字列が含まれている場合の処理を行いたいのですが、この場合はどのように書けばよろしいのでしょうか。 $word = "文字列b<>ipアドレスb"; if ($word !~ ログ内容) {処理} ↑のように色々試してみましたがうまくいきません。Perlの知識は素人並みです。宜しくお願いいたします。

    • ベストアンサー
    • Perl
  • C言語で取得した文字列を、C++の文字列として取り扱いたいです。

    C言語で取得した文字列を、C++の文字列として取り扱いたいです。 皆さんこんにちは。 C言語で取得したchar型で定義された文字列を、 C++の「std::string」に渡したいと思っております。 どうすればかなうでしょうか? 具体的には次のような内容です。 ■C言語側 ---- char key1 = "deperture"; ---- ■C++側で「key1 = key2」としたいです。 ---- std::string key2 = key1; ---- C言語側で記述されている「key1」の値(deperture)を、 C++ソース内の「key2」に渡したいと思っています。 こうゆう場合、どんな方法をとれば適切でしょうか。 C言語側でのchar型の文字列の値を、 C++側の「std::string」型として C++のソースへ渡す方法が分からないです。 アドバイスいただけるとありがたいです。 簡単な例を頂けると更に大変ありがたいです。 以上どうぞ宜しくお願い致します。

  • 文字列のある行数を表示する

     お世話になっています。  前回、文字列の検索の質問をしたものです。  このプログラムは文字列を入力して、ファイルから文字列を検索する。  そして、検索した文字列の総数と、存在する行数目を出すというものです。    現状の問題は、検索した文字列の総数は出るようになりました。      しかし、存在する行だけを出したいのに、全ての行数目を      出してしまいます。           どのようにすれば検索した文字列のある行数目だけを表示できるようになるのでしょうか。  以下、現在のソースの状態です。 #include <stdio.h> #include <fstream> #include <iostream> #include <stdlib.h> #include <string.h> #define FALSE 0 #define TRUE 1 using namespace std; int main( ) { FILE *fp;//ファイルポインタ char filename[256];//ファイル名 char key[128];//検索文字列 char key2[128];//見つけた文字列の保存 int iCnt[128];//見つけた文字 char c;    int keylen;//検索文字列の長さ int i = 0;//検索文字列の位置 int search = FALSE;//検索中フラグ int count = 0;//検索文字列出現回数 int j = 0; //検索対象ファイル名と検索文字列をコンソール入力 cout << "ファイル名を入力してください⇒  "; cin >> filename ; cout << "検索文字列を入力してください⇒  "; cin >> key; keylen = strlen(key); if((fp = fopen(filename,"r")) == NULL)     { cout << "ファイルオープンエラー\n" ; exit(1); } //ファイル読み込み while((c = fgetc(fp)) != EOF) { if(search) {//検索中       //検索文字列に一致しない文字が現れた    if(c != key[i]) { search = FALSE; i = 0; } else{  i++; } }   else{ //検索中ではない if(c == key[i]) { search = TRUE; i++; } }     //検索文字列と全て一致した場合 if(keylen == i) { count++; i = 0; iCnt[i] = 1; search = FALSE; } } fclose(fp); cout << "出現回数は " << count << '\n'; //ファイル(filename)からの読み込み        ifstream ifs(filename); string buf; while(getline(ifs, buf) && ifs ) { // ここで行目数の処理を行っています。 j++; if((count++ && search = FALSE) == TRUE) { cout << j << "行目" << endl; } } return 0; }

  • CGI.pmで取得したファイルハンドルを変数にいれるとファイル名のみになる・・・

    perlにて、 use CGI; my $q = new CGI; my $ufh = $q->upload('file'); などで$ufhにファイルハンドルを受け取り、 この直後で、アップロードなどを行うと正常に行われるのですが、 別の関数に渡してからアップロードを行うとファイル名がついた0バイトのファイルがアップロードされます。 &test($ufh); test($){ $filename = $_[0]; while(read($filename , $buffer, 1024)){ $file .=$buffer; } my $basename; my $exp; my $files; my $newfile; my @files = split(/\\/, $file_name); ($basename, $exp) = split(/\./, $files[-1]); $newfile = $basename . "." . $exp; open(FILE, "> /tmp/$newfile"); binmode(FILE); print(FILE $files); close(FILE); } ファイルハンドルを変数に格納して持ちまわすことはできないのでしょうか? よろしくお願いします。

    • ベストアンサー
    • Perl
  • C の文字列置き換え

    #include <stdio.h> // buffer overflowは無視している文字列置き換え関数 void replace(char *buf, char *pre, char *aft) {   char *p;   p = strstr(buf, pre);   if (p){     char *p_2 = p + strlen(pre);     replace(p_2, pre, aft);     memmove(p + strlen(aft), p_2, strlen(p_2)+1);     memcpy(p, aft, strlen(aft));   } } int main(void) {   char buf[1024] = "C:\\programfile\\LOG";   replace(buf, "LOG", "RESULT");   printf("%s\n", buf);   return 0; } というソースが以前出ていたのですがこのバッファーオーバフローはどうすれば回避できるのですか? お願いします

  • 文字列扱い方

    構造体の中の配列へ文字列を入れる方法がわからなくてこまっています! #include <stdio.h> struct TEST{     char str[32]; }; int main(){     TEST test;     test.str = "test";     return 0; } このように入力するとconst char [5]' から 'char [32]' に変換できません。と出てしまいます。 何か良い方法がありましたらぜひご教授お願いいたします。

専門家に質問してみよう