-
03. 제어구조와 배열2C++ 2021. 1. 22. 13:46
제어구조와 배열 (2)
< ex19_multi_array.cpp >
#include <iostream> using namespace std; #define WIDTH 9 #define HEIGHT 3 int main(int argc, char const *argv[]) { int table[HEIGHT][WIDTH]; int r, c; for (r = 0; r < HEIGHT; r++){ for (c = 0; c < WIDTH; c++){ table[r][c] = (r+1) * (c+1); } } for (r = 0; r < HEIGHT; r++){ for (c = 0; c < WIDTH; c++){ cout << table[r][c] << ", "; } cout << endl; } return 0; }
-
다차원 배열
- 데이터타입 배열이름[행][열];
- 바깥 루프가 보통 높은 차원의 배열, 안쪽 루프가 보통 낮은 차원의 배열
- c++에서는 배열의 연산 불가능
- sizeof() -> 해당 변수에 할당된 메모리의 크기를 byte단위로 리턴해준다
< ex18_2_advanced_for.cpp >
#include <iostream> using namespace std; int main(int argc, char const *argv[]) { int list[] = {1,2,3,4,5,6,7,8,9,10}; int list2[10]; // int 하나는 4byte int length = sizeof(list) / sizeof(int); // 40 / 4 -> 10 (엘리먼트 개수) // list 메모리 크기 : int 크기(4) * 10개 -> 40byte cout << length << endl;; // 복사 전 list2 출력, 초기화 안 된 배열 // 출력 -> 14292736 0 16 0 0 0 4200206 0 4199744 // 지역변수는 초기화되지 않으면 임의의 값을 가진다 // 0으로 초기화되지 않는다 for(auto i: list2){ cout << i << " "; } // 복사 for (int i = 0; i < length; i++){ list2[i] = list[i]; // 엘리먼트 단위로 복사 } // 복사 후 lsit2 출력 for(auto i: list2){ cout << i << " "; } return 0; cout << list << endl // 0x61fda0 출력, 주소값 출력 }
< ex01_func.cpp >
#include <iostream> using namespace std; // 함수의 존재 밝혀준다, 함수 원형, 뒤에 나올 것이다 // 매개변수의 이름은 생량 가능하다 int max(int x, int y); int max(int x, int y){ if (x > y){ return x; } else { return y; } } int main(int argc, char const *argv[]) { int n; n = max(2,3); // C++는 함수를 정의 전에 호출해도 요즘 컴파일러는 돌아간다, 컴파일러에 따라 상이 // 컴파일러는 매개변수가 매칭이 잘 되고 있는가, 리턴값 맞는가를 체크 // 컴파일러가 해석할 수 있는 정보는 int max(int x, int y); 에 다 있다 cout << "result : " << n << endl; return 0; }
-
함수의 구조
-
반환형 함수이름(매개변수){}
-
ex) int max(int x, int y){}
-
반환형 생략시 디폴트로 int 배정
-
void -> 리턴데이터가 없는 때
-
-
함수 인자 전달 방법
-
call by value
- 값 복사
-
call by reference
- &(참조변수), 원본에 대한 참조로 매개변수 넘기는 것
- 참조변수 -> 기존 변수에 새로운 운영 이름 추가하는 것, 저장공간은 하나
- 참조변수는 초기화문과 같이 써야 한다, 분리되어 있으면 안 된다 (이름을 붙여야 하는데 이름을 붙일 곳이 없는 상황)
- 참조변수는 주로 매개변수 처리할 때 사용한다
- 원본을 다른 함수에서 참조매개변수를 통해서 수정할 수 있다
-
call by address (pointer)
-
사용자가 선택해서 쓰면 된다
-
파이썬은 call by value, call by reference가 일어나는 데이터타입이 정해져 있다
-
< ex04_overload.cpp >
#include <iostream> using namespace std; int square(int i){ cout << "square(int) : " << endl; return i*i; } double square(double i){ cout << "square(double) : " << endl; return i*i; } int main(int argc, char const *argv[]) { cout << square(10) << endl; cout << square(2.0) << endl; return 0; }
< ex05_default_param.cpp >
#include <iostream> using namespace std; void display(char c = '*'){ for (int i = 0; i < 20; i++){ cout << c; } cout << endl; } void display(char c = '*', int n = 10){ for (int i = 0; i < n; i++){ cout << c; } cout << endl; } int main(int argc, char const *argv[]) { display(); // 허용 X, 둘 다 호출가능한 형태 display('#'); // 허용 X, 둘 다 호출가능한 형태 display('#', 5); //후자의 display return 0; }
-
중복 함수 (overload)
-
함수의 이름은 동일하지만 함수의 인자가 다르면 다른 함수로 인식
-
동일한 이름의 함수를 여러개 만들 수 있다
-
함수 중복 체크할 때 리턴타입을 보지 않는다 (함수의 이름과 매개변수만 체크한다)
-
< ex05_2_array_func.cpp >
#include <iostream> using namespace std; void initArray(int array[], int size, int value = 0){ // int value = 0는 call by value, & 없기 때문, 대입연산을 통해서 값이 대입될 수 있어야 한다 // int array[] -> 비워두면 초기화식의 엘리먼트의 개수에 따라 결정된다, 범용함수 // 호출될 때 결정된다, 배열의 크기 한정짓지 않았다 // int size = sizeof(array) / sizeof(int); int array[] -> call by address (원본으로 작업) for (int i = 0; i < size; i++){ array[i] = value; } } void printArray(int array[], int size){ // int size = sizeof(array) / sizeof(int); for(int i = 0; i < size; i++){ cout << array[i] << " "; } cout << endl; } int main(int argc, char const *argv[]) { const int ARRAY_SIZE = 40; int intList[ARRAY_SIZE]; initArray(intList,ARRAY_SIZE, 100); // 두 번째 인자 값으로 초기화 printArray(intList, ARRAY_SIZE); initArray(intList, ARRAY_SIZE); //인자 하나, 0으로 초기화 printArray(intList, ARRAY_SIZE); return 0; }
- 배열의 개수는 상수로 운영하는 걸 추천
- 배열은 call by value 불가능! call by address 방식으로 전달한다 (배열1 = 배열2; 불가능)
- 배열1 = 배열2; 허용되면 call by value 가능, 안 되면 call by value 불가능
< ex06_string.cpp >
#include <iostream> #include <string> using namespace std; int main(int argc, char const *argv[]) { string s1 = "Slow", s2 = "steady"; // s1은 string 객체의 인스턴스 string s3 = "the race."; string s4; s4 = s1 + " and " + s2 + " wins " +s3; cout << s4 << endl; return 0; }
-
string 클래스
- 문자열 데이터 저장 및 처리 함수(메서드) 제공
- #include <string>을 먼저 지정 후 사용</string>
-
파이썬의 문자열은 조작 불가능 (불변)
-
c++ 문자열은 조작 가능
- s.empty(), s.insert(), s.remove(), s.find(), s.reverse()
< ex07_string.cpp >
#include <iostream> #include <string> using namespace std; int main(int argc, char const *argv[]) { string s1, addr; cout << "name : "; cin >> s1; // enter를 치면 "홍길동\r\n" 입력된다 // \r 입력되면 문자열이 끝났다고 생각함, 홍길동이 s1에 들어간다 // getline은 줄바꿈 문자열이 있을 때까지, \n이 남아있으니 새로운 문자열 받지 않고 자동으로\n을 받는다 // ignore()을 사용하게 되면 \n을 제거하고 쓰라는 뜻 cin.ignore(); // 엔터키 제거 // 주소는 공백이 들어가니 cout << "address : "; getline(cin, addr); cout << addr << "'s " << s1 << " sir hello" << endl; return 0; }
< ex08_string.cpp >
#include <iostream> #include <string> using namespace std; int main(int argc, char const *argv[]) { string s = "when in rome, do as the romans"; int size = s.size(); int index = s.find("rome"); cout << size << endl; cout << index << endl; s. insert(0, "hello"); // 맨 앞에 문자열 추가 cout << s << endl; s += "end of world" // 맨 뒤에 문자열 추가 cout << s << endl; s.append("\n-------------\n"); // 맨 뒤에 문자열 추가 cout << s; return 0; }
-
sizeof(s) -> 항상 32 리턴, 스트링 객체의 크기는 항상 32 바이트
- string 객체의 인스턴스에 데이터가 있다는 것이 아니라 다른 곳에 데이터가 있다는 뜻
- 스택에는 자신의 데이터의 주소를 가지고 있다
- 힙에 실제 데이터 저장, 관리
-
s.size -> 문자열의 사이즈 리턴
- size는 힙에 있는 실제 데이터의 길이를 리턴해주는 것
-
파이썬은 해당 인스턴스가 힙에 만들어진다
-
c++은 실제 데이터의 저장공간이 힙에 만들지 스택에 만들지 선택할 수 있다
-
스트링 객체 내부 관리 데이터의 크기가 32바이트라는 뜻
< ex09_string.cpp >
#include <iostream> #include <string> using namespace std; int main(int argc, char const *argv[]) { string s = "when in rome, do as the romans"; // 읽기 for(auto& ch : s){ // char &ch = s[i], 참조, 속도 더 빠름 cout << ch << ' '; } cout << endl; for (auto ch : s){ // char ch = s[i], 새로운 변수 만들고 값 복사 cout << ch << ' '; } cout << endl; // 읽을 때는 참조변수로 하나 값 복사하나 결과 똑같다 // 쓰기 (참조와 값복사가 다름) for(auto& ch : s){ // char &ch = s[i], 이름만 추가, T를 위한 공간 할당 X, 원본으로 작업 ch = 'T'; } cout << s << endl; for (auto ch : s){ // char ch = s[i], ch를 위한 별도의 메모리 공간을 만들고 운영(1byte), 값 복사 ch = 'W'; // 메모리 공간에 W 입력 } cout << s << endl; // 원본에는 변화 X // 쓰기 작업은 속도의 문제가 아니라 원본을 수정할 것인지 아닌지의 문제 // 속도 자체는 참조변수가 더 빠르다 return 0; }
< ex10_string.cpp >
#include <iostream> using namespace std; int main(int argc, char const *argv[]) { string list[] = {"홍길동", "고길동", "둘리"}; // string list[] -> 지역변수, 스택에 지정 // 배열명 list는 상수이다, 배열명도 스택에 독자적인 메모리 공간을 가진다, 배열명은 배열의 첫 번째 엘리먼트의 주소값을 가진다 (스택), 이 값을 수정할 수 없다 (상수이기 때문에) // 배열1 = 배열2의 표현은 배열명을 바꾸겠다는 표현이기 때문에 불가능하다 // 실제 배열의 데이터는 힙에 있다 for(auto& name : list){ cout << name << endl; } return 0; }
- 내가 지금 작업중인 데이터가 어디에 있냐? 내가 복사본으로 작업하고 있는지 아니면 원본으로 작업하고 있는지 (스택 or 힙) -> 항상 신경쓰기
'C++' 카테고리의 다른 글
04. 클래스와 객체 (0) 2021.01.27 [열혈 C++] 02. C언어 기반의 C++ 2 (0) 2021.01.22 [열혈 C++] 01. C언어 기반의 C++ 1 (0) 2021.01.22 02. 제어와 배열 (0) 2021.01.21 01. C++ 기초사항 (0) 2021.01.21 -