2015年10月19日月曜日

PHP vsprintf "Argument number must be greater than zero"

謎のエラーが出て悩んだのでメモします。

PHP 5.5.29 にてコマンドラインから下記のスクリプトを実行しました。

■ソース(vsprintf.php)
<?php
$format = '%$1s';
$args = array( 'test' );
echo vsprintf( $format, $args );
?>

■実行結果
[kiya@test ~]$ php vsprintf.php
PHP Warning:  vsprintf(): Argument number must be greater than zero in /var/www/mainecoon/bat/vsprintf.php on line 4
PHP Stack trace:
PHP   1. {main}() /var/www/mainecoon/bat/vsprintf.php:0
PHP   2. vsprintf() /var/www/mainecoon/bat/vsprintf.php:4

vsprintf()の引数は0個より多くないとダメだよと言っているようです???
引数は $format, $args と2つ指定しているので「なに!?」となるわけですが、このエラーは $format の書式が間違っているのが原因です…え~~~。

$format で指定している '%$1s' は '%1$s' の間違いでおかしな所に$が現れたのでエラーになったんです。

そう、これエラーメッセージが間違っているんです><;

う~ん、実際には可変引数を受け取ってメッセージを合成して出力する関数でこのエラーに遭遇しまして、$formatの書式ははなから疑っていなかったため、結構な時間悩んでしまいました…

2015年9月30日水曜日

FREETEL priori2 LTE (FT151A) の USBドライバー

クライアント様がターゲット端末として priori2 を選択されたので実機デバッグをしようとしました。
3G専用の FT142Aは何もせずに使えましたが FT151Aは USBドライバーのインストール方法がわからずあれこれ調べたのでメモ書きします。

■参考サイト
http://pieceofnostalgy.blogspot.jp/2015/03/android-studioadb.html
※参考サイトというかここに書かれていた通りにすればOK
  1. 「設定」→「端末情報」を開き一番下の「ビルド番号」連打して「開発者」になる
  2. 「設定」→「開発者向けオプション」を開き「ON」にする
  3. USBケーブルでPCと接続
  4. ドライバーインストールでエラーになる
  5. PCのデバイスマネージャーを開き黄色い!マークの付いた「ADB interface」を右クリックして「プロパティ」を開く
  6. 「詳細」タブの「プロパティ」を「ハードウェアID」として「値」欄をメモ。私はコピペで秀丸へ
  7. Android SDK がインストールしてあるフォルダの下の 「extras\google\usb_driver\android_winusb.inf」を開く

    私の場合は下記でした。
    F:\ProgramFiles\Android\sdk\extras\google\usb_driver\android_winusb.inf
  8. [Google.NTamd64]セクションの末尾に上記でメモしたハードウェアIDを追加

    私の場合は下記を追加
    ;priori2 LTE FT151A
    %SingleAdbInterface%    = USB_Install, USB\VID_05C6&PID_9039
    %CompositeAdbInterface%  = USB_Install, USB\VID_05C6&PID_9039&MI_01
    
  9. デバイスマネージャにて5.のデバイスを右クリックして「ドライバー ソフトウェアの更新」を開く
  10. 7.のフォルダーを選択してドライバーをインストール

2015年9月10日木曜日

vim で改行時の自動コメントアウトを無効にする

ググるといろいろ出てきます。
下記の2つのページを参考に自分設定をしたので覚え書き。

■vim で改行での自動コメントアウトを無効にする
http://easyramble.com/disable-vim-auto-comment.html

■Vimで改行時の自動コメントアウトを無効化
http://qiita.com/necojackarc/items/1f997481764ed42023a7

  1.  vim を起動する
  2.  :set runtimepath? runtimepath=~/.vim,/usr/share/vim/vimfiles,/usr/share/vim/vim74,/usr/share/vim/vimfiles/after,~/.vim/after
  3.  # vi /usr/share/vim/vimfiles/after/plugin/common-settings.vim
  4.  au FileType * setlocal formatoptions-=ro を追加

これで全ユーザー、全ファイルタイプで「小さな親切、大きなお世話」をしなくなります。

2015年8月12日水曜日

Androidアプリにて自身のIPアドレスを取得

Android アプリを作っていて、環境による接続不良の原因を簡単に調べたいと思いアプリに自身のIP表示機能を実装しようと思いました。

自身のIP取得方法をGoogle先生に聞いてみるとあれこれ出てくるのですがどうもうまく動きません。

調べてみると InetAddressUtils.isIPv4Address() が "192.168.0.100" に対して false を返してくる…

これじゃァ駄目だ…

他の方法もいくつかあったのですがなんか書かれていることと結果が微妙に違っていたりするので適当に自分で作ってみました。

public String getLocalIpAddress() {
    String ip = null;
    try {
        // インターフェースを列挙
        Enumeration<networkinterface> en = NetworkInterface.getNetworkInterfaces();
        while ( (ip == null) && en.hasMoreElements() ) {
            // インターフェースオブジェクトを取得
            NetworkInterface ni = en.nextElement();

            // このインターフェースのアドレスを列挙
            Enumeration<inetaddress> ei = ni.getInetAddresses();
            while (ei.hasMoreElements()) {
                // アドレスを取得
                InetAddress ia = ei.nextElement();

                // IPv4でなければ無視
                if ( !(ia instanceof java.net.Inet4Address) ) {
                    continue;
                }
                // ループバックアドレスは無視
                if ( ia.isLoopbackAddress() ) {
                    continue;
                }

                // IPアドレスを取得
                ip = ia.getHostAddress();
                break;
            }
        }
    } catch (Exception ex) {
        Log.e("getLocalIpAddress: ", ex.toString());
    }

    return ip;
}

取得したInetAddress オブジェクトのクラスをチェックするというヤクザな方法なので、あまり参考にはならないかもしれません^^;

2013年11月27日水曜日

改造版ツイスター

10年以上前に書いたツイスターの改造版が見つかったので掲載します。GPLとかBSDとかのライセンスはよくわからないので、もし、この公開が問題あるようならご指摘くださいm(_ _)m

主な改造内容はコメントを見ていただければわかりますが、オリジナルの実装だと最初に作った乱数を使い果たすとすべてを再度作る様になっています。これでは実使用上、不特定のタイミングで大きなオーバーヘッドが生じることになってしまいます。

そこで乱数を使用するごとに次周の分を作成するようにしました。これにより実運用上は大きなオーバーヘッドの変化が生じないと思います。

Twister.h

#if !defined(AFX_TWISTER_H__7CBE0C01_D79E_11D2_A3E1_00606733955B__INCLUDED_)
#define AFX_TWISTER_H__7CBE0C01_D79E_11D2_A3E1_00606733955B__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

//====================================================================
//====================================================================
//====================================================================
//
// Twister.h: CTwister クラスのインターフェイス
//
//====================================================================
//====================================================================
//====================================================================

class CTwister  
{
    //================================================================
    //=== 構築/消滅 ==================================================
    //================================================================
public:
    CTwister();

    //================================================================
    //=== アトリビュート (定数) ======================================
    //================================================================
protected:
    enum {
        N = 624,                                // データースロット数
        M = 397,                                // インターリブ長
        MATRIX_A   = 0x9908b0df,                // constant vector a
        UPPER_MASK = 0x80000000,                // most significant w-r bits
        LOWER_MASK = 0x7fffffff,                // least significant r bits
    
        TEMPERING_MASK_B = 0x9d2c5680,
        TEMPERING_MASK_C = 0xefc60000,
    };

    //================================================================
    //=== アトリビュート (変数) ======================================
    //================================================================
protected:
    DWORD m_dwlData[N+M];
    int m_iCurPos;

    //================================================================
    //=== アトリビュート (関数) ======================================
    //================================================================
protected:
    DWORD dwGetData( int iIndex )
        { return m_dwlData[(iIndex) % (N+M)]; }

    DWORD dwCreateNew( int iPos );

    DWORD dwTemperingShiftU( DWORD dw )
        { return dw >> 11; }
    DWORD dwTemperingShiftS( DWORD dw )
        { return (dw <<  7) & (DWORD)TEMPERING_MASK_B; }
    DWORD dwTemperingShiftT( DWORD dw )
        { return (dw << 15) & (DWORD)TEMPERING_MASK_C; }
    DWORD dwTemperingShiftL( DWORD dw )
        { return dw >> 18; }

    //================================================================
    //=== オペレーション =============================================
    //================================================================
public:
    void Randomize( DWORD dwSeed = 0 );
    DWORD dwRandom( );

    int iRandom( )
        { return (int)dwRandom( ); }
    WORD wRandom( )
        { return (WORD)dwRandom( ); }

    DWORD dwRandom( DWORD dwLimit );
    int iRandom( int iLimit )
        { return (int)dwRandom( (DWORD)iLimit ); }

protected:
    void SetData( int iIndex, DWORD dwData )
        { m_dwlData[(iIndex) % (N+M)] = dwData; }
};

//====================================================================
//====================================================================
//====================================================================
#endif // !defined(AFX_TWISTER_H__7CBE0C01_D79E_11D2_A3E1_00606733955B__INCLUDED_)
Twister.cpp
//====================================================================
//====================================================================
//====================================================================
//
// Twister.cpp : CTwisterインプリメンテーション ファイル
//
//  元のアルゴリズムでは、一度に全スロットにデーターを設定し、使い終わ
//  ったらまた全スロット再設定するようになっていたが、これでは、処理速
//  度が変化してしまい使いにくいので、1つ使うごとに次週のデーターを作
//  成するように修正しました。
//
//  この修正のためデーターバッファのサイズが2倍になってしまいました。
//
//====================================================================
//====================================================================
//====================================================================

#include "stdafx.h"
#include "Twister.h"

//=== ヘッダー・ファイル・インクルード ===============================

//=== インライン関数インクルード =====================================

//====================================================================
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//====================================================================
//=== tempering parameters ===========================================
//====================================================================

//====================================================================
//=== 構築 ===========================================================
//====================================================================

CTwister::CTwister()
{
    Randomize( 4357/*0*/ );
}

//====================================================================
//=== 新たなデーターの作成 ===========================================
//====================================================================

inline DWORD CTwister::dwCreateNew( int iPos )
{
    DWORD dw0 =  dwGetData( iPos );
    DWORD dw1 =  dwGetData( iPos + 1 );
    DWORD dwM =  dwGetData( iPos + M );

    DWORD dw = (dw0 & (DWORD)UPPER_MASK) | (dw1 & (DWORD)LOWER_MASK);
    dw = dwM ^ (dw >> 1) ^ ((dw & 1) ? MATRIX_A : 0);

    return dw;
}

//====================================================================
//=== 乱数初期化 =====================================================
//====================================================================

void CTwister::Randomize( DWORD dwSeed/* = 0*/ )
{
    if ( dwSeed )
        m_dwlData[0] = dwSeed & 0xffffffff;
    else
        m_dwlData[0] = ::GetTickCount( );

    //================================================================
    for ( m_iCurPos = 1 ; m_iCurPos < N ; ++ m_iCurPos )
        m_dwlData[m_iCurPos] = ( 69069 * m_dwlData[m_iCurPos-1] ) & 0xffffffff;

    //================================================================
    for ( int i = 0 ; i < N ; ++ i )
    {
        DWORD dw = dwCreateNew( i );
        SetData( i, dw );
    }

    //================================================================
    m_iCurPos = 0;
}

//====================================================================
//=== 乱数発生 =======================================================
//====================================================================

DWORD CTwister::dwRandom( )
{
    //================================================================
    //=== 今回の乱数を生成 ===========================================
    //================================================================
    DWORD dwRet = m_dwlData[m_iCurPos];

    //=== +M 位置の作成のため今回の値を保存 ==========================
    SetData( m_iCurPos + N, dwRet );

    //=== 乱数作成 ===================================================
    dwRet ^= dwTemperingShiftU(dwRet);
    dwRet ^= dwTemperingShiftS(dwRet);
    dwRet ^= dwTemperingShiftT(dwRet);
    dwRet ^= dwTemperingShiftL(dwRet);

    //================================================================
    //=== 次周の為のデーターを作成 ===================================
    //================================================================
    DWORD dw = dwCreateNew( m_iCurPos );
    SetData( m_iCurPos + N, dw );

    //================================================================
    //================================================================
    //================================================================
    m_iCurPos = (m_iCurPos + 1) % (N + M);

    //================================================================
    //================================================================
    //================================================================
    return dwRet; 
}

//====================================================================
//=== 引数未満の乱数を発生 ===========================================
//====================================================================

//DWORD CTwister::dwRandom( DWORD dwLimit )
//{
//  return (int)(((__int64)dwRandom() * (__int64)dwLimit) >> 32);
//}
//
#pragma warning(disable : 4035)
DWORD CTwister::dwRandom( DWORD dwLimit )
{
    dwRandom( );
__asm
    {
        MUL     [dwLimit]
        MOV     EAX, EDX
    }
}
#pragma warning(default : 4035)

//====================================================================
//=== オリジナルです =================================================
//====================================================================
//
//DWORD CTwister::dwRandom( )
//{
//  DWORD y;
//  static DWORD mag01[2] = {0x0, MATRIX_A};
//
//  if ( m_iCurPos >= N )
//  {
//      /* generate N words at one time */
//      int kk;
//
//      if ( m_iCurPos == N+1 )   /* if sgenrand() has not been called, */
//          Randomize( 4357 ); /* a default initial seed is used   */
//
//      for (kk=0;kk> 1) ^ mag01[y & 0x1];
//      }
//
//      for (;kk> 1) ^ mag01[y & 0x1];
//      }
//
//      y = (m_dwlData[N-1]&UPPER_MASK) | (m_dwlData[0]&LOWER_MASK);
//      m_dwlData[N-1] = m_dwlData[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
//
//      m_iCurPos = 0;
//  }
//
//  y = m_dwlData[m_iCurPos++];
//  y ^= TEMPERING_SHIFT_U(y);
//  y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
//  y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
//  y ^= TEMPERING_SHIFT_L(y);
//
//  return y; 
//}

2013年1月16日水曜日

1.9.0 で jQuery.browser がエラーになる


管理画面で使用している cleditor が突然動かなくなったとお客様より連絡があり調べたところ、非推奨メソッドの jQuery.browser が使用されていました。

恐らく、jQuery が 1.9.0 にバージョンアップされた際に削除されたものと思われます。

とりあえずの対応としては下記の2通りあるかと思います。

1. jquery-1.8.3.min.js を使う

2. 下記のパッチを当てる
//@@mod  ie = $.browser.msie,
  ie = (typeof($.browser.msie) != 'undefined') ? $.browser.msie : false;

//@@mod  documentClickAssigned,
  documentClickAssigned = false,

2012年12月7日金曜日

IE8 で文字化け

常識かもしれませんが、ちと引っかかったのでメモ。

ヘッダーのメタタグに下記を入れたページを作成しました。

<meta http-equiv="Content-Type" content="text/html; charset=UTF8">

これが IE8 だと見事に文字化けしました><;

Content-Type で文字セットしてしているのになんでだ!?スペルミス?

さっそくグーグル先生に問い合わせてみるとどうやら UTF-8 が正解だったようです。大文字小文字の区別はないようです。

うむむ、ちと恥ずかしいミスでした…