NaaN日記

やったこと、覚えたことを発信する場

最大値と最小値を出す(C)

ポインタを使ってみるよ
ポインタを使った式を、もっと短くかけたので、追記。
素敵なことを教えていただいたので追記
与えられた数の中から最も大きいものと小さいものを表示するようにする

入力方式
[一つ目の値, 二つ目の値, 三つ目の値……, 最後の値,, 終了を意味する任意の値]

まずはポインタをできるだけ使わずにやってみる
#include <stdio.h>
int main(void){
	int i = 0;
	int array[10];//値を何個格納するか
	int max = 1;//入力する可能性のある最低値
	int min = 1000;//入力する可能性のある最大値
//この場合、1 ~ 1000の範囲の値を最大9個入力
	
	do{
		scanf("%d", &array[i]);
		printf("%d番:%d\n", i+1,array[i]);
		i++;
	}while(array[i - 1] != 0);//0が入力された時点で終了
	
	for (i = 0; array[i] >= 0; i++){
		if (array[i] == 0){
			break;//0のとき抜ける
		}
		else{
			if (array[i] > max){
				max = array[i];//array[i]の中で一番大きいものをmax
			}
			if (array[i] < min){
				min = array[i];//array[i]の中で一番小さいものをmin
			}
		}
	}
	printf("最小値%d\n", min);
	printf("最大値:%d\n", max);
	return 0;
}
ポインタを使うとこんな感じ
#include <stdio.h>

void calculate(int array[],int*,int*);

int main(void){
	int i = 0;
	int array[10];//値を格納
	int max, min;
	
	do {
		scanf("%d",&array[i]);
		printf("%d番:%d\n",i+1,array[i]);
		i++;
	} while (array[i-1] != 0);//0が入力された時点で終了
	
	calculate(array,&max,&min);
	
	printf("最大値:%d\n最小値:%d\n",max, min);
	
	return 0;
}

void calculate(int array[],int *max,int *min){
	int i;
	int high = 1;//最大値
    int low = 1000;//最小値

	for(i=0; array[i]!=0; i++){
	    if(array[i] > high){
	        high = array[i];
	    }
	    if(array[i] < low){
	        low = array[i];
	    }
	}
	        *max = high;
	        *min = low;
}
high lowにいれなくてもできた
void calculate(int array[], int *max, int *min){
	int i;
	*max = 1;
	*min = 1000;

	for (i = 0; array[i] != 0; i++){
		if (array[i] > *max){
			*max = array[i];
		}
		if (array[i] < *min){
			*min = array[i];
		}
	}
}
すごい
void calculate(int array[], int *max, int *min){
	int i;
	*max = *min = *array;   //max,minの初期値にarray[0]が入る

	for (i = 1; array[i] != 0; i++){
		if (array[i] > *max){
			*max = array[i];
		}
		if (array[i] < *min){
			*min = array[i];
		}
	}
}

比較の時に最初の値をmaxとminに入れておいてぐるぐるするので、
intの範囲でどんな数でも入れられるようになった

iを消した
void calculate(int array[], int *max, int *min){
	for (*min = *max = *array; *array; array++){
		if (*array > *max){
			*max = *array;
		}
		if (*array < *min){
			*min = *array;
		}
	}
}

2行短くなった!!

表示

[283 876 961 346 315 0]と入力すると、どれも
次のように表示される

1番:283
2番:876
3番:961
4番:346
5番:315
6番:0
最大値:961
最小値:283

やったね

配列のポインタ(C)

コメントで教えてくださりありがとうございます。
表し方の数を増やしました。

これらは同じ意味
data[i]
*(data + i)
*(i + data)    //New!!
i[data]    //New!!

i[data]で表せることにビックリした

配列を書き換えられる
    int arr[5] = {1,2,3,4,5};
    printf("%d\n", arr[2]); //3
    data = arr;
    data[2] = 8; //他の書き方可
    printf("%d\n", arr[2]); //8
使ってみる
#include <stdio.h>
int main(void){
    int *data;
    int i;
    int sum = 0;
    int arr[5] = {1,2,3,4,5};
    
    data = arr;
    for(i = 0; i < 5; i++){
        sum += data[i]; //他の書き方可
    }
    printf("%d\n", sum); //15

    return 0;
}
上のfor文はこう書ける
    for(data = arr; data != &arr[5]; data++){
        //data = &arr[0]
        sum += *data;
    }
引数に配列を与える

色々書ける

型 hoge(型 配列名[要素数]);
型 hoge(型 配列名[]);
型 hoge(型 *配列名);

ポインタを理解しようと思って解いた問題の解答例がエラーばかりで悲しい

ポインタを使えるようになりたい(C)

ポインタは難しい。

同じアドレスになる
#include <stdio.h>

int main(void){
    int *p; //ポインタ変数を宣言
    int i = 2;
    p = &i; //pにiのアドレスを入れる
    printf("%d\n", i);
    printf("%p\n", &i); //iのアドレスを表示
    printf("%p\n", p);//pのアドレスを表示

    return 0;
    }

//2
//0x7ffcfdad145c
//0x7ffcfdad145c
書き換えられる
int *p;
int i = 2;
p = &i;
*p = 5;
printf("%d\n", i); // 5
NULLを使って事故を防止

宣言したポインタ変数に使えないアドレスが入っていると事故る

int *p = NULL;
使ってみる

ポインタ演算を使わずに足し算

#include <stdio.h>
int main(void){
    int i, sum = 0, num[10]={1,2,3,4,5,6,7,8,9,10};
    for(i = 0; i<10; i++){
        sum += num[i];
    }
    printf("%d", sum);
    return 0;
}


ポインタ演算を使うと、

#include <stdio.h>
int main(void){
    int *data, sum = 0, num[10]={1,2,3,4,5,6,7,8,9,10};
    for(data = num; data != &num[10]; data++){
        sum += *data;
    }
    printf("%d", sum);
    return 0;
}

つづく

構造体(C)

構造体について。

構造体の作成
struct 構造体タグ名{
//データ
}

普通関数よりも先に宣言する

構造体の型の変数を宣言
struct 構造体タグ名 構造体変数名;

C++ではstructをつけなくても宣言できるらしい。

新しく名前をつける
struct animals_tag {
    char animal[64];
    char name[64];
    int old;
    int weight;
};
typedef struct animals_tag animals;
/* typedef データ型 新しい名前 */
一度に宣言できる
typedef struct animals_tag {
    char animal[64];
    char name[64];
    int old;
    int weight;
} animals;

新しい型が定義できれば構造体タグ名を省略できる?

typedef struct {
    char animal[64];
    char name[64];
    int old;
    int weight;
} animals;

構造体のポインタを構造体要素に持つときは省略できない
(構造体の宣言が終了していないから?)

構造体変数では要素を名前で区別する
#include <stdio.h>
struct animals_tag {
    char animal[64];
    char name[64];
    int old;
    int weight;
};

int main(void){
    struct animals_tag data;
    data.old = 5;
    printf("%d歳", data.old);

    return 0;
}
/*5歳*/
文字列を扱うならstrcpy
#include <stdio.h>
#include <string.h>
struct animals_tag {
    char animal[64];
    char name[64];
    int old;
    int weight;
};

int main(void){
    struct animals_tag data;

    strcpy(data.animal, "ねこ");
    printf("%s", data.animal);

    return 0;
}
/*ねこ*/
表示してみる
#include <stdio.h>
#include <string.h>
typedef struct {
    char animal[64];
    char name[64];
    int old;
    int weight;
} animals;
void animals_print(animals data);
int main(void){
    
    animals data;
    strcpy(data.animal,"ねこ");
    strcpy(data.name, "きなこ");
    data.old = 2;
    data.weight = 5;
    
    animals_print(data);
    
    return 0;
}
void animals_print(animals data){
    printf("種類:%s\n", data.animal);
    printf("名前:%s\n", data.name);
    printf("年齢:%d\n", data.old);
    printf("体重:%dkg\n", data.weight);
    return;
}
/*
種類:ねこ
名前:きなこ
年齢:2歳
体重:5kg
*/
構造体の注意

○構造体変数同士での演算、比較はできない
○配列が含まれているとき、中身がコピーされる

書式を変えてみる(Python)

前回に引き続きformatを使ってみる

オプションを設定!
{引数のインデックス:オプション}
{:オプション}
位置を調節
'{:<10}'.format('左詰め')
#'左詰め       '
'{:>10}'.format('右詰め')
#'       右詰め'
'{:^10}'.format('真ん中')
#'   真ん中    '
特定の文字(※1文字)で調節
'{:☆^15}'.format('Hello')#オプションの前で指定
#'☆☆☆☆☆Hello☆☆☆☆☆'
数値に符号をつける
#'+':正負の符号をつける
#'-':負の値に符号をつける
#' ':正の数のとき空白、負の数のとき符号をつける
'{:+}'.format(1)
#'+1'
'{:+}'.format(-1)
#'-1'
'{:-}'.format(-1)
#'-1'
'{: }'.format(1)
#' 1'
'{: }'.format(-1)
#'-1'
10進数にをn進数に変換
'{:b}'.format(12)#b:2進数
#1100
'{:o}'.format(12)#o:8進数
#'14'
'{:d}'.format(12)#d:10進数
#'12'
'{:x}'.format(12)#x:16進数
#'c'
'{:X}'.format(12)#X:16進数(アルファベット大文字)
#'C'
'{:#x}'.format(18)
#'0x12'
','で数を区切る
'{:,}'.format(1000000)
#'1,000,000'
小数
'{:f}'.format(0.12)
#'0.120000'
小数点以下の桁数を指定
'{:.2f}'.format(0.12345)
#'0.12'
'{:.5f}'.format(0.12345)
#'0.12345'

.。( C言語のprintfと似てる )

パーセントに変換する
'{:.0%}'.format(0.25)
#'25%'
'{:.1%}'.format(0.2546)
#'25.5%' .。(四捨五入される)

文章中に文字列や数を挿入(Python)

今回はformatを使ってみる

こういう感じ
name = 'ねこ'
print('あなたは{}ですか?'.format(name))
#あなたはねこですか?
複数の引数を用いる
print('今日は{0}か{1}か{2}が食べたい'.format('カレー','うどん','野菜炒め'))
print('今日は{m1}か{m2}か{m3}が食べたい'.format(m1='カレー',m2='うどん',m3='野菜炒め'))
#今日はカレーかうどんか野菜炒めが食べたい
順番通りだと省略できる
print('今日は{}か{}か{}が食べたい'.format('カレー','うどん','野菜炒め'))
#今日はカレーかうどんか野菜炒めが食べたい
リスト
lst = ['じゃがいも', 'かぼちゃ', 'トマト', 'にんじん', 'たまねぎ']
print('夕食の材料は{0[0]}と{0[3]}と{0[4]}です'.format(lst))
#夕食の材料はじゃがいもとにんじんとたまねぎです
辞書
dic = {'name': 'ねこ', 'color': 'white', 'age': '3'}
print('名前は{0[name]}、色は{0[color]}、歳は{0[age]}歳'.format(dic))
#名前はねこ、色はwhite、歳は3歳

次回は書式

関数を作る(Python)

今回は関数を作ることについて。理解していないことの多さを痛感。

関数の定義
def 関数名():
    処理
return
def name(na):
    return na

def hello():
    print(name('ねこ') + "さん、こんにちは!!")

#ねこさん、こんにちは!!

printで'+'をつけることを忘れそうになる

複数return

','で区切ることで複数の要素をreturnできる
○タプル
下のようにreturnすると、型はタプル

def test():
    return 'zero', 0

print(type(test()))
<class 'tuple'>

○リスト
'[]'で囲むことで型がリストになる

def test():
    return ['zero', 0]

print(type(test()))
#<class 'list'>
デフォルト引数
def 関数名(引数=デフォルト値,引数=デフォルト値):
    関数のブロック
#引数を指定せず関数を実行すると、デフォルト引数が入る
def name(na = '名無し'):
    return na

print(name() + "さん!")
#名無しさん!

print(name('ねこ') + "さん!")
#ねこさん!
デフォルト引数の注意点

デフォルト値は最初に一度だけしか評価されないので、
リストや辞書といった変更可能なオブジェクトを使う際、注意が必要

def list_beta(lst = []):
    lst.append('Hello')
    print(lst)
list_beta()
list_beta()
list_beta()
list_beta(['Good','Morning'])

#['Hello']
#['Hello', 'Hello']
#['Hello', 'Hello', 'Hello']
#['Good', 'Morning', 'Hello']

デフォルト引数は不変のものを設定する方が良い

def list_beta(lst = None):
    if lst is None:
        lst = []
    lst.append('Hello')
    print(lst)
    
list_beta()
list_beta()
list_beta(['Good','Morning'])

#['Hello']
#['Hello']
#['Good', 'Morning', 'Hello']