[C言語]正接(tangent)

sine, cosine, tangentを日本語で、正弦、余弦、正接という
tanは45°で1, 30°で√3/3

#include 
#include 


int main(void){

	int thd;
	double th;
	FILE *fp = NULL;
	char c[128];

	fp=fopen("tangent.txt", "w");
	if(fp == NULL) return 1;
	fputs("正接表\n\n", fp);

	fputs("角度\t正接\n",fp);
	printf("\n角度\t正接\n");

	for(thd=-89; thd<90; thd+=1){
		th = thd*0.017453295;
		sprintf(c, "%3d\t%10.6f\n",thd, tan(th));
		fputs(c,fp);
		printf("%s",c);
	}
	if(fp!=NULL) fclose(fp);

	return 0;
}

$ gcc -o main main.c
/tmp/cc1hB26c.o: In function `main':
main.c:(.text+0xe1): undefined reference to `tan'

あれ? tanは特にincludeは要らないはずだが。
stackoverflowに買いてありますな。

You should add -lm to your compiler option.
Besides of that, you could also change -lpthread to -pthread.

$ gcc -o main main.c -lm
$ ./main

角度 正接
-89 -57.290686
-88 -28.636432
-87 -19.081215
-86 -14.300710
-85 -11.430080
-84 -9.514384
-83 -8.144360
-82 -7.115380
-81 -6.313760
-80 -5.671288
-79 -5.144559
-78 -4.704635
-77 -4.331480
-76 -4.010784
-75 -3.732054
-74 -3.487417
-73 -3.270855
-72 -3.077685
-71 -2.904213
-70 -2.747479
-69 -2.605090
-68 -2.475088
-67 -2.355853
-66 -2.246038
-65 -2.144508
-64 -2.050305
-63 -1.962611
-62 -1.880727
-61 -1.804048
-60 -1.732051
-59 -1.664280
-58 -1.600335
-57 -1.539865
-56 -1.482561
-55 -1.428148
-54 -1.376382
-53 -1.327045
-52 -1.279942
-51 -1.234897
-50 -1.191754
-49 -1.150369
-48 -1.110613
-47 -1.072369
-46 -1.035531
-45 -1.000000
-44 -0.965689
-43 -0.932515
-42 -0.900404
-41 -0.869287
-40 -0.839100
-39 -0.809784
-38 -0.781286
-37 -0.753554
-36 -0.726543
-35 -0.700208
-34 -0.674509
-33 -0.649408
-32 -0.624869
-31 -0.600861
-30 -0.577350
-29 -0.554309
-28 -0.531710
-27 -0.509526
-26 -0.487733
-25 -0.466308
-24 -0.445229
-23 -0.424475
-22 -0.404026
-21 -0.383864
-20 -0.363970
-19 -0.344328
-18 -0.324920
-17 -0.305731
-16 -0.286745
-15 -0.267949
-14 -0.249328
-13 -0.230868
-12 -0.212557
-11 -0.194380
-10 -0.176327
-9 -0.158384
-8 -0.140541
-7 -0.122785
-6 -0.105104
-5 -0.087489
-4 -0.069927
-3 -0.052408
-2 -0.034921
-1 -0.017455
0 0.000000
1 0.017455
2 0.034921
3 0.052408
4 0.069927
5 0.087489
6 0.105104
7 0.122785
8 0.140541
9 0.158384
10 0.176327
11 0.194380
12 0.212557
13 0.230868
14 0.249328
15 0.267949
16 0.286745
17 0.305731
18 0.324920
19 0.344328
20 0.363970
21 0.383864
22 0.404026
23 0.424475
24 0.445229
25 0.466308
26 0.487733
27 0.509526
28 0.531710
29 0.554309
30 0.577350
31 0.600861
32 0.624869
33 0.649408
34 0.674509
35 0.700208
36 0.726543
37 0.753554
38 0.781286
39 0.809784
40 0.839100
41 0.869287
42 0.900404
43 0.932515
44 0.965689
45 1.000000
46 1.035531
47 1.072369
48 1.110613
49 1.150369
50 1.191754
51 1.234897
52 1.279942
53 1.327045
54 1.376382
55 1.428148
56 1.482561
57 1.539865
58 1.600335
59 1.664280
60 1.732051
61 1.804048
62 1.880727
63 1.962611
64 2.050305
65 2.144508
66 2.246038
67 2.355853
68 2.475088
69 2.605090
70 2.747479
71 2.904213
72 3.077685
73 3.270855
74 3.487417
75 3.732054
76 4.010784
77 4.331480
78 4.704635
79 5.144559
80 5.671288
81 6.313760
82 7.115380
83 8.144360
84 9.514384
85 11.430080
86 14.300710
87 19.081215
88 28.636432
89 57.290686

[C言語]マンデルブロ集合

マンデルブロ集合
充填ジュリア集合に対する指標として提唱された集合

ジュリア集合
複素平面上のある近傍で反復関数が非正規族となる点の集合
ガストン・ジュリアの名による

#include 
#include 

#define C0r -0.743
#define C0i 0.1145
#define VS 0.003

#define NMAX 20000
#define STEP 800.0

double mandelbrot(double a, double b){
	double x = 0.0;
	double y = 0.0;
	double x1, y1;

	int n;

	for(n = 1; n <= NMAX; n++){
		x1 = x * x - y * y + a;
		y1 = 2.0 * x * y + b;
		if(x1 * x1 + y1 * y1 > 4.0) return log(n);
		x = x1;
		y = y1;
	}
	return 0;
}


int main(void){

	double a, b;

	for(a = C0r-VS; a < C0r+VS; a += 2.0*VS/STEP){
		for(b = C0i - VS; b < C0i+VS; b += 2.0*VS/STEP){
			printf("%1.14e %1.14e %1.14e\n", a, b, mandelbrot(a, b));
		}
		printf("\n");
	}
	return 0;
}

[C言語]2の冪乗

#include

int main(void){
int i, n;
int k = 1;

printf(“2を何乗しますか? ->”);
scanf(“%d”, &n);

for(i=0; i3
計算結果: 8
$ ./main
2を何乗しますか? ->4
計算結果: 16

そのまんまか

[C言語]2進数変換

– 整数iを2で割った値を配列に入れていく

#include <stdio.h>

int main(void){
	int n, i, a[32];

	printf("数を入力してください->");
	scanf("%d", &n);
	for(i=0; n>0; i++){
		a[i] = n % 2;
		n = n / 2;
	}
	while(i > 0) printf("%1d",a[--i]);
	printf("\n");

	return 0;
}

$ ./main
数を入力してください->15
1111

$ ./main
数を入力してください->6
110

変数の先頭に–演算子を書くのを前置形式という
前に置く場合は、まずiの値を減らしてから表示する

あれ、何でこれで上手く表示できるんだ??

[C言語]関数電卓

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

#define PI 3.14159265

int main(void){
	char c[128],fnc[128];
	double x=0,y,z=0;
	double rd=PI/180.0;

	printf("関数電卓\n");
	printf("sin X, cos X, tan X\n");
	printf("exp X, log X, ln X\n");
	printf("sqr X, X ^ Y\n");

	printf("数値 X:");
	gets(c); x=atof(c);
	printf("関数:");
	gets(fnc);
	if(strcmp(fnc,"^")==0){   // strcmpは文字列の比較
		printf("数値 Y:");
		gets(c); y=atof(c);
	}  
	if(strcmp(fnc,"sin")==0)
		{z=sin(x*rd);}
	else if(strcmp(fnc,"cos")==0)
		{z=cos(x*rd);}
	else if(strcmp(fnc,"tan")==0)
		{z=tan(x*rd);}
	else if(strcmp(fnc,"exp")==0)  // exp(x)とは自然対数の底eのx乗, 微分しても値が変わらない
		{z=exp(x);}
	else if(strcmp(fnc,"log")==0) // 底が10である対数
		{z=log10(x);}
	else if(strcmp(fnc,"ln")==0)  // 底がeである対数
		{z=log(x);}
	else if(strcmp(fnc,"sqr")==0)  // x の y 乗の値
		{z=sqrt(x);}
	else if(strcmp(fnc,"pow")==0)
		{z=pow(x,y);}
	else
		{printf("関数がありません。\n");}
	
	printf("答え:%4.8f\n\n",z);

	return 0;
}

v$ gcc -o main main.c
main.c: In function ‘main’:
main.c:19:2: warning: implicit declaration of function ‘gets’; did you mean ‘fgets’? [-Wimplicit-function-declaration]
gets(c); x=atof(c);
^~~~
fgets
/tmp/ccbBDDqy.o: In function `main’:
main.c:(.text+0x93): warning: the `gets’ function is dangerous and should not be used.
main.c:(.text+0x15c): undefined reference to `sin’
main.c:(.text+0x19c): undefined reference to `cos’
main.c:(.text+0x1dc): undefined reference to `tan’
main.c:(.text+0x222): undefined reference to `exp’
main.c:(.text+0x268): undefined reference to `log10′
main.c:(.text+0x2ae): undefined reference to `log’
main.c:(.text+0x2f4): undefined reference to `sqrt’
main.c:(.text+0x343): undefined reference to `pow’
collect2: error: ld returned 1 exit status
あれ??

[C言語]素因数分解

素因数分解とは自然数を素数の掛け算で表すこと
素因数分解の対象は自然数であること(0を除く)
素数とは、1とその数以外に約数を持たないこと

### 素因数分解のやり方?
対象の自然数をNとする
1. Nを2で割る
-> 2で割り切れた場合: 割り切れた値を更に2で割る
-> 2で割り切れない場合: 下に行く

2.3で割る(※2+1)
-> 3で割り切れた場合: 割り切れた値を更に3で割る
-> 3で割り切れない場合: 下に行く

3.5で割る(※2+2)
-> 5で割り切れた場合: 割り切れた値を更に5で割る
-> 5で割り切れない場合: 7 下に行く

2から始めて、これをN回繰り返す であってる??
割る数は2から3へは+1だが、3以降は+2の方が無駄な計算がなくなる
プログラムで書きたい

#include 

int main(void){
	int prime = 27; // 素因数
	int assemble[prime]; // 割り切れる数
	int i, j, k;

	j = 0;
	for(i=2; i < prime; i++){
		while(prime % i == 0){
			prime = prime / i;
			assemble[j] = i;
			j++;
		}
	}

	for(k=0; k < j; k++){
		printf("%d ", assemble[k]);
	}
	printf("\n");

	return 0;
}

素因数が27の時
$ ./main
3 3 3
上手くいってる。

素因数が21の時
$ ./main
3

あれ、何でだ。。
あ、forループでprimeが割られた数を代入するからおかしくなるんだ。
forループの変数を変えて再度計算します。

#include 

int main(void){
	int prime = 60; // 素因数
	int cal = 60;
	int assemble[prime]; // 割り切れる数
	int i, j, k;

	j = 0;
	for(i=2; i < cal; i++){
		while(prime % i == 0){
			prime = prime / i;
			assemble[j] = i;
			j++;
		}
	}

	for(k=0; k < j; k++){
		printf("%d ", assemble[k]);
	}
	printf("\n");

	return 0;
}

素因数が60の時
$ ./main
2 2 3 5

素因数が115の時
$ ./main
5 23

わお、中々素晴らしい。
forループの時に、最初だけi++として、2回目以降をi+2とするにはどう書けばいいんだろう。
1回目の割り算を切り離して書いて、2回目以降をforループで書くのだろうか。

[C言語]CSVから郵便番号読み取り

– ユーザが郵便番号7桁を入力すると市区町村を返したい
– 郵便番号のデータは郵便局のHPで配布している
zipcode
– 全国一括データは12万件ある
-> 今回は東京都のデータを使用する
– データの中身を見ると、C列が郵便番号、G列が東京都、H列が区/市、I列が町村となっている。

まずExcelのデータ読み取りからか? ubuntuに”13TOKYO.CSV”を配置する。

#include <stdio.h>
#include <string.h> // strtokに必要
#include <stdlib.h>
#define MAX 2048

int main(void){
	FILE *fp;
	char buf[2048] = {0};
	char *ary[3];
	char fname[] = "13TOKYO.CSV";
	int i;
	
	if((fp=fopen(fname,"r"))!=NULL){
		i = 0;
		while(fgets(buf, 2048, fp) != NULL){
			ary[0] = strtok(buf,",");  // ','を区切りに分解する
			ary[1] = strtok(NULL,",");
			ary[2] = strtok(NULL,",");
			printf("%s %s %s\n", ary[0],ary[1],ary[2]);
			i++;
			if(i > 5){
				break;
			}
		}
	}
	fclose(fp);

	return 0;
}

$ ./main
1000000 ?????s ???c??
1020072 ?????s ???c??
1020082 ?????s ???c??
1010032 ?????s ???c??
1010047 ?????s ???c??
1000011 ?????s ???c??

文字化けする
gccを変えてみたがダメ
$ gcc -o main main.c -finput-charset=UTF-8 -fexec-charset=CP932

csvをUTF-8の文字コードで保存してみる。

$ ./main
1000000 東京都 千代田区
1020072 東京都 千代田区
1020082 東京都 千代田区
1010032 東京都 千代田区
1010047 東京都 千代田区
1000011 東京都 千代田区

来た!
CSVはstrtokでカンマ区切りで取得すればOKとのことです。

[C言語]インチ計算

1inchは2.54cm
ということは1cm = 0.393701 inch

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

int main(void){
	int cm;
	double inch;

	printf("cmを入力してください。\n"); fflush(stdout); 
	scanf("%d", &cm);

	inch = cm * 0.393701;

	printf("%dcmは%.3finch\n", cm, inch);

	return 0;
}

$ ./main
cmを入力してください。
14
14cmは5.512inch

きゃーーーー
あ、0.393701で掛けるよりも、2.54で割る方が一般的のようです。

[C言語]分計算

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

int main(void){
	char c[128];
	int m,h,m2;

	printf("時間: \n"); fflush(stdout); // stream が指すストリームにおいて,まだ書き込まれていないデータを書き込み
	gets(c); h=atoi(c);

	printf("分: \n"); fflush(stdout);
	gets(c); m=atoi(c);

	m2 = h*60 + m;

	printf("%d時間%d分 -> %d分: \n", h, m, m2);

	return 0;
}

$ ./main
時間:
4
分:
25
4時間25分 -> 265分

[C言語]ホスト名

#include <stdio.h>

int main(void){
	char cpnm[MAX_COMPUTERNAME_LENGTH+1];
	DWORD len;

	len=MAX_COMPUTERNAME_LENGTH+1;

	GetComputerName(cpnm,&len);
	printf("this computer name is %s\n", cpnm);


	return 0;
}

$ gcc -o main main.c
main.c: In function ‘main’:
main.c:4:12: error: ‘MAX_COMPUTERNAME_LENGTH’ undeclared (first use in this function)
char cpnm[MAX_COMPUTERNAME_LENGTH+1];
^~~~~~~~~~~~~~~~~~~~~~~
main.c:4:12: note: each undeclared identifier is reported only once for each function it appears in
main.c:5:2: error: unknown type name ‘DWORD’
DWORD len;
^~~~~
main.c:9:2: warning: implicit declaration of function ‘GetComputerName’ [-Wimplicit-function-declaration]
GetComputerName(cpnm,&len);
^~~~~~~~~~~~~~~

GetComputerNameではなく、gethostnameか。

#include <stdio.h>
#include <unistd.h> // インプリメンテーション固有関数

int main(void){
	char hostname[128];

	gethostname(hostname, sizeof(hostname));

	printf("host name is %s\n", hostname);

	return 0;
}

$ ./main
host name is ubuntu-bionic

ほうー