웹_프론트_백엔드/단과

[단과_C] 2020.03.18

shine94 2020. 3. 18. 23:01

1. 포인터(주소값) 
   포인터 변수
   포인터 상수(배열) : 값을 변경하기 위해서는 strcpy() 필요
   
   변수 : 값을 담기 위한 저장공간
   포인터 변수 : 주소값을 담기 위한 저장 공간
   포인터 변수를 줄여서 포인터라고 부르기도 한다.

 


2. 포인터를 사용하는 이유
1) return값은 반드시 한 개여야 하기 때문에 포인터를 사용한다.
   주소값은 유일하기 때문에(중복이 없기 때문에)
   주소값을 다른 영역에 전달하면 (참조로 접근해서)값을 수정할 수 있다.


3. 포인터 확인하는 방법
1) 중단점 : F9
2) 디버그 : F5
3) 디버그클릭 > 창 > 자동 > 주소값 우클릭 > 값 복사 클릭
4) Ctrl + Alt + m, 1 : 메모리1 창
5) 주소 붙여넣기
6) 다음 줄 디버깅 : F10

 


4. 이중 포인터
 : 포인터의 주소값을 담기 위해 사용한다.
   다른 영역에 있는 포인터의 값을 수정하기 위해 사용한다.

 


5. 포인터 배열
 : 포인터를 여러 개 선언하게 되면 관리가 힘들기 때문에
   포인터 형식의 배열을 선언할 때 사용한다.

 


6. 배열 포인터
 : 배열의 주소값을 담을 저장공간 


7. 오늘 실습코드

1) cafe 만들기

** cafe.c **

#include<stdio.h>
#include<string.h>
//사용자 정의 헤더파일 추가
#include"twosomeplace.h"

//상품 최대 개수
#define CNT 100

/*전역변수*/
//상품명 배열
char arName[CNT][100] = { "", };
//가격 배열
int arPrice[CNT] = { 0, };
//추가된 상품 총 개수
int insertCnt;
//검색된 상품의 행번호
int rowNum;

void main() {
	//twosomeplace.h 참고
	cafe();
}


** twosomeplace.h **

#define CNT 100

/*======함수 선언부======*/
/*재사용의 목적*/
char checkDup(char[]);
void insert(char[], int);
void update(char[], int, int);
void delete();
int select(char[], int[]);

/*소스코드 간결화*/
void printInsert();
void printUpdate();
void printDelete();
void printSelect();
void selectAll();
void cafe();
/*================*/

//extern 사용시 초기값을 넣을 수 없다.
//중복 선언으로 간주된다.
extern char arName[CNT][100];
extern int arPrice[CNT];
extern int insertCnt;
extern int rowNum;

void cafe() {
	char title[20] = "♨Twosome place♨";
	char menu[100] = "①추가하기\n②수정하기\n③삭제하기\n④검색하기\n⑤목록보기\n⑥나가기\n";
	char errMsg[20] = "다시 시도해주세요.";

	int choice = 0;

	while (1) {
		printf("%s\n%s", title, menu);
		scanf_s("%d", &choice);

		if (choice == 6) { break; }

		switch (choice) {
		//추가
		case 1:
			printInsert();
			break;
		//수정
		case 2:
			printUpdate();
			break;
		//삭제
		case 3:
			printDelete();
			break;
		//검색
		case 4:
			printSelect();
			break;
		//목록
		case 5:
			selectAll();
			break;
		//그 외
		default:
			printf("%s", errMsg);
		}
	}
}
//중복검사
char checkDup(char temp[]) {
	//외부에서 문자열을 전달받아서 arName에 있는지 없는지 검사
	char check = '0';
	for (int i = 0; i < insertCnt; i++) {
		if (!strcmp(arName[i], temp)) {
			rowNum = i;
			//중복이 있다면 check는 '1'
			check = '1';
			break;
		}
	}
	return check;
}
//추가
//char insert(char temp[], int price) {
void insert(char temp[], int price) {
	//char isDup = checkDup(temp);
	//char check = '0';

	//if(!(isDup - 48)){

	//외부에서 중복검사 진행 후 insert()사용!
	strcpy_s(arName[insertCnt], sizeof(arName[insertCnt]), temp);
	arPrice[insertCnt] = price;
	//총 상품개수 1 증가
	insertCnt++;
	//check = '1';
	//}
	//return check;
}
void printInsert() {
	char isDup = ' ';
	char temp[100] = "";
	int price = 0;

	printf("상품명 : ");
	scanf_s("%s", temp, sizeof(temp));
	isDup = checkDup(temp);

	//중복이 없다면 참
	//문자 - 48 == 정수
	if (!(isDup - 48)) {
		printf("가격 : ");
		scanf_s("%d", &price);
		insert(temp, price);
	}
	else {
		printf("중복된 상품명입니다.\n");
	}
}
//수정
void update(char temp[], int price, int choice) {
	//외부에서 새로운 상품명, 새로운 가격, 수정할 상품의 행번호를 전달 받는다.
	strcpy_s(arName[choice], sizeof(arName[choice]), temp);
	arPrice[choice] = price;
}
void printUpdate() {
	char temp[100] = "";
	char isDup = ' ';
	int choice = 0;
	int price = 0;

	printf("수정하실 기존 상품명 : ");
	scanf_s("%s", temp, sizeof(temp));
	isDup = checkDup(temp);
	//수정할 상품이 있는지(1번), 있다면 새로운 상품명이 중복되는지(2번)
	//총 checkDup()를 2번 사용하기 때문에 1번 rowNum을 기억해야 한다.
	//1번 rowNum이 수정할 행 번호이기 때문이다. 따라서 choice에 1번 rowNum을
	//저장한다.
	//만약 저장하지 않으면 2번에서 rowNum의 값이 변경될 수 있다.
	choice = rowNum;

	//1번
	if (isDup - 48) {
		printf("새로운 상품명 : ");
		scanf_s("%s", temp, sizeof(temp));
		isDup = checkDup(temp);
		//2번
		if (!(isDup - 48)) {
			printf("새로운 가격 : ");
			scanf_s("%d", &price);
			update(temp, price, choice);
		}
		else {
			printf("중복된 상품명입니다.\n");
		}
	}
	else {
		printf("수정하실 상품이 존재하지 않습니다.\n");
	}
}
//삭제
void delete() {
	for (int j = rowNum; j < insertCnt; j++) {
		strcpy_s(arName[j], sizeof(arName[j]), arName[j + 1]);
		arPrice[j] = arPrice[j + 1];
	}
	insertCnt--;
}
void printDelete() {
	char temp[100] = "";
	char isDup = ' ';

	printf("삭제할 상품명 : ");
	scanf_s("%s", temp, sizeof(temp));

	isDup = checkDup(temp);
	if (isDup - 48) {
		delete();
	}
	else {
		printf("삭제하실 상품이 존재하지 않습니다.\n");
	}
}
//검색
int select(char temp[], int arIdx[]) {
	//상품명, 검색된 상품의 행번호를 담을 배열의 주소를 전달받는다.
	int cnt = 0;

	for (int i = 0; i < insertCnt; i++) {
		//arName의 각 요소에 temp가 포함되어 있다면 검색 성공!
		//"아" 검색시 "아"가 포함된 모든 문자열 검색
		if (strstr(arName[i], temp) != NULL) {
			//결과가 한 개 이상이 나올 수 있기 때문에 arIdx를 배열로 만든다.
			//i는 검색된 상품의 행 번호이다.
			arIdx[cnt] = i;
			cnt++;
		}
	}
	//총 검색 결과 건수 리턴
	return cnt;
}
void printSelect() {
	char temp[100] = "";
	int arIdx[100] = { 0, };
	int cnt = 0;

	printf("검색할 상품명 입력 : ");
	scanf_s("%s", temp, sizeof(temp));

	//이 영역에 있는 arIdx의 주소를 select함수에 전달한다.
	cnt = select(temp, arIdx);
	for (int i = 0; i < cnt; i++) {
		//arIdx배열은 각 방에 검색된 상품의 행 번호를 가지고 있다.
		//따라서 순서대로 cnt만큼 반복하면 검색 결과를 출력할 수 있다.
		printf("%s(%d원)\n", arName[arIdx[i]], arPrice[arIdx[i]]);
	}
	//검색 결과가 없을 때
	if (cnt == 0) {
		printf("검색결과 없음\n");
	}
}
//목록
void selectAll() {
	char temp[100] = "";
	strcpy_s(temp, sizeof(temp), insertCnt == 0 ? "목록 없음" : "상품명(가격)");
	printf("%s\n", temp);
	for (int i = 0; i < insertCnt; i++) {
		//총 상품 개수만큼 순서대로 출력
		printf("%s(%d원)\n", arName[i], arPrice[i]);
	}
}

 

2) pointerTest.c

#include<stdio.h>
void main() {
	int data = 10;
	int data2 = 20;
	int* PData = &data;
	
	PData = &data2;

	printf("%d\n", data);
	printf("%d\n", *PData);
	printf("%p\n", &data2);
	printf("%p\n", PData);
}

 

3) pointer.c

#include<stdio.h>
void function(int data) { 
	data = 100;
}

void function2(int* pData) {
	*pData = 100;
}

void main() {
	int data = 10;
    
	//call by value : 값에 의한 호출
	function(data);
	printf("%d\n", data);

	//call by address : 주소값에 의한 호출
	function2(&data);
	printf("%d\n", data);
}

 

4) pointerTask.c

#include<stdio.h>
//정수를 입력받고 입력받은 정수의 제곱을 구해주는 void형 함수 선언하기
//main()함수에서 정수를 입력받는다.
void 제곱(int* PNum) {
	*PNum = *PNum * *PNum;
}
void main() {
	int num = 0;
	printf("정수 : ");
	scanf_s("%d", &num);

	printf("%d의 제곱 : ", num);
	제곱(&num);
	printf("%d\n", num);

}

 

5) doublePointer.c

#include<stdio.h>
//void function(int* pData) {
void function(int** PPData) {
	int data = 100;
	//pData = &data;
	*PPData = &data;
}

void main() {
	int data = 10;
	int* PData = &data;
	//function(pData);
	function(&PData);
	printf("%d\n", *PData);
}

 

6) poterEtc.c

#include<stdio.h>
#define L 3
void main() {
	int arData[L] = { 10, 20, 30 };
	int(*arPData)[L] = &arData;

	for (int i = 0; i < L; i++) {
		//printf("%d\n", (*arPData)[i]);
		printf("%d\n", *((*arPData) + i));
	}

	//int* PArData[L] = { 0, };

	//for (int i = 0; i < L; i++) {
	//	PArData[i] = &arData[i];
	//}

	//for (int i = 0; i < L; i++) {
	//	printf("%d\n", *PArData[i]);
	//}
}

'웹_프론트_백엔드 > 단과' 카테고리의 다른 글

[단과_C] 2020.03.20  (0) 2020.03.22
[단과_C] 2020.03.19  (0) 2020.03.20
[단과_C] 2020.03.17  (0) 2020.03.18
[단과_C] 2020.03.16  (0) 2020.03.17
[단과_C] 2020.03.13  (0) 2020.03.15