scanfで苦戦した
まえおき
C言語の話。
コンパイラはgcc。
scanfを複数回実行すると入力バッファに改行文字が残って意図しない動作をすることがある。
その回避策として以下の2つがあった。
- 代入抑止文字を使う方法
scanf("%c%*c",&c);
- 空白文字を使う方法
scanf(" %c",&c);
ほんだい
目的
上記の方法を使って以下のようなことを実現する。
- 入力されたもののうち先頭にある文字だけを読み取る。
- どんな入力に対しても対処できるようにする。
実装
- 代入抑止文字を使う方法
scanf("%c%*[^\n]%*c", &ch);
先頭の文字を読み取り、入力バッファに残ってるものを読み捨てる。
例
#include <stdio.h> int main(void) { char ch; while (1) { scanf("%c%*[^\n]%*c", &ch); printf("ch:%c;%d\n", ch, ch); printf("--------------------\n"); } return 0; }
実行結果
q ch:q;113 strchr(str, ch):;4196100 -------------------- w ch: ;10 strchr(str, ch):;0 -------------------- e ch:e;101 strchr(str, ch):;4196102 -------------------- rty ch: ;10 strchr(str, ch):;0 --------------------
うまくいかない。
- 空白文字を使う方法
scanf(" %c%*[^\n]", &ch);
先頭の空白文字と改行を読み捨ててから、先頭の文字を読み取り、入力バッファに残っている改行文字までを読み捨てる。
例
#include <stdio.h> int main(void) { char ch; while (1) { scanf(" %c%*[^\n]", &ch); printf("ch:%c;%d\n", ch, ch); printf("--------------------\n"); } return 0; }
実行結果
q ch:q;113 strchr(str, ch):;4196100 -------------------- w ch:w;119 strchr(str, ch):;4196101 -------------------- e ch:e;101 strchr(str, ch):;4196102 -------------------- rty ch:r;114 strchr(str, ch):;4196103 --------------------
よさそう。
まとめ
scanfはなるべく使いたくない
NodeListは配列じゃないよって話
そういやdocument.querySelectorAll()でElementNodeの配列らしきものを受け取った時にisArray()を使ってもfalseが出るの何でなんだ?ブラケット[]で囲まれてるのに配列じゃないの?Array.push()はちゃんと出来たのになぜ?
— nimius (@nimiusxp) 2016, 1月 10
というわけで調べてみるとこんなのが出てきた。
NodeList are used very much like arrays and it's tempting to invoke Array.prototype methods on them, however NodeList objects don't have any of the familiar Array methods.
NodeList - Web APIs | MDN
簡単に言えば、document.querySelectorAll()で取得したNodeListは配列じゃなくて"配列っぽい"オブジェクトということ。配列と同じように扱うと痛い目みるよってわけ。
解決策としては配列に変換すればいいのだけど色々方法があるみたい。
- apply(), call()を使う方法
var nodeList = document.querySelectorAll("div"); //適当に取得 Array.isArray(nodeList); // false => not Array Array.isArray(Array.apply(nodeList)); // true => Array Array.isArray(Array.call(nodeList)); // true => Array Array.isArray(Array.prototype.slice.apply(nodeList)); // true => Array Array.isArray(Array.prototype.slice.call(nodeList)); // true => Array Array.isArray([].slice.apply(nodeList)); // true => Array Array.isArray([].slice.call(nodeList)); // true => Array
- Spread Operator(...)を使う方法
Array.isArray([...nodeList]); // true => Array Firefoxのみ
- Array.from()を使う方法
Array.isArray(Array.from(nodeList)); // true => Array Firefoxのみ
下の2つはまだサポートしてないブラウザが多いので一番上のが実用的みたい。
個人的には一番下が好み。
ツイートを10000文字にするブックマークレットを作った
こんにちは、nimius(@nimiusxp)です。初投稿です。
最近Twitterでツイートの最大文字数が10000文字になるのではないかという話題がありました。反対意見が多いようですが迷惑ならなければいいかなと思っています。
さて、今回はタイトルにある通り実際にTL上に10000文字のツイートで埋めてみたらどうなるかをブックマークレットで試してみました。コードは以下のようになります。
javascript:(function(){ //追加する適当な文字列 var extention = '試合を終えて家路へ向かうサッカー部員達。疲れからか、不幸にも黒塗りの高級車に追突してしまう。後輩をかばいすべての責任を負った三浦に対し、車の主、暴力団員谷岡に言い渡された示談の条件とは・・・。'; //ツイートのテキスト部分に当たるノードを取得 var tweetTextsNode = document.querySelectorAll('p.tweet-text'); //ノード群を配列にする。 var tweetTexts = Array.apply(null,tweetTextsNode); tweetTexts.forEach(function(item){ //10000文字前後になるまで文字列を追加する for(var i = 0; i < 10000; i+=extention.length){ item.textContent += extention } }); })();
上のリンクをブックマークして、Twiiter、TweetDeck内で使うことができます。
実際に使ってみましたが、1ツイートで画面が埋まってしまって非常に鬱陶しいです。下の画像はtweetdeck。
以上です。