[ 4주차 - 2 ]
함수
전역변수와 지역변수의 이름이 같을 때는 지역변수에 우선순위가 있음
포인터와 함께 함수 호출
1. 포인터와 함께 함수 호출
→ 함수의 매개변수를 포인터 형으로 선언
→ 포인터를 사용하는 함수 내의 연산을 수행할 때, 그 포인터가 가리키는 변수에서 작동
2. 배열과 함께 함수 호출
→ 함수의 매개변수를 배열 또는 포인터로 선언한다.
→ 함수 호출시에 배열에 대한 오직 하나의 포인터만이 전달된다.
→ c++는 배열의 경계를 확인하지 않으므로 배열의 실제 크기는 중요하지 않다.
3. 문자열 전달
→ 문자열이 함수에 전달될 때, 그 문자열의 시작에 대한 포인터가 실제 전달된다.
#include <iostream>
using namespace std;
void f(int *j);
int main() {
int i;
int *p;
p = &i; // p는 i를 가리키는 포인터 변수
f(p); // f(&i)와 같은 기능이다. -> i의 주소가 전달됨
cout << i;
return 0;
}
void f(int *j) { // 포인터 변수를 받는 매개변수도 포인터 변수로 선언을 해줘야함
*j = 100;
}
// ▶ 100
함수를 호출할 때 포인터 변수를 파라미터로 넘겨준다면 대응하는 함수의 매개변수는 반드시 포인터 변수로 선언을
해주고, 호출할 때 파라미터로 들어온 포인터 변수의 주소를 받아서 * 연산자를 사용해 그 주소에 해당하는 값에
넣어줄 수 있다.
배열과 함께 함수 호출하기
#include <iostream>
using namespace std;
void display(int num[10]);
int main() {
int t[10];
for (int i = 0; i < 10; ++i) {
t[i] = i;
}
display(t);
return 0;
}
void display(int num[10]) { // int num[10] == int num[] == int *num
for (int i = 0; i < 10; i++) {
cout << num[i] << " ";
}
}
// ▶ 0 1 2 3 4 5 6 7 8 9
display 함수의 파라미터인 num 배열은 인수로 넣은 배열 t를 공유한다. 즉 t의 주소를 그대로 받게 된다.
→ t의 시작주소가 num에 들어가게 된다.
* 배열을 파라미터로 받을 때는 빈 대괄호( [] )로 줌으로써 배열을 명시하는게 좋다. 포인터 변수를 넣을 경우
배열이 들어오는지 무슨 변수가 들어오는지 알 수 가 없다.
문자열 전달하기
#include <iostream>
#include <cstring>
#include <cctype>
using namespace std;
void stringupper(char *str);
int main() {
char str[80];
strcpy_s(str, "this is a text");
stringupper(str); // str 배열의 주소가 전달이 된다.
cout << str;
return 0;
}
void stringupper(char *str) { // char *str == char str[]
while (*str) {
*str = toupper(*str);
str++; // 다음 문자로 이동
}
}
// ▶ THIS IS A TEXT
문자열도 char 형 배열이기 때문에 함수의 파라미터로 포인터 변수나 배열을 전달하는 것은 똑같다.
main() 함수의 매개변수 : argc, argv
명령어 라인 인수 ( command line argument ) : 프로그램이 실행할 때의 정보 전달
→ 명령어 라인에서 프로그램의 이름 뒤에 오는 정보를 메인 함수의 매개변수가 받는다.
* 명령어 라인 인수는 빈칸 또는 탭에 의해 구분
1. argc : 명령어 라인에 있는 인수들의 수를 저장 ( 프로그램의 이름도 하나의 인수로 취급 )
2. argv : 문자형 포인터 배열에 대한 포인터
argv[0]은 프로그램의 이름
argv[1]은 첫번째 인수
argv[2]는 두번째 인수
* argv는 여러개 문자열을 나타내는 배열이 되어야 하므로 포인터이다.
또한 2차원 배열로 한 행에는 인수로 들어오는 하나의 문자열을 나타내고, 차례차례 인수로 들어오는 문자열을
저장하고 나타낸다.
#include <iostream>
#include <cstdlib>
using namespace std;
int main(int argc, char *argv[]) {
double a, b;
if (argc != 3) { //비정상적인 경우
cout << "Usage : add num num\n";
return 1;
}
a = atof(argv[1]);
b = atof(argv[2]);
cout << a + b;
return 0;
}
num에게 값을 전달해주는 것은 운영체제이다. argc에는 명령어 라인에 있는 인수들의 수를 전달하므로
argc는 3이 전달이 된다. argv[0]에는 add 라는 문자열이 들어가고, argv[1]에는 100.2, argv[2]에는 231라는
문자열이 전달된다. 명령어 라인에 입력될 때는 모두 문자열 취급한다.
* atof()는 문자열을 실수형( float )으로 변환해주는 시스템 함수이다.
atoi()는 문자열을 정수형( int )으로 변환해주는 시스템 함수이다.
* visual studio에서 명령어 인수 넣기
[ 프로젝트 메뉴 ] → [ 프로젝트이름의 속성 ] → [ 구성 속성 - 디버깅 ]
명령인수로 aaa bbb ccc 총 3개가 있지만 4개가 있다고 인식이 되어 argc에는 4가 전달이 된다.
→ 실행 파일 프로그램의 파일 이름은 명령 인수에 주지 않는다.
return 문
return문의 기능으로는 함수의 호출 부분으로 즉각 되돌아가게 한다.
하나의 값을 반환하기 위해 사용될 수 있지만 함수가 void로 선언됐을 경우는 값을 반환할 수 없다.
* void 함수는 값을 반환하지 않음 → 함수를 식에 사용하는 것을 방지한다.
#include <iostream>
using namespace std;
int find_substr(char *sub, char *str);
// sub가 str의 어디 위치에 포함되어 있는지 index를 나타내줌
int main() {
int index;
index = find_substr("three", "one two three four");
cout << "index of three is " << index;
return 0;
}
int find_substr(char *sub, char *str) {
char *p, *p2;
for (int t = 0; str[t]; t++) { //긴 문자열이 끝날 때까지 반복
p = &str[t]; // 포인터를 다시 설정
p2 = sub;
/*p2와 p가 같은 글자를 가리키고 있는 동안 반복*/
while (*p2 && *p2 == *p) { //부분 문자열을 확인
p++;
p2++;
}
/* p2의 끝에 도달했다면 일치하는 것을 찾은 것*/
if (!*p2) return t; //일치하는 곳의 첨자를 반환
}
return -1; //일치하는 것이 없을 때
}
// ▶ index of three is 8
* const char * 형식의 인수가 char * 형식의 매개 변수와 호환되지 않습니다 오류 구문
→ 대입 하려는 문자열이 문자열 상수이기 때문에 대입하고자 하는 값에 const를 붙여줘야한다.
// 변경 전
char *name = "2chaechae"
// 변경 후
const char *name = "2chaechae"
에러가 생기는 이유는 기존 visual studio 표준을 무시하고 컴파일을 시도했기 때문
→ visual studio 17 기준으로 준수모드가 표준적으로 '예'로 설정되어 있어서 '아니오'로 변경해줘야함
실습 문제
find_substr 함수를 사용해서 문자열에서 일치하는 부분 문자열의 수를 출력하기
입력 문자열 = "aabababacabaabca"
패턴 = "aba"
#include <iostream>
using namespace std;
int find_substr(char *string, char *pattern);
int main() {
int index;
index = find_substr("aabababacabaabca", "aba");
cout << "문자열 수 출력하기 : " << index;
return 0;
}
int find_substr(char *string, char *pattern) {
int count = 0;
char* p, * p2;
for (int i = 0; string[i]; i++) { //문자열이 끝날 때 까지 반복
p = &string[i]; //포인터를 다시 설정
p2 = pattern;
//p2와 p가 같은 글자를 가리키고 있는 동안 반복
while (*p2 && *p2 == *p) { //부분 문자열을 확인
p++;
p2++;
}
if (!*p2) { //p2의 끝에 도달했다면 일치하는 것을 찾은 것
count++;
}
}
return count;
}
'2CHAECHAE 학교생활 > 객체지향프로그래밍(C++)' 카테고리의 다른 글
[ 객체지향프로그래밍(C++) 5주차 ② ] (0) | 2022.04.01 |
---|---|
[ 객체지향프로그래밍(C++) 5주차 ① ] (0) | 2022.04.01 |
[ 객체지향프로그래밍(C++) 4주차 ① ] (0) | 2022.03.24 |
[ 객체지향프로그래밍(C++) 3주차 ② ] (0) | 2022.03.21 |
[ 객체지향프로그래밍(C++) 3주차 ① ] (0) | 2022.03.21 |