One dimensional arrays
array 배열
선언하는 법 : type array_name[size];
array initialization 배열 초기화
array는 storage class가 auto, external, static일 수 있다(register는 안됨)
auto인 경우에는 선언만 해주면, 쓰레기값이 들어있으므로꼭 초기화를 해주어야 한다.
float f[5] = {0.0, 1.0, 2.0, 3.0, 4.0};
int a[100] = {0};
int a[] = {2,3,5,-7};
array subscripting 배열 첨자
a[i]로 배열 요소에 접근한다.
sorting
배열을 이용하여, 4,-681,52,-23,15,9,13을 정렬하는 프로그램을 짜보자.
1) bubble sort program
우선 가장 코드가 간단한 bubble sort부터!
int bubbleSort(int a[], int n){
for (int i =0;i<n;i++){
for (int j = i;j<n;j++){
if (a[i]>a[j]){
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
}
for (int i=0;i<n;i++){
printf("%d\n", a[i]);
}
return 0;
}
2) selection sort algorithm
int selectionSort(int a[], int n){
for (int i=0;i<n;i++){
int tmp = a[i];
for (int j=i;j<n;j++){
if (a[j]<a[i]){
tmp = a[j];
}
}
a[i] = tmp;
}
for (int i=0;i<n;i++){
printf("%d\n", a[i]);
}
return 0;
}
pointer
& : 주소를 나타내는 단항 연산자
포인터 변수는 값으로 주소를 가져간다.
포인터 변수의 선언은 int *p; 와 같은 형식으로 이루어진다.
선언 : type *pointer_name;
할당 : pointer_name = &variable;
조작 : *pointer_name = value;
-> *pointer_name은 해당 메모리 주소에 저장된 값을 의미한다.
특이한 사례)
포인터 변수에 직접 특정한 상수를 부여할 수도 있다.
int *p;
p=0;
p=NULL; // == p=0;
p=&i;
p = (int*) 1776; // 메모리의 진짜 주소값 like 관악로1번지
용례)
int a =1, b=2, *p;
p = &a;
b = *p;
#include <stdio.h>
int main(void){
int i=7, *p = &i;
printf("Value of i:%d\nLocation of i:%p",*p, p);
return 0;
}
허용되는 경우
포인터 타입이 서로 다른데 할당하려고 하는 경우
int *p = 0; // void인 경우와
int *p = (int*) 1; // constant인 경우와
void *v; int *p = v; // void 포인트인 경우 허용된다.
call by reference
기본은 call by value인데,
포인터 변수를 이용하면 call by reference를 수행할 수 있다.
arrays and pointers
#include <stdio.h>
void swap(int *, int*);
int main(void){
int i=3, j=5;
printf("%d %d\n", i, j);
swap(&i, &j);
printf("%d %d\n", i, j);
return 0;
}
void swap(int *p, int *q){
int tmp;
tmp = *p;
*p = *q;
*q = tmp;
}
배열도 포인터와 같이 취급할 수 있다.
a[i] = *(a+i)
*(p+i) = p[i]
p = a; <=> p = &a[0];
p = a+1; <=> p = &a[1];
int a[N]과 같이 정의된 배열은 상수 포인터와 같다?
pointer arithmetic and element size
pointer arithmetic
포인터가 특정한 type으로 선언된 경우,
p+1, p+i, ++p, p+= i와 같은 산술적인 조작이 가능하다.
double a[2], *p, *q;
p = a;
q = p+1;
printf("%d\n", q-p);
printf("%d\n", (int)q - (int)p); // 주소의 차이 == sizeof(double) == 8
q - p
array element의 개수를 보여준다.
arrays as function arguments
이거 선언하는 방법이 어렵다.
그 다음에는 똑같음
기본적으로 call by value
double sum(double a[], int n)
{
int i;
double sum = 0.0;
for (i=0;i<n;++i)
sum += a[i];
return sum;
}
void main(void)
{
double v[100];
sum(v,100);
sum(&v[50], 50);
sum(v+7, 3);
}
pointer 변수를 인자로 넣으면, call by reference가 된다.
double sum(double *a, int n)
{
// ...
}
bubble sort
using pointer
#include <stdio.h>
#include <stdlib.h>
void bubbleSort(int *, int);
void swap(int *, int *);
void print(int *, int);
int main(void){
int *a, n;
n = 12;
int list[] = {10,20,30,1,2,3,4,5,6,2,1,13};
a = list;
bubbleSort(a, n);
print(a, n);
return 0;
}
void bubbleSort(int *a, int n){
for (int i=0;i<n;i++){
for (int j =i;j<n;j++){
if (*(a+i)>*(a+j)){
swap((a+i), (a+j));
}
}
}
}
void swap(int *a, int *b){
int *tmp = (int*)malloc(sizeof(int));
*tmp = *a;
*a = *b;
*b = *tmp;
}
void print(int *a, int n){
for (int i=0;i<n;i++){
printf("%d ", *a);
a++;
}
printf("\n");
}
dynamic memory allocation
stdlib.h 헤더 파일에 calloc(), malloc(), free() 함수가 있다.
보통 malloc을 많이 쓴다. free는 자꾸 까먹는데, 잘 쓰도록 하자.
calloc()
ptr = calloc(n, sizeof(int);
연속적인 할당? (초기화 해줌)
char *p = (char*)malloc(sizeof(char)*10));
char *p = (char*)calloc(10,sizeof(char));
malloc()
ptr = malloc(n*sizeof(int));
메모리 할당 (초기화 안해줌)
free(ptr);
할당해준 메모리 공간을 해제한다.
merge sort
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
void merge(int a[], int b[], int c[], int m, int n);
void mergeSort(int key[], int n);
void wrt(int key[], int sz);
void merge(int a[], int b[], int c[], int m, int n){
int i=0, j=0, k=0;
while (i<m&&j<n){
if (a[i]<b[j]){
c[k++]=a[i++];
}
else{
c[k++]=b[j++];
}
}
while (i<m) c[k++]=a[i++];
while (j<n) c[k++]=b[j++];
}
void mergeSort(int key[], int n){
int j, k, m, *w;
for (m=1;m<n;m*=2);
if (n<m) exit(1);
w=calloc(n, sizeof(int));
assert(w!=NULL);
for (k=1;k<n;k*=2){
for (j=0;j<n-k;j+=2*k){
merge(key+j, key+j+k, w+j, k, k);
}
for (j=0;j<n;++j) key[j] = w[j];
}
free(w);
}
void main(void){
int sz;
int key[] = {4,3,1,67,55,8,0,4,-5,37, 7,42,9,1,-1};
sz=sizeof(key)/sizeof(int);
printf("\nBefore : ");
wrt(key, sz);
mergeSort(key, sz);
printf("\nAfter");
wrt(key, sz);
}
void wrt(int key[], int sz){
for (int i=0;i<sz;i++){
printf("%d ", *(key+i));
}
printf("\n");
}
strings
문자열은 char type의 1차원 배열과 같다.
문자열의 끝을 표기하기 위해서 '\0'가 추가된다(Null character)
string 문자열 상수는 포인터처럼 취급할 수 있다.
char *p = "abcde";
count the number of words in a string
scanf 대신 fgets를 사용하자.
fgets(저장할 배열, 배열의 최대 크기, stdin);
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void){
char s[100];
fgets(s, 100, stdin);
int cnt = 0;
char *str = s;
while (*str!='\0'){
while (isspace(*str)){
str++;
}
if (*str!='\0'){
cnt++;
while (!isspace(*str)&&*str!='\0'){
str++;
}
}
}
printf("%d\n", cnt);
return 0;
}
string handling functions in standard library
string.h에 정의되어 있다.
- strcat -
원형 : char *strcat(char *s1, const char *s2);
s1 뒤에 s2를 붙인다. concat
- strcpy -
원형 : char *strcpy(char *s1, const char *s2);
s1을 s2에 복사 붙여넣기 한다('\0'까지 함께!)
- strlen -
원형 : size_t strlen(const char *s); // 형변환 필수**
number of characters before '\0'(띄어쓰기 있으면 못 세주니까 주의 - fgets를 이용하자!)fgets(저장할 배열, 배열 크기, stdin)이면 끄떡없다!
size_t strlen(const char *s)
{
size_t n;
for (n=0;*s!='\0'; ++s) ++n;
return n;
}
char *strcpy(char *s1, const char *s2)
{
char *p = s1;
while (*p++=*s2++);
return s1;
}
char *strcat(char *s1, const char *s2)
{
char *p = s1;
while (*p) ++p;
while (*p++ = *s2++);
return s1;
}
multidimentional arrays
기본적으로
int a[2][7];
double c[5][3][2];
와 같은 방식으로 다차원 배열을 선언할 수 있다.
a[i][j]로 접근 가능함
storage mapping function
그냥.. 명시적으로 다 쓰자 ^^
typedef
#include <stdio.h>
#define N 3
typedef double scalar;
typedef scalar vector[N];
typedef scalar matrix [N][N];
void add(vector x, vector y, vector z);
scalar dot_product(vector x, vector y);
scalar multiply(matrix a, matrix b, matrix c);
int main(void){
vector x = {1,2,3};
vector y = {2,3,4};
vector z = {0};
add(x,y,z);
printf("%f %f %f\n", z[0], z[1], z[2]);
printf("%f\n", dot_product(x, y));
return 0;
}
void add(vector x, vector y, vector z){
z[0] = x[0] + y[0];
z[1] = x[1] + y[1];
z[2] = x[2] + y[2];
}
scalar dot_product(vector x, vector y){
scalar tmp =0;
tmp += x[0] * y[0];
tmp += x[1] * y[1];
tmp += x[2] * y[2];
return tmp;
}
scalar multiply(matrix a, matrix b, matrix c){
/* a = b * c */
int i, j, k;
for (i=0;i<N;++i){
for (j=0;j<N;++j){
a[i][j] = 0.0;
for (k=0;k<N;++k){
a[i][j] += b[i][k] * c[k][j];
}
}
}
}
arrays of pointers
좀 긴 부분임
arguments to main()
argc, argv를 받음
#include <stdio.h>
int main(int argc, char *argv[]){
int i;
printf("argc = %d\n", argc);
for (i=0;i<argc;++i)
printf("argv[%d]=%s\n", i, argv[i]);
return 0;
}
$ ./e my_echo a is for apple
argc = 6
argv[0]=./e
argv[1]=my_echo
argv[2]=a
argv[3]=is
argv[4]=for
argv[5]=apple
int main(int argc, char * argv[])를 가져가자..
ragged arrays
크기가 다른 배열들을 수용하는 포인터의 배열 (2차원 배열)
#include <stdio.h>
int main(void){
char a[2][15] = {"abc:", "a is for apple"};
char *p[2] = {"abc:", "a is for apple"};
printf("%s%s\n", a[0], a[1]);
printf("%s%s\n", *p, *(p+1));
return 0;
}
function as arguments
이걸.. 꼭.. 지금 봐야할까?
function pointers
이걸.. 꼭.. 지금 봐야할까?
'Computer Science > C' 카테고리의 다른 글
C언어 10강 | Structures and list processing | 제일 중요함 *** (0) | 2021.12.17 |
---|---|
C언어 9강 | 구조체 Structures (0) | 2021.12.17 |
C언어 4강 | Flow of Control | 반복문, 조건문, 순차 구조 (0) | 2021.12.16 |
C언어 3강 | 데이터 타입 | char, int(short, long,unsigned), float, typedef (0) | 2021.12.16 |
C언어 2강 | 어휘 요소와 연산자 Lexical Elements & Operators (0) | 2021.12.15 |