[C言語]配列のアドレス

#include 

int main(void){
	char c[128] = "1234ABCDあいうえ";
	int i;

	printf("char型変数の値\n");
	printf("cの値:%s\n",c);
	printf("cのアドレス:%X\n",c);

	printf("配列要素c[i]の値とアドレス(16進数)\n");
	for(i=0; i<16; i++){
		printf("c[%2d]:値=%X アドレス=%X\n", i, c[i],&c[i]);
	}


	return 0;
}

$ ./main
char型変数の値
cの値:1234ABCDあいうえ
cのアドレス:E16367D0
配列要素c[i]の値とアドレス(16進数)
c[ 0]:値=31 アドレス=E16367D0
c[ 1]:値=32 アドレス=E16367D1
c[ 2]:値=33 アドレス=E16367D2
c[ 3]:値=34 アドレス=E16367D3
c[ 4]:値=41 アドレス=E16367D4
c[ 5]:値=42 アドレス=E16367D5
c[ 6]:値=43 アドレス=E16367D6
c[ 7]:値=44 アドレス=E16367D7
c[ 8]:値=FFFFFFE3 アドレス=E16367D8
c[ 9]:値=FFFFFF81 アドレス=E16367D9
c[10]:値=FFFFFF82 アドレス=E16367DA
c[11]:値=FFFFFFE3 アドレス=E16367DB
c[12]:値=FFFFFF81 アドレス=E16367DC
c[13]:値=FFFFFF84 アドレス=E16367DD
c[14]:値=FFFFFFE3 アドレス=E16367DE
c[15]:値=FFFFFF81 アドレス=E16367DF

メモリのアドレスは順番に入っていることがわかります。

[C言語]変数のアドレス

#include <stdio.h>

int main(void){
	int a=127;

	printf("int型変数の値\n");
	printf("10進数表示:%d\n",a);
	printf("16進数表示:%X\n",a);

	printf("int型変数のアドレス\n");
	printf("10進数表示:%d\n",&a);
	printf("1t進数表示:%X\n",&a);


	return 0;
}

$ ./main
int型変数の値
10進数表示:127
16進数表示:7F
int型変数のアドレス
10進数表示:489720900
1t進数表示:1D308C44

ポインタのアドレスは&、値参照は*
何度も繰り返さないと忘れる

[C言語]論理式(0 | 1)

#include <stdio.h>
#include <stdlib.h>

int main(void){
	char c[128];
	int a,b,m;

	printf("\n数字を二回入力して論理式を調べます\n");
	printf("aに好きな数字を入力してください。\n");
	printf("a=\n");gets(c);a=atoi(c);
	printf("bに好きな数字を入力してください。\n");
	printf("b=\n");gets(c);b=atoi(c);

	printf("\n aの値は%d, bの値は%d\n\n", a,b);

	m=(a==b);
	printf("論理式 a==b の値は%d\n",m);
	m=(a<b);
	printf("論理式 a<b の値は%d\n",m);
	m=(a>b);
	printf("論理式 a>b の値は%d\n",m);

	

$ ./main

数字を二回入力して論理式を調べます
aに好きな数字を入力してください。
a=
6
bに好きな数字を入力してください。
b=
2

aの値は6, bの値は2

論理式 a==b の値は0
論理式 ab の値は1

m=(a==b)と書いて、正の場合は1, 正しくない場合は0を表示する
true or falseに慣れていると、奇妙な感じがします。

[C言語]Shift_JIS

Shift_JISは日本語を含む文字列を表現するために用いられる文字コードの一つ
linuxにgetcheは無いののでgetcharを使う

#include <stdio.h>

int main(void){
	char c1, c2;

	c1 = getchar();
	c2 = getchar();
	
	printf("shift jis code:%02X%02X\n",c1, c2);

	return 0;
}

$ ./main
23
shift jis code:3233

ふむ、文字コードはC言語でなくても考えることなので、特に問題なし

[C言語]早打ちゲーム

時間計測にはclock()を使う

#include <stdio.h>
#include <time.h>

int main(void){
	
	clock_t start, end;

	start = clock();

	end = clock();
	printf("%f秒かかりました。\n", (double)(end-start)/CLOCKS_PER_SEC);

	return 0;
}

$ ./main
0.000002秒かかりました。

#include <stdio.h>
#include <time.h>

int main(void){
	int i;
	clock_t start, end;
	start = clock();
	printf("人口当たりの大根消費量ランキング1位はどこでしょう?\n1.岩手県, 2.千葉県, 3.群馬県\n");

	scanf("%d", &i);
	end = clock();

	if(i == 1){
		printf("正解です。%f秒かかりました。\n", (double)(end-start)/CLOCKS_PER_SEC);

	} else {
		printf("%f秒かかりました。入力内容が正しくありません。\n", (double)(end-start)/CLOCKS_PER_SEC);
	}
	
	return 0;
}

$ ./main
人口当たりの大根消費量ランキング1位はどこでしょう?
1.岩手県, 2.千葉県, 3.群馬県
1
正解です。0.000137秒かかりました。

なんかちゃうなぁ

[C言語]日時と時間

struct tmの構造体
struct tm {
int tm_sec; /* 秒 (0-60) */
int tm_min; /* 分 (0-59) */
int tm_hour; /* 時間 (0-23) */
int tm_mday; /* 月内の日付 (1-31) */
int tm_mon; /* 月 (0-11) */
int tm_year; /* 年 – 1900 */
int tm_wday; /* 曜日 (0-6, 日曜 = 0) */
int tm_yday; /* 年内通算日 (0-365, 1 月 1 日 = 0) */
int tm_isdst; /* 夏時間 */
};

#include <stdio.h>
#include <time.h>

int main(void){
	static char *week[] = {"日","月","火","水","木","金","土"};
	time_t now;
	struct tm
		*tm_now;

	now = time(NULL);
	tm_now = localtime(&now);
	printf("%4d年%2d月%2d日 %s曜日\n", tm_now->tm_year + 1900, tm_now->tm_mon+1, tm_now->tm_mday, week[tm_now->tm_wday]);
	printf("%2d時%2d分%2d秒\n", tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec);

	return 0;
}

$ ./main
2020年 5月31日 日曜日
4時45分40秒

あれ、9時間+する方法がわからん。

時計

int main(void){
	static char *week[] = {"日","月","火","水","木","金","土"};
	time_t now, prev;
	struct tm
		*tm_now;

	prev = -1;
	for(;;){
		now = time(NULL);
		if(prev == now)
			continue;
		prev = now;
		tm_now = localtime(&now);
		printf("%2d時%2d分%2d秒\n", tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec);
	}

	return 0;
}

[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;
}