[C言語]Unicode

Unicodeとは、符号化文字集合や文字符号化方式などを定めた文字コードの業界規格
gccのデフォルトはutf-8
c言語で文字列を扱うにはマルチバイトセットとUnicodeがある

#include <stdio.h>

int main(void){
	char str[] = "あいうえお順";
	printf("%s\n", str);

	return 0;
}

$ ./main
あいうえお順
-> 日本語で出力されます

char str[] = "\u3042\u3044\u3046";

$ ./main
あいう

C言語では、wchar_t型がワイド文字型と呼ばれ、Unicode文字を表現する際に使われる
文字を「L”」で囲むと、その文字を表現するワイド文字型の数値となる
wchar_t 型を使用する際には、ロケール(地域)を設定する必要がある
mac OSやLinuxでは、ワイド文字型は通常は32ビット

#include <stdio.h>
#include <wchar.h> //linuxでwcharを使うのに必要
#include <locale.h>

int main(void){
	wchar_t wc = L'a';
	setlocale(LC_ALL,"ja_JP.UTF-8");;
	wprintf(L"変数wcに格納された文字は%c\n", wc);
	wprintf(L"変数wcに格納された文字は%4x\n", wc);

	return 0;
}

$ ./main
??wc?????????a
??wc????????? 61

あれ、wprintfだと文字化けするな。何故だ。

[C言語]文字型のオーバーフロー

#include 

int main(void){
	signed char c1 = '\0';
	unsigned char c2 = '\0';
	int i;

	printf("*** signed char ***\n");
	for(i = 0; i < 256; i++){
		printf("%4d", c1);
		c1++;
	}

	printf("\n\n*** unsigned char ***\n");
	for(i = 0; i < 256; i++){
		printf("%4d", c2);
		c2++;
	}

	return 0;
}

$ ./main
*** signed char ***
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127-128-127-126-125-124-123-122-121-120-119-118-117-116-115-114-113-112-111-110-109-108-107-106-105-104-103-102-101-100 -99 -98 -97 -96 -95 -94 -93 -92 -91 -90 -89 -88 -87 -86 -85 -84 -83 -82 -81 -80 -79 -78 -77 -76 -75 -74 -73 -72 -71 -70 -69 -68 -67 -66 -65 -64 -63 -62 -61 -60 -59 -58 -57 -56 -55 -54 -53 -52 -51 -50 -49 -48 -47 -46 -45 -44 -43 -42 -41 -40 -39 -38 -37 -36 -35 -34 -33 -32 -31 -30 -29 -28 -27 -26 -25 -24 -23 -22 -21 -20 -19 -18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1

*** unsigned char ***
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255

[C言語]整数のオーバーフロー

– 大きな数値同士の掛け算ではオーバーフローしやすい
– 表現可能なのは2147483647まで
– 最大値に1を足した場合もオーバーフローになる

#include <stdio.h>
#include <limits.h>

int main(void){
	int a = INT_MIN; // -2147483648
	int b = -1;

	int answer = a * b;
	printf("%d\n", answer);

	return 0;
}

$ ./main
-2147483648

int answer = a / b;としても同様
$ ./main
Floating point exception (core dumped)

[C言語]分子動力学シミュレーション

原子・分子の動きをコンピュータの中で再現するために使われるのが分子動力学シミュレーション
原子の最初の配置を決め、1個の原子に他の原子から及ぶ力を計算する(ニュートンの運動方程式)

### シミュレーションの流れ
開始 -> 初期条件の設定 -> 位置の更新/速度の更新 -> 力の計算 -> 温度、圧力などの計算 -> 終了
※メインループを数万回〜数百万回実行することで、 数十(ps)〜数(ns)のシミュレーションを実行する

#include 

int main(void){
	int i, j, k;
	int step, total_step;
	double side = 9;
	double cd[N*3],vl[N*3];

	cd[0] = 4.5;cd[1]= 3.0; cd[2] = 3.0;
	cd[3] = 4.5;cd[4]= 3.0; cd[5] = 6.0;
	cd[6] = 4.5;cd[7]= 6.0; cd[8] = 3.0;
	cd[9] = 4.5;cd[10]= 6.0; cd[11] = 6.0;
	srand(1);
	for(i=0; i < N*3;i++){
		vl[i] = ((double)rand()/RAND_MAX-0.5)*.1;
	}
	total_step = 100;
	for(step = 1; step <= total_step; step++){
		for(i=0; i < N*3; i++){
			cd[i] += vl[i]*dt;
		}
		output_file(cd, side);
	}

	return 0;
}

[C言語]選択ソート

最小値を見つけて先頭に移動、2番目に小さい要素を見つけて2番目に移動 を繰り返していくアルゴリズム

#include 

void swap (int *x, int *y){
	int temp;

	temp = *x;
	*x = *y;
	*y = temp;
}

void select_sort(int array[], int array_size){
	int i, j, min_index;

	for(i = 0; i < array_size -1; i++){
		min_index = i;
		for (j = i + 1; j < array_size; j++){
			if(array[j] < array[min_index]) {min_index = j;}
		}
		swap(&array[min_index], &array[i]);
	}
}


int main(void){
	int array[10] = {3, 4, 1, 5, 6, 2, 8, 7, 9, 0};
	int i;

	select_sort(array, 10);
	for(i = 0; i<10; i++){
		printf("%d ", array[i]);
	}
	printf("\n");
	

	return 0;
}

$ ./main
0 1 2 3 4 5 6 7 8 9

左右の比較ではなくて、先頭との比較 swap(&array[min_index], &array[i])ってところがなるほどなーって思う

[C言語]円周率

円周率の計算方法

### マチンの公式
π/4 = 4Arctan*1/5 – Arctan*1/239
これをコーディングすると

#include <stdio.h>
#include <math.h>

int main(void){

	double pi;

	pi = (4 * atan(1/5) - atan(1/239)) / 4;

	printf("%lf\n", pi);


	return 0;
}

$ ./main
0.000000
あれ?? 何故?

### 22/7、355/113、428224593349304/136308121570117

#include <stdio.h>
#include <math.h>

int main(void){

	double pi1, pi2, pi3;
	pi1 = 22.0/7.0;
	pi2 = 355.0/113.0;
	pi3 = 428224593349304.0/136308121570117.0;

	printf("%lf\n", pi1);
	printf("%lf\n", pi2);
	printf("%lf\n", pi3);


	return 0;
}

$ ./main
3.142857
3.141593
3.141593

22/7で計算すると、int型で3.000000になってしまう

### モンテカルロ法

#include 
#include 
#include 

int main(void){

	int j, jmax = 100000000;
	int Ni;
	double x,y,max,pi;

	max = (double)RAND_MAX;
	srand(time(NULL));

	for(j=0, Ni=0; j

$ ./main
3.141687

円周率、侮ってた、奥が深い

[C言語]経路探索

バックトラック: 失敗したら後戻りして別の道を選ぶ -> メモリ使用量が少ない
幅優先探索: 全ての経路を並行して探索 -> メモリ使用量が多い

隣接行列
N|ABCDEFG
A|0110000
B|1011000
C|1100100
D|0100110
E|0011001
F|0001000
G|0000100

int adjacent[N][N] {
	{0, 1, 1, 0, 0, 0, 0},
	{1, 0, 1, 1, 0, 0, 0},
	{1, 1, 0, 0, 1, 0, 0},
	{0, 1, 0, 0, 1, 1, 0},
	{0, 0, 1, 1, 0, 0, 1},
	{0, 0, 0, 1, 0, 0, 0},
	{0, 0, 0, 0, 1, 0, 0},
}

隣接リスト

enum {S, A, B, C, D, E, F, G};

int adjacent[N + 1][M] = {
	{S},
	{B, C, S},
	{A, C, D, S},
	{A, B, E, S},
	{B, E, F, S},
	{C, D, G, S},
	{D, S},
	{E, S},
};

### プログラム

#include 
#include  //  4 つのマクロが定義 bool, true, false, __bool_true_false_are_defined

#define N 7
#define M 4

enum {S, A, B, C, D, E, F, G};

int adjacent[N + 1][M] = {
	{S},
	{B, C, S},
	{A, C, D, S},
	{A, B, E, S},
	{B, E, F, S},
	{C, D, G, S},
	{D, S},
	{E, S},
};


// 経路
int path[N];
bool visited[N + 1];

// 経路の表示
void print_path(int n){
	for(int i = 0; i

$ ./main
A B C E G
A B D E G
A C B D E G
A C E G

関数のdfsのint y = adjacent[x][i];で進んでいってるってこと?
A->B->C の順番の経路だから上のロジックでも成り立っているように見えるが。。。
それとvisitedの書き方がtrue -> 再帰処理 -> falseにする意味がよくわからん

[C言語]クリップボード

クリップボードの動き
——-
1.OpenClipboard()  // 開く
2.EmptyClipboard() // 現在の確保メモリを開放
3.GlobalAlloc()、GlobalLock() // 書き込むメモリを確保
4.上記メモリに書き込む
5.GlobalUnlock()   // メモリのロックを解除
6.SetClipboardData() // メモリをクリップボードにセット
7.CloseClipboard() // 閉じる

#include <stdio.h>
#include <string.h> // strlenに使用

int main(void){
	char str[256];
	int len;

	scanf("%s", str);
	len = strlen(str);

	printf("入力した文字列は:%s\n文字数:%d\n", str, len);

	thandl = GlobalAlloc(str, len+1);

	OpenClipboard(NULL);
	EmptyClipboard();

	SetClipboardData(str, thandl);
	CloseClipboard();

	return 0;
}

$ gcc -o main main.c
main.c: In function ‘main’:
main.c:13:2: error: ‘thandl’ undeclared (first use in this function)
thandl = GlobalAlloc(str, len+1);
^~~~~~
main.c:13:2: note: each undeclared identifier is reported only once for each function it appears in
main.c:13:11: warning: implicit declaration of function ‘GlobalAlloc’ [-Wimplicit-function-declaration]
thandl = GlobalAlloc(str, len+1);
^~~~~~~~~~~
main.c:15:2: warning: implicit declaration of function ‘OpenClipboard’ [-Wimplicit-function-declaration]
OpenClipboard(NULL);
^~~~~~~~~~~~~
main.c:16:2: warning: implicit declaration of function ‘EmptyClipboard’ [-Wimplicit-function-declaration]
EmptyClipboard();
^~~~~~~~~~~~~~
main.c:18:2: warning: implicit declaration of function ‘SetClipboardData’ [-Wimplicit-function-declaration]
SetClipboardData(str, thandl);
^~~~~~~~~~~~~~~~
main.c:19:2: warning: implicit declaration of function ‘CloseClipboard’ [-Wimplicit-function-declaration]
CloseClipboard();
^~~~~~~~~~~~~~

windows.hでないと無理か。。
APIがOSによって異なることをあまり理解できていない。

[C言語]あみだくじを作りたい

C言語であみだくじを作りたい

配列0〜8に数字1〜9が入っているとする
(1, 2, 3, 4, 5, 6, 7, 8, 9)

横線が入ると、数字の値が入れ替わる
(2, 3) -> (3, 2)
(8, 9) -> (9, 8)

最終的に
(1, 3, 2, 4, 5, 6, 7, 9, 8)

図で書くとこんな感じか

これをプログラミングで書きたい

1回交換するだけなら

#include 
#include 
#include 

int main(){
	int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
	int i, num1, num2, tmp;

	srand((unsigned int)time(NULL));
	num1 = rand() % 9;
	if(num1 == 8){
		num1 = 7;
	}
	num2 = num1 + 1;

	tmp = a[num1];
	a[num1] = a[num2];
	a[num2] = tmp;
	
	
	for(i=0; i<9; i++){
		printf("%d ",a[i]);
	}
	printf("\n");

	return 0;
}

$ gcc -o main main.c
$ ./main
0 1 2 4 3 5 6 7 8
$ ./main
0 1 2 3 5 4 6 7 8

これを複数回変更したい

#include 
#include 
#include 

int main(){
	static int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
	int i, j, num1, num2, tmp;
	srand((unsigned int)time(NULL));

	for(i=0; i<3; i++){
		num1 = rand() % 9;
		if(num1 == 8){
			num1 = 7;
		}
		num2 = num1 + 1;
		printf("%d回目に変更したのは%d番目と%d番目\n", i+1, num1+1, num2+1);

		tmp = a[num1];
		a[num1] = a[num2];
		a[num2] = tmp;
	}
		
	for(j=0; j<9; j++){
		printf("%d ",a[j]);
	}
	printf("\n");

	return 0;
}

$ ./main
1回目に変更したのは3番目と4番目
2回目に変更したのは4番目と5番目
3回目に変更したのは8番目と9番目
0 1 3 4 2 5 6 8 7
$ ./main
1回目に変更したのは7番目と8番目
2回目に変更したのは6番目と7番目
3回目に変更したのは5番目と6番目
0 1 2 3 7 4 5 6 8

いいねー、3時間ぐらいかかったけど

[C言語]MIDI

MIDIとはMusical Instrument Digital Interface, 電子機器の演奏データを機器間で転送・共有するための共通規格


ん? なんだこれは?

#include 
#include 

typedef struct {   // typedefはtype definition 構造体
	char type[4];
	int size; // トラックチャンクデータのサイズ[4byte]
	char *data;
} TrackChunk;

short mergeChar7bit(char x, char y){
	short s;
	s = (unsigned char)x;
	s <<= 7;
	s = (s |(unsigned char)(y & 0x7f));
	return s;
}

int convertEndian(void *input, size_t s){
	int i;
	char *temp;

	if((temp = (char *)calloc(s, sizeof(char))) == NULL){
		perror("Error: Cannot get money for temp.");
		return 0;
	}

	for(i=0; i

$ gcc -o main main.c
main.c: In function ‘main’:
main.c:64:3: warning: implicit declaration of function ‘eperror’; did you mean ‘perror’? [-Wimplicit-function-declaration]
eperror("Error:Cannot open the file.");
^~~~~~~
perror
main.c:147:5: error: ‘jLL’ undeclared (first use in this function); did you mean ‘NULL’?
jLL;
^~~
NULL
main.c:147:5: note: each undeclared identifier is reported only once for each function it appears in
main.c:317:13: warning: too many arguments for format [-Wformat-extra-args]
printf(")=%d",c,(unsigned char)track_chunks[i].data[j]);
^~~~~~
main.c:319:12: warning: zero-length gnu_printf format string [-Wformat-zero-length]
printf("");
^~
main.c:334:15: error: ‘statu’ undeclared (first use in this function); did you mean ‘status’?
} else if((statu & 0xf0) == 0xf0){
^~~~~
status
main.c:335:5: warning: implicit declaration of function ‘swtich’ [-Wimplicit-function-declaration]
swtich(status & 0x0f){
^~~~~~
main.c:335:26: error: expected ‘;’ before ‘{’ token
swtich(status & 0x0f){
^
main.c:573:22: error: invalid suffix "O" on integer constant
switch(cnt & 0xCO){
^~~~
main.c:645:11: warning: zero-length gnu_printf format string [-Wformat-zero-length]
printf("");

..$ gcc -o main main.c
main.c: In function ‘main’:
main.c:64:3: warning: implicit declaration of function ‘eperror’; did you mean ‘perror’? [-Wimplicit-function-declaration]
eperror("Error:Cannot open the file.");
^~~~~~~
perror
main.c:147:5: error: ‘jLL’ undeclared (first use in this function); did you mean ‘NULL’?
jLL;
^~~
NULL
main.c:147:5: note: each undeclared identifier is reported only once for each function it appears in
main.c:317:13: warning: too many arguments for format [-Wformat-extra-args]
printf(")=%d",c,(unsigned char)track_chunks[i].data[j]);
^~~~~~
main.c:319:12: warning: zero-length gnu_printf format string [-Wformat-zero-length]
printf("");
^~
main.c:334:15: error: ‘statu’ undeclared (first use in this function); did you mean ‘status’?
} else if((statu & 0xf0) == 0xf0){
^~~~~
status
main.c:335:5: warning: implicit declaration of function ‘swtich’ [-Wimplicit-function-declaration]
swtich(status & 0x0f){
^~~~~~
main.c:335:26: error: expected ‘;’ before ‘{’ token
swtich(status & 0x0f){
^
main.c:573:22: error: invalid suffix "O" on integer constant
switch(cnt & 0xCO){
^~~~
main.c:645:11: warning: zero-length gnu_printf format string [-Wformat-zero-length]
printf("");