ludwig125のブログ

頑張りすぎずに頑張る父

Ubuntu14.0.4でホスト名とユーザ名を変更する

概要

VMのUbuntu14.0.4でホスト名とユーザ名を変更したのが意外と大変だったのでメモ

以下では、ホスト名も、ユーザ名も、gitアカウントと同じ「ludwig125」にすることを目指した

参考

Ubuntu14.04でホスト名を変更する - Qiita

ホスト名

ホスト名:hostnameコマンドの結果出力するUbuntuのホスト名を指す

ホスト名の変更は簡単だった

  • 以下のホスト名を変更するだけ
 sudo vim /etc/hostname
 sudo vim /etc/hosts

反映させるにはUbuntuの再起動が必要

確認

$ hostname
ludwig125-virtual-machine

※「-virtual-machine」の部分をつけたほうがホスト名として分かり易いのでつけた

ユーザ名の変更

ユーザ名:whoコマンドで出力されるユーザの名前

ユーザ名の変更はusermodで行う

Man page of USERMOD

usermodをする上での問題

しかし、自分のユーザ名を変更しようとしても、自分自身のプロセスがあるので変えられないという問題がある

$ sudo usermod -l ludwig125 <今のユーザ名>
usermod: user <今のユーザ名> is currently used by process 1495
$ 

別のユーザを作る

自分自身のプロセスが動いている状態で自分のユーザ名を変えられないので、別にユーザを作った (もっといい方法があるかもしれない・・・)

  • adduserで「temp_user」ユーザを追加
$ sudo adduser temp_user
ユーザー `temp_user' を追加しています...
新しいグループ `temp_user' (1001) を追加しています...
新しいユーザー `temp_user' (1001) をグループ `temp_user' に追加しています...
ホームディレクトリ `/home/temp_user' を作成しています...
`/etc/skel' からファイルをコピーしています...
新しい UNIX パスワードを入力してください: 
新しい UNIX パスワードを再入力してください: 
passwd: パスワードは正しく更新されました
temp_user のユーザ情報を変更中
新しい値を入力してください。標準設定値を使うならリターンを押してください
    フルネーム []: temp
    部屋番号 []: 
    職場電話番号 []: 
    自宅電話番号 []: 
    その他 []: 
以上で正しいですか? [Y/n] y

temp_userにsudo権限を追加

作ったばかりのtemp_userにはsudo権限がないので temp_userでusermodをすると以下のエラーが出た

$ usermod
コマンド 'usermod' は '/usr/sbin/usermod' で利用できます
'/usr/sbin'がPATH環境変数に含まれていないためコマンドを特定できませんでした。
大抵の場合、お使いのユーザーアカウントに管理者特権がないことが原因です。
usermod: コマンドが見つかりません
temp_user@ludwig125-virtual-machine:/home$ useradd
コマンド 'useradd' は '/usr/sbin/useradd' で利用できます
'/usr/sbin'がPATH環境変数に含まれていないためコマンドを特定できませんでした。
大抵の場合、お使いのユーザーアカウントに管理者特権がないことが原因です。
useradd: コマンドが見つかりません

temp_userでusermodをできるように、予めtemp_userにsudo権限を付けておく

sudoユーザーを追加する方法 - Linux入門 - Webkaru

以下はtemp_userではなく、もとのユーザ権限で実行

 usermod -G sudo temp_user

temp_userでログインし直す

ubuntuのユーザをみて、temp_userに切り替える

temp_userでusermod実行

temp_user内で改めてusermodを実行

$ sudo usermod -l ludwig125 <今のユーザ名>
usermod: user <今のユーザ名> is currently used by process 1495
$ 

もとのユーザのプロセスが動いているので、全部killする

sudo kill -9 プロセスID

再度usermodを実行したら、今度はうまくいった

ユーザディレクトリの名前を変更

$ ls /home
$ cd /home
$ sudo mv もとのユーザ ludwig125
$ ls /home
ludwig125  temp_user

whoで確認

[~] $ who
ludwig125 :0           2017-12-16 22:42 (:0)
ludwig125 pts/5        2017-12-16 22:46 (:0:S.0)
ludwig125 pts/13       2017-12-16 22:46 (:0:S.1)
[~] $ 

更に/etc/passwdのユーザディレクトリを変える

$ sudo vim /etc/passwd
で
ludwig125:x:1000:1000:ludwig125:/home/ludwig125:/bin/bash
↑この/home以下のディレクトリ名をもとのユーザ名から変える

上記までの対応によって生じた問題

トラブル1.VMとホストOSとの間でコピペができない

名前変更後、VMのデータをコピーしてホストOSのWindowsにペーストできないという問題が生じた

ホスト名を変えてしまったのでvmwaretoolsが機能していない可能性がある

いったんVMもホストOSも再起動したらコピペができるようになった

VMware Tools の概要
VMware Tools は、仮想マシンのゲスト OS のパフォーマンスを強化し、仮想マシンの管理を改善するユーティリティのスイートです。ゲスト OS に VMware Tools をインストールしておかないと、ゲストで重要な機能を実行できません。VMware Tools をインストールすると、次のような問題が排除または改善されます。
ビデオの解像度が低い
カラー深度が不十分
ネットワーク速度の表示が正しくない
マウスの動きが制限される
コピー アンド ペーストやファイルのドラッグ アンド ドロップができない
音声が出ない
ゲスト OS の静止スナップショットを作成する機能が用意される
ゲスト OS とホストの時刻が同期される

トラブル2. linuxのグループが変わっていない

グループ名が昔のまま変わっていなかったので変える

usermod -g グループ名 ユーザ名
[/home] $ sudo groupadd ludwig125
[/home] $ sudo  usermod -g  ludwig125 ludwig125
[/home] $ 

トラブル3. git に接続できない

名前変更後、gitに接続できない

git pullできない 「Permission denied (publickey).」が出た

[~/git/work] $ git pull
Warning: Permanently added the RSA host key for IP address '192.30.255.113' to the list of known hosts.
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
[~/git/work] $ 

以下を参考に調べて見る

githubで"Permission denied (publickey)."が出た時はssh -Tで繋ぎ直す - Qiita Error: Permission denied (publickey) - User Documentation Git - SSH 公開鍵の作成

[~/git/work] $ ssh -vT git@github.com
OpenSSH_6.6.1, OpenSSL 1.0.1f 6 Jan 2014
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: Applying options for *
debug1: Connecting to github.com [192.30.255.112] port 22.
debug1: Connection established.
debug1: identity file /home/ludwig125/.ssh/id_rsa type 1
debug1: identity file /home/ludwig125/.ssh/id_rsa-cert type -1
debug1: identity file /home/ludwig125/.ssh/id_dsa type -1
debug1: identity file /home/ludwig125/.ssh/id_dsa-cert type -1
debug1: identity file /home/ludwig125/.ssh/id_ecdsa type -1
debug1: identity file /home/ludwig125/.ssh/id_ecdsa-cert type -1
debug1: identity file /home/ludwig125/.ssh/id_ed25519 type -1
debug1: identity file /home/ludwig125/.ssh/id_ed25519-cert type -1
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.8
debug1: Remote protocol version 2.0, remote software version libssh_0.7.0
debug1: no match: libssh_0.7.0
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-ctr hmac-sha1 none
debug1: kex: client->server aes128-ctr hmac-sha1 none
debug1: sending SSH2_MSG_KEX_ECDH_INIT
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: RSA 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48
debug1: Host 'github.com' is known and matches the RSA host key.
debug1: Found key in /home/ludwig125/.ssh/known_hosts:1
debug1: ssh_rsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Offering RSA public key: /home/ludwig125/.ssh/id_rsa
debug1: Authentications that can continue: publickey
debug1: Trying private key: /home/ludwig125/.ssh/id_dsa
debug1: Trying private key: /home/ludwig125/.ssh/id_ecdsa
debug1: Trying private key: /home/ludwig125/.ssh/id_ed25519
debug1: No more authentication methods to try.
Permission denie
[~/git/work] $

ホスト名を変えたからなのか、なぜなのかわからないけれど、git にssh鍵が登録されていないみたい

以前書いた自分のブログを参考にssh鍵を作って登録し直す

ludwig125.hatenablog.com

登録後

[~/git/work] $ ssh -vT git@github.com
OpenSSH_6.6.1, OpenSSL 1.0.1f 6 Jan 2014
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: Applying options for *
debug1: Connecting to github.com [192.30.255.113] port 22.
debug1: Connection established.
debug1: identity file /home/ludwig125/.ssh/id_rsa type 1
debug1: identity file /home/ludwig125/.ssh/id_rsa-cert type -1
debug1: identity file /home/ludwig125/.ssh/id_dsa type -1
debug1: identity file /home/ludwig125/.ssh/id_dsa-cert type -1
debug1: identity file /home/ludwig125/.ssh/id_ecdsa type -1
debug1: identity file /home/ludwig125/.ssh/id_ecdsa-cert type -1
debug1: identity file /home/ludwig125/.ssh/id_ed25519 type -1
debug1: identity file /home/ludwig125/.ssh/id_ed25519-cert type -1
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.8
debug1: Remote protocol version 2.0, remote software version libssh_0.7.0
debug1: no match: libssh_0.7.0
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-ctr hmac-sha1 none
debug1: kex: client->server aes128-ctr hmac-sha1 none
debug1: sending SSH2_MSG_KEX_ECDH_INIT
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: RSA 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48
The authenticity of host 'github.com (192.30.255.113)' can't be established.
RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,192.30.255.113' (RSA) to the list of known hosts.
debug1: ssh_rsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Offering RSA public key: /home/ludwig125/.ssh/id_rsa
debug1: Server accepts key: pkalg ssh-rsa blen 279
debug1: key_parse_private2: missing begin marker
debug1: read PEM private key done: type RSA
debug1: Authentication succeeded (publickey).
Authenticated to github.com ([192.30.255.113]:22).
debug1: channel 0: new [client-session]
debug1: Entering interactive session.
debug1: Sending environment.
debug1: Sending env LANG = ja_JP.UTF-8
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
Hi ludwig125! You've successfully authenticated, but GitHub does not provide shell access.
debug1: channel 0: free: client-session, nchannels 1
Transferred: sent 3312, received 1872 bytes, in 0.2 seconds
Bytes per second: sent 14182.2, received 8016.0
debug1: Exit status 1
[~/git/work] $

成功 git pullもgit pushもできるようになった! ブログ書いててよかったよ

トラブル4. pip3が使えなくなってた

誤ったインタプリタです: そのようなファイルやディレクトリはありません

pip3を使おうとしたらこんなエラーが

[~/git/work/src/python/memo/pandas] $ pip3 install pandas_ply
/home/ludwig125/.pyenv/pyenv.d/exec/pip-rehash/pip: /home/ludwig125/.pyenv/versions/3.5.4/bin/pip3: /home/前のユーザ名/.pyenv/versions/3.5.4/bin/python3.5: 誤ったインタプリタです: そのようなファイルやディレクトリはありません

前のユーザ名のパスを見ようとしている?

解決できないのでpyenvごと削除して作り直す

[~] $ pyenv versions
* system (set by /home/ludwig125/.python-version)
  3.5.4
[~] $ pyenv uninstall 3.5.4
pyenv: remove /home/ludwig125/.pyenv/versions/3.5.4? yes
[~] $ 


[~] $  pyenv install 3.5.4
Downloading Python-3.5.4.tar.xz...
-> https://www.python.org/ftp/python/3.5.4/Python-3.5.4.tar.xz
Installing Python-3.5.4...
Installed Python-3.5.4 to /home/ludwig125/.pyenv/versions/3.5.4

$ pyenv local 3.5.4で移動

これでpip3を使えるようにになった

[~] $ 
[~] $ pip3 --version
pip 9.0.1 from /home/ludwig125/.pyenv/versions/3.5.4/lib/python3.5/site-packages (python 3.5)
[~] $ 

pythonでseleniumを使う

参考

とりあえず参考になったページを貼っておく

入門、Selenium - Seleniumの仕組み | CodeGrid

Selenium使ってみた(Python) - コンピュータサイエンス系勉強ノート

PythonでSeleniumを使ってスクレイピング (基礎) - Qiita

3秒でわかるSeleniumのつかいかた(Python・ちょっとDjango) - へっぽこびんぼう野郎のnewbie日記

Selenium使ってみた(Python) - コンピュータサイエンス系勉強ノート

準備

seleniumをインストール

$ pip3 install selenium

以下からchromedriverをダウンロード

以下のファイルを実行

$ cat selenium-test.py
from selenium import webdriver
browser = webdriver.Chrome(executable_path='/home/ludwig125/chromedriver')
browser.get('https://www.yahoo.co.jp/')

実行

python3 selenium-test.py 

Chromeが起動してyahooのページが表示される

f:id:ludwig125:20171216230538p:plain

トラブル対応

moduleが無いとかでうまく実行できなかったので、以下を確認し直す

$ sudo apt install python3-pip python3-dev

$ pyenv install 3.5.4
$ pyenv local 3.5.4
$ pyenv versions
  system
* 3.5.4 (set by /home/ludwig125/git/work/src/python/.python-version)
$ 

python3のパスを確認

$ which python3
/home/ludwig125/.pyenv/shims/python3
$ /home/ludwig125/.pyenv/shims/python3 --version
Python 3.5.4
$ 

pythonでグラフを描画(matplotlib)

グラフの例(sin関数)

【Python入門】ライブラリmatplotlibの基本的な使い方 - Qiita

[~/git/work/src/python] $ cat test.py
import math
import numpy as np
from matplotlib import pyplot

pi = math.pi

x = np.linspace(0, 2*pi, 100)
y = np.sin(x)

pyplot.plot(x, y)
pyplot.show()
[~/git/work/src/python] $ 

実行

python3 test.py 

f:id:ludwig125:20171207010603p:plain

以下、これを表示するまでのエラー

エラー対応

参考

matplotlibが描画されない - DISTRICT 37

python - python3 で _tkinter を import したい - スタック・オーバーフロー

ImportError:
Importing the multiarray numpy extension module failed.  Most
likely you are trying to import a failed build of numpy.
If you're working with a numpy git repo, try `git clean -xdf` (removes all
files not under version control).  Otherwise reinstall numpy.

Original error was: /usr/local/lib/python2.7/dist-packages/numpy/core/multiarray.so: undefined symbo
l: _Py_ZeroStruct

[~/git/work/src/python/software-design/saikyu-kouka] $ pip3 install numpy
Traceback (most recent call last):
  File "/usr/local/bin/pip3", line 7, in <module>
    from pip import main
  File "/usr/local/lib/python3.6/site-packages/pip/__init__.py", line 26, in <module>
    from pip.utils import get_installed_distributions, get_prog
  File "/usr/local/lib/python3.6/site-packages/pip/utils/__init__.py", line 16, in <module>
    import subprocess
  File "/usr/local/lib/python3.6/subprocess.py", line 136, in <module>
    import _posixsubprocess
ImportError: /usr/local/lib/python2.7/dist-packages/_posixsubprocess.so: undefined symbol: Py_InitMo
dule4_64


や

 Traceback (most recent call last):
  File "test.py", line 3, in <module>
    from matplotlib import pyplot
  File "/usr/local/lib/python3.6/site-packages/matplotlib/pyplot.py", line 113, in <module>
    _backend_mod, new_figure_manager, draw_if_interactive, _show = pylab_setup()
  File "/usr/local/lib/python3.6/site-packages/matplotlib/backends/__init__.py", line 60, in pylab_setup
    [backend_name], 0)
  File "/usr/local/lib/python3.6/site-packages/matplotlib/backends/backend_tkagg.py", line 6, in <module>
    from six.moves import tkinter as Tk
  File "/usr/local/lib/python2.7/dist-packages/six.py", line 92, in __get__
    result = self._resolve()
  File "/usr/local/lib/python2.7/dist-packages/six.py", line 115, in _resolve
    return _import_module(self.mod)
  File "/usr/local/lib/python2.7/dist-packages/six.py", line 82, in _import_module
    __import__(name)
  File "/usr/local/lib/python3.6/tkinter/__init__.py", line 36, in <module>
    import _tkinter # If this fails your Python may not be configured for Tk
ModuleNotFoundError: No module named '_tkinter'

などのエラーが出た

もう面倒になったので、pyenvをつくって、入れ直した

$ sudo apt install python3-pip python3-dev

$ pyenv install 3.5.4
$ pyenv local 3.5.4
$ pyenv versions
  system
* 3.5.4 (set by /home/ludwig125/git/work/src/python/.python-version)
$ 

python3のパスを確認

$ which python3
/home/ludwig125/.pyenv/shims/python3
$ /home/ludwig125/.pyenv/shims/python3 --version
Python 3.5.4
$ 

追加で必要なライブラリをインストール

$ python3 -m pip install numpy
$ python3 -m pip install matplotlib

tkinterが使えることを確認

$ python3 -m tkinter

f:id:ludwig125:20171207011158p:plain

グラフの例(1次関数)

$ cat y-is-10x.py 
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 99, 100)

y = x * 10

plt.plot(x, y)
plt.show()

実行結果

 $ python3  y-is-10x.py 

f:id:ludwig125:20171207012956p:plain

グラフの例(ノイズの入った1次関数)

$ cat noisy_y.py 
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 99, 100)

f_noisy = np.vectorize(lambda x: x * 10 + np.random.normal(0, 100))
d = f_noisy(x)

plt.plot(x, d)
plt.show()

実行結果

python3 noisy_y.py 

f:id:ludwig125:20171207013117p:plain

グラフの例(放物線)

$ cat throw.py 

from math import sin, cos, radians
from matplotlib import pyplot as plt

def throw(x, y, v0, angle, repeatNum, dt):
    isSuccess = False
    xarray = []; yarray = []
    vx = v0*cos( radians(angle) )
    vy = v0*sin( radians(angle) )
    ax = 0.0
    ay = -9.8
    for i in range(repeatNum):
        x = x + (vx + ax*dt/2)*dt
        y = y + (vy + ay*dt/2)*dt
        vx = vx + ax * dt
        vy = vy + ay * dt
        xarray.append(x)
        yarray.append(y)
    return (xarray, yarray, isSuccess)

def prepareFigureArea():
    plt.figure(figsize=(5, 5))
    plt.xlim([0, 5])
    plt.ylim([0, 5])
    plt.xlabel('X - Axis (m)')
    plt.ylabel('Y - Axis (m)')
    return

x1, y1, isSuccess = throw(0, 0, 6, 35, 500, 0.01)
x2, y2, isSuccess2 = throw(0, 0, 6, 45, 500, 0.01)
x3, y3, isSuccess3 = throw(0, 0, 6, 55, 500, 0.01)
x4, y4, isSuccess3 = throw(0, 0, 6, 70, 500, 0.01)

prepareFigureArea()
plt.plot(x1, y1, 'bo-', x2, y2, 'ro-', x3, y3, 'ko-', x4, y4, 'yo-')
plt.legend(['35 deg.', '45 deg.', '55 deg.', '70 deg.'])
plt.show()

実行結果

python3 throw.py

以下が必要だったのでpip3 install

$ pip3 install six
$ pip3 install pyparsing
$ pip3 install cycler
$ pip3 install python-dateutil --upgrade

f:id:ludwig125:20171209004734p:plain

matplotlibの仕様

グラフの点や線の形

グラフの色

matplotlib参考

MSGPACK_DEFINEが32個までしか対応していない問題

msgpackについては以下を参照

ludwig125.hatenablog.com

問題

MSGPACK_DEFINEで33個以上の引数を取ることができなかった

msgpackのバージョン

現在のmasterのバージョンは2.1.5

https://github.com/msgpack/msgpack-c/blob/master/CHANGELOG.md

MSGPACK_DEFINEとは

保存したいクラスのメンバ変数を、MSGPACK_DEFINEマクロに入れると、 自動でシリアライズ/デシリアライズできる

https://github.com/msgpack/msgpack-c/blob/master/QUICKSTART-CPP.md#user-defined-classes

You can use serialize/deserializes user-defined classes using MSGPACK_DEFINE macro.

ソースコード

MSGPACK_DEFINEの数が32のファイル

[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ cat msgpack_define_before-expand32.cpp
#include <msgpack.hpp>
#include <vector>
#include <string>
#include <iostream>

class myclass {
public:
    std::string var[32];

    MSGPACK_DEFINE(
    var[0], var[1], var[2], var[3], var[4], var[5], var[6], var[7], var[8], var[9], var[10], var[11], var[12], var[13], var[14], var[15], var[16], var[17], var[18], var[19], var[20], var[21], var[22], var[23], var[24], var[25], var[26], var[27], var[28], var[29], var[30], var[31]);
    myclass() {
        var[0] = "0";
        var[1] = "1";
        var[2] = "2";
        var[3] = "3";
        var[4] = "4";
        var[5] = "5";
        var[6] = "6";
        var[7] = "7";
        var[8] = "8";
        var[9] = "9";
        var[10] = "10";
        var[11] = "11";
        var[12] = "12";
        var[13] = "13";
        var[14] = "14";
        var[15] = "15";
        var[16] = "16";
        var[17] = "17";
        var[18] = "18";
        var[19] = "19";
        var[20] = "20";
        var[21] = "21";
        var[22] = "22";
        var[23] = "23";
        var[24] = "24";
        var[25] = "25";
        var[26] = "26";
        var[27] = "27";
        var[28] = "28";
        var[29] = "29";
        var[30] = "30";
        var[31] = "31";
}
};

int main(void) {
        std::vector<myclass> vec;
        // add some elements into vec...
        vec.push_back(myclass());

        // you can serialize myclass directly
        msgpack::sbuffer sbuf;
        msgpack::pack(sbuf, vec);

        msgpack::object_handle oh =
            msgpack::unpack(sbuf.data(), sbuf.size());

        msgpack::object obj = oh.get();

        // you can convert object to myclass directly
        std::vector<myclass> rvec;
        obj.convert(rvec);

        for(std::vector<myclass>::iterator it = rvec.begin(); it != rvec.end(); ++it) {

            for(int i = 0; i < 32; i++) {
                std::cout << (*it).var[i] << std::endl;
            }
        }
}
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ 

コンパイルと実行結果

[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ g++ -Ipath_to_msgpack/include msgpack_define_before-expand32.cpp
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ ./a.out 
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ 

これはできる

MSGPACK_DEFINEの数が33のファイル

上のファイルで33個目を追加するとコンパイルに失敗

コンパイルエラー抜粋

 /usr/local/include/msgpack/v1/adaptor/detail/cpp03_define_array.hpp:4468:171: note:   template argument deduction/substitution failed:
In file included from /usr/local/include/msgpack/adaptor/define.hpp:13:0,
                 from /usr/local/include/msgpack/type.hpp:25,
                 from /usr/local/include/msgpack.hpp:18,
                 from msgpack_define_before-expand33.cpp:1:
msgpack_define_before-expand33.cpp:10:5: note:   candidate expects 32 arguments, 33 provided
     MSGPACK_DEFINE(
     ^
In file included from /usr/local/include/msgpack/v1/adaptor/define.hpp:14:0,
                 from /usr/local/include/msgpack/adaptor/define.hpp:15,
                 from /usr/local/include/msgpack/type.hpp:25,
                 from /usr/local/include/msgpack.hpp:18,
                 from msgpack_define_before-expand33.cpp:1:

MSGPACK_DEFINEの定義

https://github.com/msgpack/msgpack-c/blob/315bbd4b40ba5b21bfaeced0e5b7688d833a5b91/include/msgpack/v1/adaptor/detail/cpp03_define_array.hpp#L4470

return define_array<A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24, A25, A26, A27, A28, A29, A30, A31>(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31);
  • MSGPACK_DEFINEで呼んでいる関数には32個までしか対応していない

対応策

考えられる対応策は以下の3つ

  • 案1.c++11にする
  • 案2.MSGPACK_DEFINEを入れ子にする
  • 案3.拡張版のMSGPACK_DEFINEを作成する

以下詳細を説明

案1.c++11にする

c++11なら出来るらしい

msgpackの1.0以上、かつc++11だったら33個以上もできそう https://github.com/msgpack/msgpack-c/issues/11

for c++98, we can't extend it easily, all we can do is just write extra specialization for more args. but for c++11, we can use variadic template to break it, although, there is limit, but it's compiler's business.

これができるならそれで問題ない

c++11でコンパイルが通ることを確認

上でコンパイルエラーになったmsgpack_define_before-expand33.cppをc++11でコンパイル

[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ g++ -Ipath_to_msgpack/include -std=c++11 msgpack_define_before-expand33.cpp
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ ./a.out 
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ 

案2.MSGPACK_DEFINEを入れ子にする

  • 例えば、stuct Aに33個以上の項目を入れてまとめてMSGPACK_DEFINEをしようとすると失敗する
  • そこで、別にstruct Bを用意して、その中に項目を入れて、MSGPACK_DEFINEし、さらにそのstructBをstructAの一要素とすれば(入れ子にすれば)、それぞれのstructの項目数は32個を超えずに済む
  • 多分これでもできそうだが、入れ子になるのが気持ち悪かったので試してない

案3.拡張版のMSGPACK_DEFINEを作成する

  • msgpack 0.5ではかんたんだったけど、最新版は難しい

手順1.拡張版ファイルの作成

https://github.com/msgpack/msgpack-c/tree/315bbd4b40ba5b21bfaeced0e5b7688d833a5b91/erb/v1

ここのerbのGENERATION_LIMIT = 31を40とかに書き換える

https://github.com/msgpack/msgpack-c/blob/315bbd4b40ba5b21bfaeced0e5b7688d833a5b91/erb/v1/cpp03_define_array.hpp.erb#L24

今回上のソースコードで使っているのはarrayだけなので、arrayとそこでつかっているtupleだけ増やしたファイルを用意すればいい(mapは不要) なので、以下のファイルのLIMITを40とかに書き換える

  • cpp03_msgpack_tuple_decl.hpp.erb
  • cpp03_msgpack_tuple.hpp.erb
  • cpp03_define_array_decl.hpp.erb
  • cpp03_define_array.hpp.erb

あとは、以下のファイルを実行すれば、修正したerbをもとに拡張版のヘッダファイルが自動で作成される

https://github.com/msgpack/msgpack-c/blob/315bbd4b40ba5b21bfaeced0e5b7688d833a5b91/preprocess

rubyが無いと言われたので以下でインストール

http://kwski.net/linux/1223/

# apt-add-repository ppa:brightbox/ruby-ng  // レポジトリの追加
# apt-get update                            // 
# apt-get install ruby2.2                   // ruby(バージョン)のインストール

手順2.作ったファイルでライブラリのファイルを置き換える

これで作ったファイルを実際のmsgpackファイルと置き換える

  • 以下のファイルをつくったファイルと置き換える
    • /usr/local/include/msgpack/v1/adaptor/detail

これで実行すると、拡張版を使って33以上の項目もMSGPACK_DEFINEできる

[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ cat msgpack_define_expand33.cpp
#include <msgpack.hpp>
#include <vector>
#include <string>
#include <iostream>

class myclass {
public:
    std::string var[33];

    MSGPACK_DEFINE(
    var[0], var[1], var[2], var[3], var[4], var[5], var[6], var[7], var[8], var[9], var[10], var[11], var[12], var[13], var[14], var[15], var[16], var[17], var[18], var[19], var[20], var[21], var[22], var[23], var[24], var[25], var[26], var[27], var[28], var[29], var[30], var[31], var[32]);
    myclass() {
        var[0] = "0";
        var[1] = "1";
        var[2] = "2";
        var[3] = "3";
        var[4] = "4";
        var[5] = "5";
        var[6] = "6";
        var[7] = "7";
        var[8] = "8";
        var[9] = "9";
        var[10] = "10";
        var[11] = "11";
        var[12] = "12";
        var[13] = "13";
        var[14] = "14";
        var[15] = "15";
        var[16] = "16";
        var[17] = "17";
        var[18] = "18";
        var[19] = "19";
        var[20] = "20";
        var[21] = "21";
        var[22] = "22";
        var[23] = "23";
        var[24] = "24";
        var[25] = "25";
        var[26] = "26";
        var[27] = "27";
        var[28] = "28";
        var[29] = "29";
        var[30] = "30";
        var[31] = "31";
        var[32] = "32";
}
};

int main(void) {
        std::vector<myclass> vec;
        // add some elements into vec...
        vec.push_back(myclass());

        // you can serialize myclass directly
        msgpack::sbuffer sbuf;
        msgpack::pack(sbuf, vec);

        msgpack::object_handle oh =
            msgpack::unpack(sbuf.data(), sbuf.size());

        msgpack::object obj = oh.get();

        // you can convert object to myclass directly
        std::vector<myclass> rvec;
        obj.convert(rvec);

        for(std::vector<myclass>::iterator it = rvec.begin(); it != rvec.end(); ++it) {

            for(int i = 0; i < 33; i++) {
                std::cout << (*it).var[i] << std::endl;
            }
        }
}
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ 

コンパイルと実行

[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ g++ -Ipath_to_msgpack/include msgpack_define_expand33.cpp
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ ./a.out 
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32  ← 33個目が使えている!
[~/git/work/src/cpp/msgpack/my_sample/msgpack_define_expand] $ 

c++のメモ

概要

c++についての自分用のメモ書き

g++

g++ がサポートしている規格

$ g++ --version
g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 $  g++ -v --help 2>/dev/null | grep -E "^\s+\-std=.*$"
  -std=<standard>          Assume that the input sources are for <standard>
  -std=f2003                  Conform to the ISO Fortran 2003 standard
  -std=f2008                  Conform to the ISO Fortran 2008 standard
  -std=f2008ts                Conform to the ISO Fortran 2008 standard
  -std=f95                    Conform to the ISO Fortran 95 standard
  -std=gnu                    Conform to nothing in particular
  -std=legacy                 Accept extensions to support legacy code
  -std=c++03                  Conform to the ISO 1998 C++ standard revised by
  -std=c++0x                  Deprecated in favor of -std=c++11
  -std=c++11                  Conform to the ISO 2011 C++ standard
  -std=c++1y                  Conform to the ISO 201y(7?) C++ draft standard
  -std=c++98                  Conform to the ISO 1998 C++ standard revised by
  -std=c11                    Conform to the ISO 2011 C standard (experimental
  -std=c1x                    Deprecated in favor of -std=c11
  -std=c89                    Conform to the ISO 1990 C standard
  -std=c90                    Conform to the ISO 1990 C standard
  -std=c99                    Conform to the ISO 1999 C standard
  -std=c9x                    Deprecated in favor of -std=c99
  -std=gnu++03                Conform to the ISO 1998 C++ standard revised by
  -std=gnu++0x                Deprecated in favor of -std=gnu++11
  -std=gnu++11                Conform to the ISO 2011 C++ standard with GNU
  -std=gnu++1y                Conform to the ISO 201y(7?) C++ draft standard
  -std=gnu++98                Conform to the ISO 1998 C++ standard revised by
  -std=gnu11                  Conform to the ISO 2011 C standard with GNU
  -std=gnu1x                  Deprecated in favor of -std=gnu11
  -std=gnu89                  Conform to the ISO 1990 C standard with GNU
  -std=gnu90                  Conform to the ISO 1990 C standard with GNU
  -std=gnu99                  Conform to the ISO 1999 C standard with GNU
  -std=gnu9x                  Deprecated in favor of -std=gnu99
  -std=iso9899:1990           Conform to the ISO 1990 C standard
  -std=iso9899:199409         Conform to the ISO 1990 C standard as amended in
  -std=iso9899:1999           Conform to the ISO 1999 C standard
  -std=iso9899:199x           Deprecated in favor of -std=iso9899:1999
  -std=iso9899:2011           Conform to the ISO 2011 C standard (experimental

引数

引数を2倍して出力する

参考 - C++で文字列を数値に変換する方法 - C++と色々 - http://www7b.biglobe.ne.jp/~robe/cpphtml/html03/cpp03042.html

https://github.com/ludwig125/work/blob/master/src/cpp/test/argv.cpp

#include <iostream>
#include <stdlib.h>
using namespace std;

int main(int argc, char** argv)
{
    for(int i = 1; i < argc; i++){
        cout << "argv "<< i << " : " << argv[i] << endl;
        cout << "double argv: " << atoi(argv[i])*2 << endl;
    }
    return 0;
}

実行結果

$ g++ argv.cpp 
[~/git/work/src/cpp/test ] $ ./a.out 13 83
argv 1 : 13
double argv: 26
argv 2 : 83
double argv: 166

型変換

型を確認

#include <iostream>                                                     
#include <stdlib.h>
#include <typeinfo>
using namespace std;

int main(int argc, char** argv)
{
    int a,b;
    for(int i = 1; i < argc; i++){
        cout << "argv "<< i << " : " << argv[i] << endl;
    }

  // 引数の型
    cout << typeid(argv[1]).name() << " : " << argv[1] << endl;

    a = atoi(argv[1]);
    b = atoi(argv[2]);

    // 変換後の型
    cout << typeid(a).name() << " : " << a << endl;

    return 0;
}

実行結果

$ ./a.out 10 30
argv 1 : 10
argv 2 : 30
Pc : 10
i : 10

typeidの出力

Uses of typeid in C++ - Codeforces

bool = b
char = c
unsigned char = h
short = s
unsigned short = t
int = i
unsigned int = j
long = l
unsigned long = m
long long = x
unsigned long long = y
float = f
double = d
long double = e
string = Ss
int[] = A_i
double[] = A_d
vector<int> = St6vectorIiSaIiE

c++のstringへの変換について

to_stringが使えない

あまり考えずにto_stringを使おうとしたら、以下のコンパイルエラーが出た

error: ‘to_string’ is not a member of ‘std’

c++11にするとか、コンパイル時の指定が必要とか書いてある c++ - "to_string" isn't a member of "std"? - Stack Overflow

面倒なので他の方法を探してみる

stringstreamを使う

stringstreamを使った方法が見つかった

参考 - [O] C++ で int 型の値を string 型にするときは stringstream - 文字列⇔数値 - code snippets - C++11で数字→文字列はstd::to_string()、文字列→数字はstd::stoi()とかstd::stod()とか - minus9d's diary

やってみる

超適当なコード

$ cat stringToint.cpp 
#include <iostream>
#include <string>

#include <sstream>

int main(void) {
    int   a = 3;
    float b = 3.14;
    double c = 2.99792458;
    std::string d= "this is test";

    std::string str;
    std::stringstream ss;    

    ss << a;
    str = ss.str();
    std::cout << str << std::endl;

    ss.str("");
    ss << b;
    str = ss.str();
    std::cout << str << std::endl;

    ss.str("");
    ss << c;
    str = ss.str();
    std::cout << str << std::endl;

    ss.str("");
    ss << d;
    str = ss.str();
    std::cout << str << std::endl;
}

実行結果

$ g++ stringToint.cpp
$ ./a.out 
3
3.14
2.99792
this is test

vector

vectorのソート

参考: - http://blog.sarabande.jp/post/62062199465 - http://kaworu.jpn.org/cpp/std::sort

https://github.com/ludwig125/work/blob/master/src/cpp/test/sort_vector.cpp

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

int main()
{
                                                                               
    vector<int> v;
    v.push_back ( 3 );
    v.push_back ( 4 );
    v.push_back ( 1 );
    v.push_back ( 2 );

    std::sort(v.begin(), v.end(), std::greater<int>() );
    for(vector<int>::iterator it = v.begin(); it != v.end(); it++){
        cout << *it << endl;
    }

    return 0;
}

実行結果

[~/git/work/src/cpp/test ] $ ./a.out 
4
3
2
1
[~/git/work/src/cpp/test ] $

文字列を受け取って1文字ずつvectorに格納

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main()
{
    string str;
    getline(cin,str);

    string tmp;
    // 'abcde'のような文字列を一文字ずつvectorに格納
    vector<string> v;
    for(int i = 0; i < (int)str.size(); i++){
        char ch = str[i];
        cout << ch << " " << endl;

//        v.push_back(string(ch));
        // 直接charをvectorに格納しようとしたらコンパイルエラーになったのでstringの変数に入れた
        tmp = ch;
        v.push_back(tmp);
    }

    cout << "output vector" << endl;
    for(vector<string>::iterator it = v.begin(); it != v.end(); it++){
        cout << *it << endl;
    }

    return 0;
}

Linuxのメモリについて

とりあえず参考になったリンクを貼っておく あとでまとめる

いまさら聞けないLinuxとメモリの基礎&vmstatの詳しい使い方 - Qiita

Linuxのバッファキャッシュとページキャッシュの違いは? | b.l0g.jp

freeコマンドで確認するOSのメモリ情報 - Shoyan blog