• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:ユニコード文字列の分割)

ユニコード文字列の分割方法を改修する

このQ&Aのポイント
  • ユニコード文字列をカンマや'\'で分割する関数を改修する必要があります。
  • 現在の関数はマルチバイト文字に対応していますが、ユニコード文字に切り替えると分割が正しく行われません。
  • プロジェクトが既に進行中のため、対応に時間をかけずに解決する方法を探しています。

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

  • ベストアンサー
回答No.10

それとCreate関数内で if ( !(*pp)->temp ) return false; となってる部分がありますが if ( !(*pp)->temp ){ Release( pp ); return false; } にしとかないと(ほとんどないとは思いますが)メモリリークの危険が一応残っていますね。 ついでにstd::bad_allocに対しても全部例外安全にしようとすると Splitのnewのとこもこだわらないといけませんが std::bad_allocが飛ぶ状況ってほとんどまず考慮しないでいいかもしれないので アプリケーション次第ではtry-catch使わない方向で割り切ってしまっても全然いいかもしれません。 (後で細切れで気づくと何度も投稿しないといけないのが不便ですw 編集出来たらいいのに >教えて!goo )

baysidehotel
質問者

お礼

回答ありがとうございます。 本日、リーダさんに確認をとりました。 プロジェクトのどこかで工数を確保して改修することになりそうです。 いただいた回答全てを盛り込めるほどの工数は無理と思いますが・・・

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (9)

回答No.9

おっと、ReleaseAllWords関数のとこの words = NULL; は不要でしたw 美しくないので削除しておいてくださいw

全文を見る
すると、全ての回答が全文表示されます。
回答No.8

おお!全員に対してしっかりご返答なさっていらっしゃいますし ご担当なさっているプロジェクトのこれからについて大事なことでしょうから こちらとしてももうちょいしっかり情報を補足しておきます。 ・ユニコードを使う「可能性がある箇所」では必須です。 と書きましたが、これの意図するところは 実際には 現状ではファイルI/Oやコンソール出力時などのみで、確かに十分、というのが実状かもしれません。 ただし「将来的なことまで見据えて考えると」 Microsoftの気まぐれ一つで状況が変わったりするかもしれませんし 「特定の、この関数」内部では未来永劫絶対setlocaleの必要はない!と断言するのは さすがにMicrosoft幹部でも難しいと思うので 場合分けしてやって、将来変更がないか常におびえる状況になるよりも 先に全体にやっておいた方が遥かにリスクが少ない ので「必須と思った方が遥かに楽であろう」という意味です。 ・usertype.datについて 既にご存知でしたら良いですが もしまだ未着手でしたらだいぶ可読性が上がるかもしれませんので usertype.datを使うと、intやifなどの、元々色がつくようになっている 予約語など以外にも VC++上で任意のキーワードに色がついた状態で表示出来ます。 こちらの環境では Program Files\Microsoft Visual Studio 9.0\Common7\IDEの中に usertype.datを置くと効果がありました。 既にある場合は、ここに色を変えたいキーワードを一行にひとつずつ書き加えます。 ない場合は、例としてはメモ帳などで以下のように書いたテキストファイルを作り LPCTSTR TcsLiteral TCHAR ファイル名と拡張子をusertype.datにして上記などの、適切なディレクトリに置き VC++を再起動すれば効果が確認できるはずです。 ・実際の実装法について 実際では決め打ちとかできないので 標準ではない便利なライブラリとかになるべく頼らず書くなら(C++03の仕様では) これくらい書かないといけないかもしれません。 (なお、載せるのに分割状況書くのは面倒なので全部インライン指定になってますが、コンストラクタやデストラクタなどは一見短いように見えて、生成される機械語は長くなったりする可能性があるのでインライン化はこの場合お勧めできません。また、細かい仕様とかその辺は調整してください。) typedef LPCTSTR const TcsLiteral; class TcsPtrArray { typedef struct LINEARDATA { LINEARDATA* next; TcsLiteral p; LINEARDATA( TcsLiteral p_ ) : next(NULL), p(p_){} } LD; TCHAR* temp; LD* words; TcsPtrArray() : temp(NULL), words(NULL) {} ~TcsPtrArray(){ free( temp ); ReleaseAllWords(); } void ReleaseAllWords(){ for ( LD* a; a = words; ){ words = words->next; delete a; } words = NULL; } public: static void CheckFunc_S( TcsLiteral s ){ _tprintf( _T("[%s]\n"), s ); } void Split( const TCHAR delimiter ){ if (words) ReleaseAllWords(); TCHAR* c = temp; words = new LD( c ); LD** pp = &words->next; for ( ; *c; ++c ) { if ( *c != delimiter ) continue; *c = _T('\0'); *pp = new LD( c+1 ); pp = &(*pp)->next; } } template < class F > void ForEach( F& f ) const { for ( const LD* a = words; a ; a = a->next ) f(a->p); } static bool Create( TcsPtrArray** pp, TcsLiteral s ){ //生成 try { *pp = new TcsPtrArray; } catch ( std::bad_alloc ){ return false; } (*pp)->temp = _tcsdup( s ); if ( !(*pp)->temp ) return false; return true; } static void Release( TcsPtrArray** pp ){ //解放 delete *pp; *pp = NULL; } }; 少々長くなりましたが、必要ヘッダとかをインクルードすればコピペでサクッと出来ると思います。 機能拡張等は用途に応じてご自由に行ってください。 ここまで準備しておけば使い方は簡単です。 int main() { setlocale( LC_ALL, "japanese" ); TcsLiteral input = _T("ソーシャル,ネットワーク,,ソリューション,"); TcsPtrArray* tpa; if ( !TcsPtrArray::Create( &tpa, input ) ) return 0; tpa->Split( _T(',') ); tpa->ForEach( TcsPtrArray::CheckFunc_S ); TcsPtrArray::Release( &tpa ); //Createに対して対で解放 } 分からない箇所がありましたら聞いてください。

全文を見る
すると、全ての回答が全文表示されます。
回答No.7

あ、さらにもうひとつw C++用に変更、なのでやってもなんら問題のですが(むしろやった方が良いはず) 下のコードで修正忘れてました。 int main(){ の直後に setlocale( LC_ALL, "japanese" ); を持ってくるように直してください。 そうすれば、内部で何が行われてても確実に大丈夫なはずです。

baysidehotel
質問者

お礼

何度も回答いただきましてありがとうございます。 いただいたアドバイスともとにプロジェクトのリーダを相談したいと思います。

全文を見る
すると、全ての回答が全文表示されます。
  • wormhole
  • ベストアンサー率28% (1619/5653)
回答No.6

>char* str: 分割対象の文字列 「分割対象の文字列」の文字コードがUTF-8であるなら問題ないですが (問題なといってもASCIIコードの文字で分割する場合においてですが) Shift_JISだと処理内部でシングルバイト文字と マルチバイト文字の1バイト目と2バイト目を区別する必要があります。 なぜ区別しないといけないかはShift_JISの文字コード表とにらめっこするなり googleなどで検索するなりしてみてください。 また他の人もいってますが >while(*str != NULL){ >words[i][j] = NULL コンパイラはエラーや警告を出さないかもしれませんが 内容的にはバグと変わりありません。 NULLはポインタなので例え定義が0であろうと charとして扱ってはいけません。

baysidehotel
質問者

お礼

回答ありがとうございます。 いただいた指摘と他の方のアドバイスも含めてプロジェクトのリーダさんを相談します。

全文を見る
すると、全ての回答が全文表示されます。
回答No.5

もひとつ >プログラム内部では文字列は原則std::string型で保持していて 依然大変な作業になる可能性はあるかもしれませんが、状況次第では こちらのページの内容が役に立つかもしれません。 ・UNICODEで分けないtstring型を宣言する http://marupeke296.com/TIPS_No14_tstring.html

全文を見る
すると、全ての回答が全文表示されます。
回答No.4

どうも epistemeさんへの補足について 1. そこなんですよね。 「ふつ~」に使いたいという前提では少なくとも char*の内部表現とwchar_t*の内部表現は違いますので こればっかりは全部マルチバイト専用のコードになってる場合 必要箇所全てにわたって書きなおす必要があります。 (現実的には「編集→検索と置換→クイック置換」などの機能を駆使して必要箇所をまとめて書き変えていく、といったことになるかと) コストがかかっても変換する必要がある場合はWideCharToMultiByteやMultiByteToWideCharなどで変換する必要があります。 (MFCではCStringA、CStringW、CStringなどの便利な使い方があったと思いますが http://www.usefullcode.net/2006/11/widechartomultibytemultibyteto.html) ただ いずれにせよ、よっぽどでかいプロジェクトの場合、最初からこれが配慮されてないコードで書かれたものを正確に直し続けていく事は 結構大変な作業になることは覚悟しなければいけません。 ただし、特定の個所でのみ両対応にする、という場合はそれほど大変ではない場合もあります。 例えば const char* text = "aaa"; MessageBox(NULL, text, "", 0 ); はデフォがマルチバイトの設定でしか通用しない書き方ですが LPCTSTR text = _T("aaa"); MessageBox(NULL, text, _T(""), 0 ); とかに直していくのが面倒で、この付近に関してはマルチバイト文字しか使わなくてOKと分かってる場合は const char* text = "aaa"; MessageBoxA(NULL, text, "", 0 ); こういう風に、呼び出し側の関数をマルチバイト専用に明示的に指定してやることで対処することも可能です。 逆に、ユニコード版しか用意されてない関数とかでは LPCWSTR text = L"WINDOW"; HTHEME theme = OpenThemeData( hw, text ); などと、明示的にユニコード指定にしてやる必要があります。 2. ユニコードを使う「可能性がある箇所」では必須です。 なのでTCHARを使う場合はやっておいてください。 とはいえ、アプリケーション中で一つのロケールしか必要ないのであれば アプリケーションの最初に1回だけ呼んでおいて、そのまま変更しなければOKです。 3. これは epistemeさんが、baysidehotelさんの「関数のロジック」をもとに splitを書いたときに 内部でmallocを使用したことに起因するものです。 もし私が一から作る場合は 確保と解放は近くに書かれてた方がぱっと見分かりやすいので、呼び出し側で確保するともいます。 コードを一部お借りすると MFCが使えるという事でC++の規則込みで書いてしまいますが #include <windows.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <locale.h> #include <tchar.h> typedef LPCTSTR const TcsLiteral; int split( TCHAR* p, LPCTSTR words[], const TCHAR delimiter ){ int row = 0; words[row] = p; for ( ; *p; ++p ) { if ( *p != delimiter ) continue; *p = _T('\0'); words[++row] = p+1; } return ++row; } /* おためし */ int main() { TcsLiteral input = _T("ソーシャル,ネットワーク,,ソリューション,"); LPCTSTR words[5]; //おためしなので決め打ち TCHAR* const temp = _tcsdup( input ); //確保に当たる setlocale( LC_ALL, "japanese" ); const int n = split( temp, words, _T(',') ); for ( int i = 0; i < n; ++i ) _tprintf( _T("[%s]\n"), words[i] ); free(temp); //対で解放 } 私ならこんな感じにするかもしれません。 実行結果 [ソーシャル] [ネットワーク] [] [ソリューション] []

baysidehotel
質問者

お礼

回答ありがとうございます。 1.2.について →やはり根本的には相当数のコストをかけて該当箇所を修正するのがベストですね  ただ実施できるかは。。。 3.について →epistemeさんのコードをよく見ていませんでした。  メモリの確保と開放がmain()内にあるので保守性を考慮するとこちらのほうが  いいのかもしれません。

全文を見る
すると、全ての回答が全文表示されます。
回答No.3

>  内部的にTCHAR型にキャストして処理すればよいでしょうか? あなたのいうUNICODE対応とは何ですか? 呈示したコードは文字セットがchar, wchar_tのどちらでも動くことを 目的としたものです。 > setlocale()がコールされていますが、必須でしょうか? それは僕がきめられることではありません。 > main()関数の最後にfree()がコールされていますが、TCHAR型は > メモリ領域を確保いているのでしょうか? コードを読んでください。spィt内で確保した領域を解放しています。

baysidehotel
質問者

お礼

何度も回答いただきありがとうございます。 1.2.については不具合を指摘した人の環境を確認してみます。 3.についてはコードをよく読んでいませんでした。 #1で示していただいた内容と、他の方のアドバイスも含めて プロジェクトのリーダに相談いたします。 お手数をおかけしました。

全文を見る
すると、全ての回答が全文表示されます。
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.2

そのファイルがShift_JISで書かれていているのでは? それをchar*として読み込めば、「全角」文字は「2つの文字」になります。 「ソ」を2つに分けたとき、2番目が「\」になっています。 この2番目の\を「ソの一部」と判断できずに「\」だと判定してしまっているのが今の現象です。 ※ 「シフトJISのだめ文字」として有名な現象です。検索すれば他にもあることがわかります。 プロジェクト全体を変えるなら、TCHARを使って全角文字を「1文字」として処理するようにするのがいいのでしょう (#1さんにある方法です) ここだけを変えるなら、「2バイト目でないdelimiter」だけを処理するようにすることでしょう。 例えば。 bool is2byte = false ; // 2バイト目かどうかのフラグ while(*str != NULL){  // 文字列を分割する処理  if( is2byte || (str != delimiter) ){ //2バイト目ならdelimiterとの比較はしない   words[i][j++] = *str;   // 次の処理が2バイト目かどうか   if(is2byte){    is2byte=false;   }else{    is2byte=(*strが2バイト文字の1バイト目):   }  }  else {   words[i][j] = NULL   i++; j=0;   is2byte=false;  } とか。 あと、細かいことかもしれませんが > while(*str != NULL){ > words[i][j] = NULL 「何も指していないポインタ」であるNULLと、ヌル文字'\0'は別です。 VC++の実装でNULL='\0'=0にはなっていますが。

baysidehotel
質問者

お礼

回答ありがとうございます。 >「ソ」を2つに分けたとき、2番目が「\」になっています。 >この2番目の\を「ソの一部」と判断できずに「\」だと判定してしまっているのが今の現象です。 知りませんでした。 いままで文字コードを意識してコーディングをしたことがなかったもので・・・ >あと、細かいことかもしれませんが >> while(*str != NULL){ >> words[i][j] = NULL >「何も指していないポインタ」であるNULLと、ヌル文字'\0'は別です。 >VC++の実装でNULL='\0'=0にはなっていますが。 こちらのほうは改修に合わせて修正します。

全文を見る
すると、全ての回答が全文表示されます。
回答No.1

...別に問題なさそうですが。 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <locale.h> #include <tchar.h> int split(const TCHAR* str, TCHAR* words[], TCHAR delimiter) { TCHAR* p; int row = 0; TCHAR* buf = (TCHAR*)malloc(sizeof(TCHAR)*(_tcslen(str)+1)); _tcscpy(buf, str); words[row] = buf; for ( p = buf; *p != _T('\0'); ++p ) { if ( *p == delimiter) { *p = _T('\0'); words[++row] = p+1; } } return ++row; } /* おためし */ int main() { const TCHAR* input = _T("ソーシャル,ネットワーク,,ソリューション,"); TCHAR* words[5]; int n; int i; setlocale(LC_ALL, "japanese"); n = split(input, words, L','); for ( i = 0; i < n; ++i ) { _tprintf(_T("[%s]\n"), words[i]); } free(words[0]); }

baysidehotel
質問者

補足

回答ありがとうございます。 いくつか確認させてください。 1.split()の引数が全てTCHAR型です。   問題の関数は全て現在はchar型で処理しています。   内部的にTCHAR型にキャストして処理すればよいでしょうか?   あるいはsplit()の呼び出し部分も合わせて改修が必要ですか?   プログラム内部では文字列は原則std::string型で保持していて  split()コール時にchar型にキャストしています。 2.setlocale()がコールされていますが、必須でしょうか?   現状はファイルI/Oかコンソール出力時のみ、該当の箇所で直前に  設定して処理後に設定を解除しています。 3.main()関数の最後にfree()がコールされていますが、TCHAR型は  メモリ領域を確保いているのでしょうか? よろしくお願いいたします。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 文字列の扱い方

    初歩的な質問ですみません… str文字列からcという文字を見つけたら添字を返すという関数を作ったのですが、 iにこの関数を代入して、if文の制御式にiを使って比較するまでは正常なのですが、 真文にiを使うと何故か偽文(という言い方でいいのでしょうか…この場合("そんな値はありません。"というところです)が実行されてしまいます。 よろしければご教授お願い致します。 #include <stdio.h> int str_char(const char str[],int c) { int len = strlen(str); int i; for (i = 0;i < len;i++) { if (str[i] == c) return i; } return -1; } int main() { char str[64] = "Fucking Brutal Death Metal"; int ch,i; printf("どの文字を調べますか?"); scanf("%c",&ch); i = str_char(str,ch); if (i >= 0) printf("その文字は%d番目にあります。",str_char(str,ch) + 1); //何故かiだと動かない else printf("そんな値はありません。"); return 0; }

  • 文字列の比較について

    BufferedReaderでファイルを読んだのちに、見出しの文字列をカンマで分割して 文字列を比較しようとしています。 ですが、分割すると、文字列が別な文字コードによる表記に変わってしまいます。 なぜでしょうか? また、解決方法などのヒントなどあれば教えてください。 BufferedReader buffReader = new BufferedReader( new FileReader("/home/masa/Desktop/Sample.csv")); String s; int ini=0; int wamei=0; int i=0; while((s = buffReader.readLine())!= null){ String[] str = s.split(",", -1); //System.out.println(s); if (i == 0) { for(int j=0; j<str.length;j++){ System.out.println(String.toString(str)); if(str.equals("五十音")){ini = j;} System.out.println("五十音"+ini); if(str.equals("a")){wamei = j;} System.out.println("和名"+wamei); //System.out.println(j); } } i++;

    • ベストアンサー
    • Java
  • 文字列

    下のプログラムは何をするためのプログラムなのか教えてください。 個人的にはJISコードに関係していると思うのですがさっぱりわかりません。 どなたか詳しい説明お願いします。 #include <stdio.h> #define LEN 255 int main(void) { char str[LEN]; char cipher[LEN]; int ikey; int i,n; printf("文字列を入力せよ : "); scanf("%s", str); printf("鍵を入力 : "); scanf("%d", &ikey); i = 0; while (str[i]!='\0') { n = (str[i]-'A'+ikey)%26; cipher[i] = 'A'+n; ++i; } cipher[i] = '\0'; printf("%s\n", cipher); return 0; }

  • C言語で分からないところがあるのですが

    すみません。C言語のポインタで分からないことがあって来ました。 ポインタの理屈は理解してはいるのですが、いざソースコードを書いてみようということになると全く手がつけられずにいます。 以下のソースコードですが、strlen()と同じ働きをする関数mystrlen()と、strcmp()と同じ働きをする関数mystrcmpを、ポインタを使って作成するものです。どこをどうすればいいのか教えてくださいませんか。 #include <stdio.h> int main(void) { char str1[80], str2[80]; int i, j; int len1, len2; printf("第1の文字列を入力してください: "); gets(str1); printf("第2の文字列を入力してください: "); gets(str2); /* * 文字列の長さを確認する */ /* NULL文字(文字列の最後)まで読み飛ばす */ for (len1 = 0; len1 < 80 && str1[len1] != '\0'; len1++) ; /* ループ終了後、len1 に文字列の長さが入っている */ if (len1 < 80) { printf("%s は %d 文字の長さです\n", str1, len1); } else { printf ("第1の文字列が80字以上あります\n"); } /* str2 についても同様 */ for (len2 = 0; len2 < 80 && str2[len2] != '\0'; len2++) ; if (len2 < 80) { printf("%s は %d 文字の長さです\n", str2, len2); } else { printf ("第2の文字列が80字以上あります\n"); } if (len1 < 80 && len2 < 80) { for (i = 0; i < 80 && str1[i] != '\0' && str2[i] != '\0' && str1[i] == str2[i]; i++) ; if (str1[i] == str2[i]) { /* 両者同時に == '\0' のはず*/ printf("文字列は等しい\n"); } else if (str1[i] < str2[i]) { /* str1[i] == '\0' のはず*/ printf("%s は %s より小さい\n", str1, str2); } else { /* str2[i] == '\0' のはず*/ printf("%s は %s より大きい\n", str1, str2); } } /* * 十分なスペースがあれば、str2をstr1の最後に連結する */ if (len1 + len2 < 80) { /* str1 の末尾を探す */ for (i = 0; str1[i] != '\0'; i++) ; /* ループを抜けた段階では i は len1 と同じはずなので、 上記のループを作らず、i の代わりに len1 を用いるのも可 */ /* それ以降に str2 の中身をコピーする */ for (j = 0; str2[j] != '\0'; j++) { str1[i+j] = str2[j]; } str1[i+j] = '\0'; printf("%s\n", str1); } else { printf ("文字列をつなげた長さが80字以上あります\n"); } /* * str2をstr1にコピーする */ if (len1 + len2 < 80) { for (i = 0; str1[i] != '\0'; i++) { str1[i] = str2[i]; } str1[i] = '\0'; printf("%s %s\n", str1, str2); } return 0; }

  • 文字列に関する関数

    現在C言語の勉強をしております。 そこで、以下の関数の作成について質問させてください。 【関数の仕様】 引数の文字列から、'-'(ハイフン)と'P'以降を排除した文字列を返す。 自分なりに作成してみたのですが、コンパイルで警告が出てしまう状況です・・・。 もっとスマートに書けるんだろうとは思っているんですが、精一杯でした・・・。 どなたか教えていただけませんでしょうか? char *getDelStr(char *str) { int len = strlen(str); int count; char targetStr[32]; for(count = 0; count < len; count++){ if(str[count] != 'P'){ if(str[count] != '-'){ strcat(targetStr,str[count]); } }else{ return targetStr; } } return str; } 以上、よろしくお願いいたします。

  • 全角文字と半角文字を判別して文字列を追加

    全角文字と半角文字が混合している文字列に文字を追加するプログラムを考えています。 仕様としては全角から半角に変わる際には全角文字の後ろに1234を、 半角から全角に変わるときは半角文字の後ろに4321をつけるというものです。 例1 文字列が「あxxxお」ならば出力結果は「あ1234xxx4321お」 そこで質問なのですが 文字列から全角文字と半角文字をプログラム上で判別して 上記のように出力するにはどうしたらいいんでしょうか? ヒント等ございましたらどうぞお願いします。 とりあえず作ってみた例1の結果を無理やり出力するプログラムのコードを載せておきます。 こちらをうまく改変してくださっても結構ですのでよろしくお願いいたします。 #include <stdio.h> #include <string.h> int main(void){ unsigned char str0[256] = "あxxxお", str1[256] = "1234",str2[256]= "4321"; unsigned int zh,hz, len0 = strlen(str0),len1=strlen(str1),len2=strlen(str2); printf("挿入前:%s\n",&str0); zh=2; //全角から半角に変わる位置 hz=5; //半角から全角に変わる位置 //1234を挿入/// memmove(&str0[zh+len1], &str0[zh], len0 - zh+1); memcpy(&str0[zh], str1, len1); //4321を挿入/// memmove(&str0[hz+len1+len2], &str0[hz+len1], len0); memcpy(&str0[hz+len1], str2, len2); printf("挿入後:%s\n",&str0); return 0; }

  • 文字列操作(分割)のプログラムについて!

    ファイルのデータを1行ずつ読み込み、","で区切られた要素に分割して配列に格納するプログラムの作り方を教えてください。 下記のようなファイルがあり、各行の3つめの要素の数字(ハイフンを含む)を各行で比較し、昇順に行をソートするというプログラムを作成しております。 要素数は4つめ以降各行ばらばらです。 [ファイル test.txt] 2013/08/01,16:19,20130801161906-210164001071,,,川口,神奈川,,電話番号 2013/08/01,11:32,20130802003256-116091178056,鈴木,埼玉,mail,電話番号 2013/08/01,15:55,20130801155519-119072194140,,,山田,東京,mail まず、ファイルを読み込み、3つめの要素を下記のように配列s[i]に格納しようとしたのですが、うまく配列に3つめの要素がはいってくれません。 配列の格納にstrcpyを用いたところ、途中でプログラムが強制終了し、配列への格納ができませんでした。 この原因と対策がわからなくて困っております。 [格納の例] s[0]=20130801161906-210164001071 s[1]=20130802003256-116091178056 s[2]=20130801155519-119072194140 [自分のプログラム] #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 300 int main() { char filename[] = "test.txt"; FILE *fp; char data[MAX], *words[MAX],*s[MAX],*cp; const char *delim=","; int g,i=0,j,len; // ファイル・オープン if ((fp = fopen(filename, "r")) == NULL) { printf("ファイルのオープンに失敗\n"); exit(1); } while (fgets(data, MAX, fp) != NULL) //1行読み込む { cp = data; for (len = 0; len < MAX; len++) { if ((words[len] = strtok(cp, delim)) == NULL) //","で文字列を分割 break; cp = NULL; } s[i] = words[2]; //3つ目の要素を配列に格納 i++; } for(j=0;j<3;j++){ //表示 printf("%s\n",s[j]); } [実行結果] 20130801155519-119072194140 20130801155519-119072194140 20130801155519-119072194140 プログラムの訂正箇所,上記と異なるプログラム,大体の流れ… などなんでもかまいませんので、教えていただきたいです。よろしくお願いします。

  • javaの文字列分割

    文字列を分割して、またさらに分割することはできますでしょうか? 具体例をあげますと st = jave 入門,bai ダウンロード,kai ゲーム; この文字列をString[] str = st.sprit(",");で分割して、 さらにstrをString[][] strl = str.sprit(" ")で分割して表示すると str[0][0] = java str[0][1] = 入門 str[1][0] = bai str[1][1] = ダウンロード str[2][0] = kai str[2][1] = ゲーム という形にしたいのですが、どうしたらよいでしょうか?

  • 作ったプログラミングC何だけど、評価していただけませんが?不足があれば、教えてください!

    文字列「abc」の各アルファベットを1文字ずらすと文字列「bcd 」になり、 文字列「nisidate」の各アルファベットを2文字ずらすと文字 列「pkukfcvg」となる。さらに、 文字列「kibishii」の各アルファベットを2文字ずらすと文字 列「mkdkujkk」となる。 このような、任意の文字列の各要素を任意の文字数ずらすプロ グラムを作成する、なお、zを1文字ずらしたとき のアルファベットはaとする。 #include <stdio.h> #include <string.h> int main(void) { char str[27]="abcdefghijklmnopqrstuvwxyz",str1[50], str2[50]; int x,i,j,len; printf("文字列を入力---> "); scanf("%s", str1); printf("何文字ずらすかを入力---> "); scanf("%d",&x); len=strlen(str1); for(i=0;i<len;i++) { for(j=0;j<27;j++) { if(str1[i]=='z') { str2[i]=str[x-1]; } if(!(str1[i]=='z')) { if(str1[i]==str[j]) { str2[i]=str[j+x]; } } } } printf("%d文字ずらした文字列は%sです\n", x, str2); return 0; } よろしくお願いします!!

  • 文字列の途中から途中までを抽出

    文字列の一部を抽出したいときのプログラムです。 絶対条件は ・文字列は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];などにすればいいのですが、それ以外の方法でお願いします。

このQ&Aのポイント
  • Windows8で購入したノートン360のソフトを手動でアンインストールしようとしたが、許可確認の「はい」がクリックできない。ソフトを削除しないとスーパーセキュリティをインストールできない状態で困っている。
  • マカフィーのソフトは手動ではなく画面上で削除できたため、PC上の問題ではないと思われる。
  • ネット接続状態で再試行したが、同じ状況が続いている。ソースネクスト株式会社の製品・サービスについて質問している。
回答を見る

専門家に質問してみよう