質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Electron

Electronは、HTML5とNode.jsというWebの技術を用いてデスクトップアプリケーションを作成できるクロスプラットフォームな実行環境です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

7392閲覧

【JavaScript】indexOfで特定文字が反応しない

nnahito

総合スコア2004

Electron

Electronは、HTML5とNode.jsというWebの技術を用いてデスクトップアプリケーションを作成できるクロスプラットフォームな実行環境です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2017/01/11 14:22

編集2017/01/11 14:57

JavaScriptのindexOfメソッドで、文章の検索を実行しているのですが、
何故か「よという文字だけが反応しません。

「あ「漢「alphaなどはしっかりと開始位置が取得できます。
これはなぜでしょうか…?

perlで言う、http://www.shtml.jp/mojibake/sjis_cgi.htmlの様な現象なのでしょうか?

JavaScriptで、このような事例が、しかも「よで起こるということを聴いたことがなく、困惑しております。
ご存じの方がいらっしゃいましたら、ご教示ください。
よろしくお願いいたします。

追記

テンパりすぎて、コードの掲載などを失念しておりました。
追記いたします。


【やりたいこと】
文章の入った変数から、
開始文字から終了文字までを抜き出したい。


開始文字:「
終了文字:」
文章:「会話文1」地の文「会話文2」
理想結果:「会話文1」「会話文2」


【利用環境】

  • MacOS X Yosemite
  • FireFox 50.0.1
  • CodeMirror 5.22.1
  • Electron v1.4.12

【手順】
Electronウインドウ上のCodeMirrorを反映させたTextAreaから文字列を取得。
その中から会話文をのみを取得。

【状況】
Electronウインドウ上のCodeMirrorを反映させたTextAreaから文字列を取得はできており、変数に格納できている。
開始文字列(「)と、終了文字列(」)も取得できている。

それらを以下のオリジナルの関数に投げ、配列として結果を返したい。

なお、

  • text:全文章
  • from_text:開始文字列
  • to_text:終了文字列

としています。

JavaScript

1function createLinesCount(text, from_text, to_text){ 2 var start = 0; // 検索開始位置 3 var end = 0; // 検索終了位置 4 var lines = []; // 抜き出した文字列 5 6 // 検索終了文字が指定されていなければ、改行コードを終了文字にする 7 if ( to_text == "" ) to_text = "\n"; 8 9 while( 1 ){ 10 // 検索開始位置を取得 11 start = text.indexOf(from_text, start); 12 13 if ( start === -1 ) break; 14 15 // 検索終了位置を取得 16 end = start + to_text.length; 17 end = text.indexOf(to_text, end) + to_text.length; 18 19 // 文字の抜き出し 20 var line = text.substring(start, end); 21 22 // 抜き出した文字列を配列に追加 23 lines[lines.length] = line; 24 25 start = start + end; 26 27 } 28 29 return lines; 30 31 }

【結果】
●全文章
「あ」
「漢」
「よ」
「alpha」

●開始文字列

●終了文字列

●取得結果
イメージ説明

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

carimatics

2017/01/11 14:39

コードを掲載してください。また、そのコードにおける期待した結果と実際の結果も併せて掲載してください。
nnahito

2017/01/11 14:58

申し訳ありません。情報を追加しました。
guest

回答2

0

String.prototype.indexOf

問題なく動きましたので、現象を再現可能なコードを開示する事をお勧めします。

JavaScript

1'use strict'; 2console.log('「よ」'.indexOf('「よ')); // 0

残存する問題点

下記コードは質問文のコードをそのまま使用したものです。

質問の本題部分は ikedas さんの回答で解決できていますが、まだ問題が残っているように思います。

ローカル変数 lines

JavaScript

1var lines = []; // 抜き出した文字列

区切り文字が改行であるとは限らない為、変数名 lines に違和感があります。
質問文のケースにあてはめても改行を含まない文字列に対して処理を行う事が可能です。

JavaScript

1console.log(createLinesCount('「あ」「漢」「alpha」', '「', '」')); // ["「あ」","「漢」","「alpha」"]

第三引数(検索終了文字)の省略

JavaScript

1// 検索終了文字が指定されていなければ、改行コードを終了文字にする 2if ( to_text == "" ) to_text = "\n";

to_text が指定されなかった場合、undefined として評価されますが、undefined == "" は「偽」なのでこの条件式は正しく機能しません。
従って、第三引数を省略した場合に to_text.length の部分で「TypeError 例外」が発生してしまいます。

JavaScript

1createLinesCount('「あ」\n「漢」\n「よ」\n「alpha」', '「'); // TypeError: Cannot read property 'length' of undefined

検索終了文字列が持つからないと無限ループする

JavaScript

1// 検索終了位置を取得 2end = start + from_text.length; 3end = text.indexOf(to_text, end) + to_text.length;

検索終了文字列('to_text')が見つからなかった時の配慮がありません。
仮に次のコードを実行した場合、

JavaScript

1createLinesCount('「あ\n「漢\n「よ\n「alpha', '「', '」')); // "」" が見つからないので無限ループしてしまう

検索終了文字列('"」"')が見つからない為に text.indexOf(to_text, end) の評価値が -1 となり、to_text.length は 1 なので end が 0 にリセットされます。
すると、初めから検索をやり直すことになるので while 文が無限ループしてしまいます。

while(1)

JavaScript

1while( 1 ){

while (1) は無限ループになるリスクがある為、可能な限りループ継続条件となる条件式を与えてやるのが好ましいと思います。
前述の無限ループもwhile条件を見直すことで回避する事が可能です。

修正コード (String#indexOf版)

上記問題を修正したコードがこちら。

JavaScript

1'use strict'; 2function extractFromString(targetString, startString, endString){ // 検索対象文字列, 検索開始文字列, 検索終了文字列 3 // 全ての引数を String 型に変換する 4 targetString = String(targetString); 5 startString = String(startString); 6 endString = arguments.length > 2 ? String(endString) : '\n'; // 検索終了文字が指定されていなければ、改行コードを終了文字にする 7 8 var startStringLength = startString.length, // 検索開始文字列の文字数 9 endStringLength = endString.length, // 検索終了文字列の文字数 10 extractedStrings = [], // 抜き出した文字列リスト 11 startPosition, 12 endPosition; 13 14 do { 15 startPosition = targetString.indexOf(startString, startPosition); 16 17 if (startPosition !== -1) { 18 endPosition = targetString.indexOf(endString, startPosition + startStringLength); 19 20 if (endPosition !== -1) { 21 extractedStrings.push(targetString.slice(startPosition, endPosition + 1)); 22 startPosition = endPosition + endStringLength; 23 } 24 } 25 } while (startPosition !== -1 && endPosition !== -1); 26 27 return extractedStrings; 28} 29 30console.log(extractFromString('「あ」\n「漢」\n「よ」\n「alpha」', '「', '」')); // ["「あ」", "「漢」", "「よ」", "「alpha」"] 31console.log(extractFromString('「あ」「漢」「よ」「alpha」', '「', '」')); // ["「あ」", "「漢」", "「よ」", "「alpha」"] 32console.log(extractFromString('「あ」\n「漢」\n「よ」\n「alpha」', '「')); // ["「あ」\n", "「漢」\n", "「よ」\n"]

修正コード (正規表現版)

正規表現を利用するとスマートに実装できます。

JavaScript

1function extractFromString2 (targetString, startString, endString) { 2 // 正規表現化する為に文字列をエスケープする 3 startString = String(startString).replace(/(?=[$()*+\-.?\[]^{|}])/g, '\\'); 4 endString = arguments.length > 2 ? String(endString).replace(/(?=[$()*+\-.?\[]^{|}])/g, '\\') : '\n'; 5 6 return String(targetString).match(new RegExp(startString + '[^' + endString + ']*' + endString, 'g')); 7} 8 9console.log(extractFromString2('「あ」\n「漢」\n「よ」\n「alpha」', '「', '」')); // ["「あ」", "「漢」", "「よ」", "「alpha」"] 10console.log(extractFromString2('「あ」「漢」「よ」「alpha」', '「', '」')); // ["「あ」", "「漢」", "「よ」", "「alpha」"] 11console.log(extractFromString2('「あ」\n「漢」\n「よ」\n「alpha」', '「')); // ["「あ」\n", "「漢」\n", "「よ」\n"]

Re: nnahito さん

投稿2017/01/11 14:32

編集2017/01/12 03:44
think49

総合スコア18162

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nnahito

2017/01/11 14:57

申し訳ありません。 情報を追加しました。
think49

2017/01/12 03:45

To: nnahito さん 質問はクローズされていますが、まだ問題が残っているようなので親記事に追記しました。
guest

0

ベストアンサー

start = start + end;

ここは

start = end;

になるのでは?

ちなみに、今回の例では問題ないですが、

end = start + to_text.length;

end = start + from_text.length;

だと思います。

投稿2017/01/11 15:14

ikedas

総合スコア4317

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nnahito

2017/01/11 15:22

ご回答ありがとうございます。 修正したら治りました……お恥ずかしい…… たすかりました、ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問