[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

ほうー

[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言語でなくても考えることなので、特に問題なし