C/C++ 2주차 (19~30강)
#include <stdio.h>
//배열 포인터를 배워보자
int main() {
int arr[3] = { 1,2,3};
printf("arr = %d\n", arr); //14679244
printf("arr + 1 = %d\n", arr+1); //14679248
printf("&arr = %d\n", &arr); //14679244
printf("&arr +1 = %d\n", &arr + 1); //14679256 //왜 12가 더해짐?
//&arr + 1 == &arr에 sizeof(arr)를 더한 값
}
19강. 종합문제
1번. 시험점수 입력하기
// 시험점수 입력해서 출력하기
#include <stdio.h>
int main()
{
int a;
scanf_s("%d", &a);
if (a > 100 || a < 0) {
printf("잘못 입력하셨습니다.\n");
}
else {
if (a >= 90) {
printf("%c\n", 'A');
}
else if (a >= 80) {
printf("%c\n", 'B');
}
else if (a >= 70 ) {
printf("%c\n", 'C');
}
else if (a >= 60) {
printf("%c\n", 'D');
}
else {
printf("%c\n", 'E');
}
}
}
2번. 약수구하기
//자연수를 입력받아 소수를 출력해보자
//약수들은 나눴을 때 나머지가 0이되는 수들
#include <stdio.h>
int main() {
int a;
scanf_s("%d", &a);
for (int i = 1; i <= a; i++) {
if (a % i == 0) { //i가 a의 약수라는 의미
printf("%d, ", i);
}
}
}
쉼표가 안나오게 출력하는 방법
//쉼표가 안나오게 출력하는 방법: for문을 a의 1/2까지만 돌리고, 마지막에 끝값만 따로 프린트
#include <stdio.h>
int main() {
int a;
scanf_s("%d", &a);
for (int i = 1; i <= a/2; i++) {
if (a % i == 0) {
printf("%d, ", i);
}
}
printf("%d\n", a);
}
3번. 일의 자릿수가 3,6,9인 경우 1 2 * 4 5 * 7 8 * ...n까지 출력하기
//1의 자릿수가 3의 배수인 경우 *을 출력
// 1 2 * 4 5 * ... n
#include <stdio.h>
int main() {
int n;
scanf_s("%d", &n);
for (int i = 1; i <= n; i++)
{
if (i % 3 != 0)
printf("%d ", i);
else if (i % 3 == 0)
printf("* ");
}
printf("\n");
}
★4번문제
//입력받은 n을 계단형태로 홀수로만 출력하기
//1
//1 3
//1 3 5
//1 3 5 7
#include <stdio.h>
int main() {
int n,sum;
scanf_s("%d", &n);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
printf("%d ", 2*j - 1);
}
printf("\n");
}
}
5번째 문제
// n=4
/*
1
1 2 3
1 2 3 4 5
1 2 3 4 5 6 7
*/
#include <stdio.h>
int main() {
int n,sum;
scanf_s("%d", &n);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= 2*i-1; j++) { // j<=2*i-1로 해주는 게 중요
printf("%d ", j);
}
printf("\n");
}
}
20강. 배열
- 배열선언 방법1. 배열을 만들어 놓고 값 넣어주기
int arr[5];
for(int i=0; i<=4; i++){
arr[i]=i*5;
- 배열선언 방법2. 배열선언 할 때 값 배정하기
int arr[5] = { 3,1,4,2,5 }; //배열 선언 방법 2
- 배열의 크기는 sizeof()함수로 알 수 있음
#include <stdio.h>
int main(){
int arr[5] = { 3,1,4,2,5 }; //배열 크기를 sizeof(arr)/sizeof(int)로 출력
for (int i = 0; i < sizeof(arr)/sizeof(int); i++) { //20바이트 / 4바이트 ==> 5 배열의 원소를 알 수 있음.
printf("%d ", arr[i]);
}
}
21강. 배열의 활용
- 입력받은 숫자를 거꾸로 출력하기
//입력받은 숫자를 거꾸로 출력
#include <stdio.h>
int main(){
int n;
int arr[1000]; //일단 넉넉하게 배열칸을 만들어 놓고
printf("입력할 숫자의 개수: ");
scanf_s("%d", &n);
for (int i = 0; i < n; i++) {
scanf_s("%d", &arr[i]); //내가 배열에 들어갈 숫자들을 직접 지정
}
for (int i = n - 1; i >= 0; i--) {
printf("%d ", arr[i]);
}
printf("\n");
}
-최댓값 구하기
//최대최소 구하는 문제
#include <stdio.h>
int main(){
int n;
int arr[100]; //일단 넉넉하게 배열칸을 만들어 놓고
scanf_s("%d", &n);
for (int i = 0; i < n; i++) {
scanf_s("%d", &arr[i]); // 3 1 4 2 5
}
int max = arr[0]; //max = 3 저장
for (int i = 1; i < n; i++) { //arr[1] ~ arr[4]까지
if (max < arr[i]) max = arr[i]; //3<4이면 max= 4;
}
printf("%d\n", max);
}
- 최소값을 구할 때는
int min = arr[0]; //max = 3 저장
for (int i = 1; i < n; i++) { //arr[1] ~ arr[4]까지
if (min > arr[i]) min = arr[i]; //3<4이면 max= 4;
}
- 짝수의 개수 구하기
//짝수의 개수
#include <stdio.h>
int main(){
int n;
int arr[100]; //일단 넉넉하게 배열칸을 만들어 놓고
scanf_s("%d", &n);
for (int i = 0; i < n; i++) {
scanf_s("%d", &arr[i]); // 3 1 4 2 5
}
int cnt = 0;
for (int i = 0; i < n; i++) {
if (arr[i] % 2 == 0)
cnt++;
}
printf("%d\n", cnt);
}
22강. 2차원 배열 <- 배열안의 배열
//2차원 배열
#include <stdio.h>
int main() {
int n;
int arr[3][4] = {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
}
★2차원 배열을 for문을 써서 출력할 때 주의해야 할 점이 있음.
2차원배열 | 0 | 1 | 2 | 3 |
0 | arr[0][0] | arr[0][1] | arr[0][2] | arr[0][3] |
1 | arr[1][0] | ... | ||
2 |
i는 바깥쪽 행, j는 안쪽 열로 가게 해서 for문 돌리기
for (int i = 0; i < 3; i++) {
for (int j = 0; i < 4; j++) {
printf("%d ", arr[i][j]);
}
}
printf("\n");
}
★ex) 파스칼의 삼각형
//2차원 배열 - 파스칼의 삼각형
// i행 j열에 있는 숫자는
// [i][j]= [i-1 j-1] + [i-1 j]
#include <stdio.h>
int main() {
int p[10][10];
for (int i = 0; i < 10; i++) {
for (int j = 0; j <= i; j++) {
if (j == 0 || j == i) { // 1C0, 2C0,3C0,,,또는 1C1, 2C2,,,
p[i][j] = 1;
}
else {
p[i][j] = p[i - 1][j - 1] + p[i - 1][j];
}
printf("%d ", p[i][j]);
}
printf("\n");
}
}
23강. 문자열
#include <stdio.h>
int main() {
char arr[100] = "Hello, world!";
printf("%s\n", arr);
}
- 배열의 크기: ['a' ,'b', 'c', '\0'] 이렇게 되니까 배열의 길이는 4
#include <stdio.h>
int main() {
char arr[] = "abc";
printf("배열의크기: %d\n", sizeof(arr) / sizeof(char)); //4
}
- 배열에 문자열 입력받을 때 주의: scanf_s("%s", s, sizeof(s)/sizeof(char)); <-- 크기도 써줘야함.
#include <stdio.h>
int main() {
char s[100];
scanf_s("%s", s,sizeof(s)/sizeof(char)); //string은 scanf입력 받을 때 &안씀.
printf("%s\n", s);
}
string.h를 사용해보자
- strlen(str)함수 --> 문자열의 길이 반환
#include <stdio.h>
#include <string.h>
int main() {
char str[100] = "Hello";
int len;
len = strlen(str); //함수가 반환하는 값 = str의 길이를 len에 저장.
printf("문자열의 길이는: %d\n", len);
}
-strcpy(str2, str1) --> str1의 내용을 str2로 복사
#include <stdio.h>
#include <string.h>
int main() {
char str1[] = "Hello";
char str2[100]; ///그냥 char str[]; 이렇게만은 선언할 수 없음. 빈 배열이라도 크기는 알려줘야함.
strcpy(str2, str1);
printf("str2의 내용: %s\n", str2);
}
-strcat(str, 덧붙일문자열)
#include <stdio.h>
#include <string.h>
int main() {
char str[100] = "Hello";
strcat(str, "World");
printf("%s\n", str);
}
-strcmp(str1, str2) : 두 문자열을 비교, 사전순으로 누가 더 먼저 있는지도
//str1이 str2보다 사전순으로 앞쪽에 있다 --> -1반환
//str1이 str2보다 사전순으로 뒤쪽에 있다 --> 1반환
//str1이 str2이랑 같다. -->0반환
#include <stdio.h>
#include <string.h>
//strcmp : 두 문자열 비교, 사전순으로 누가 먼저 있는지도
int main() {
char str1[] = "sample";
char str2[] = "simple";
int cmp = strcmp(str1, str2);
//str1이 str2보다 사전순으로 앞쪽에 있다 --> -1반환
//str1이 str2보다 사전순으로 뒤쪽에 있다 --> 1반환
//str1이 str2이랑 같다. -->0반환
printf("%d\n", cmp);
}
24강. 변수 가리키기
포인터란(pointer)? 변수의 주소를 저장하는 변수이다.
#include <stdio.h>
//포인터는 변수의 주소를 저장하는 변수
int main() {
int a = 20;
char c = 'h';
int* ptr_a; //가리킬 변수형*ptr_변수이름;
char* ptr_c;
ptr_a = &a; //&는 주소값 , a의 주소값을 ptr_a에 저장.
printf("%d\n", ptr_a);
}
-printf를 이용해 포인터의 다양한 출력값을 이해해보자.
#include <stdio.h>
//포인터는 변수의 주소를 저장하는 변수
int main() {
int a = 20;
int* ptr_a; //포인터 선언, 가리킬 변수형*ptr_변수이름;
ptr_a = &a; //&는 주소값 , a의 주소값을 ptr_a에 저장.
printf("a의 값: %d\n", a);
printf("a의 주소값: %d\n", &a);
printf("ptr_a에 저장된 값: %d\n", ptr_a);
printf("ptr_a가 가리키는 변수의 값: %d\n", *ptr_a); //a == *ptr_a
}
즉
a의 값 = 포인터가 가리키는 변수의 값
a의 주소값 = 포인터에 저장된 값
#include <stdio.h>
//포인터는 변수의 주소를 저장하는 변수
int main() {
int a = 10;
int b = 20;
int* ptr;
ptr = &a;
printf("ptr이 가리키는 변수에 저장된 값: %d\n", *ptr);
ptr = &b;
printf("ptr이 가리키는 변수에 저장된 값: %d\n", *ptr);
}
- *ptr == a와 같다.
#include <stdio.h>
//포인터는 변수의 주소를 저장하는 변수
int main() {
int a = 10;
int* ptr;
ptr = &a;
printf("a의 값: %d\n", a);
*ptr = 20; // a=20; == *ptr=20; 같은 의미임.
printf("a의 값: %d\n", a);
}
<꼭 이해해보기>
#include <stdio.h>
int main() {
int a = 10;
int *ptr; //포인터 ptr을 선언
ptr = &a; //포인터가 a의 주소를 가리키도록 선언
//포인터를 가리키는 포인터를 만들어보자
int **ptr_ptr; //포인터를 가리키는 포인터 ptr_ptr
ptr_ptr = &ptr; //포인터를 가리키는 포인터에는 포인터의 주소를 저장
printf("a = %d\n", a);
printf("&a = %d\n", &a);
printf("ptr = %d\n", ptr); //ptr안에 저장된 a의 주소값
printf("&ptr= %d\n", &ptr); //ptr의 주소값
printf("ptr_ptr= %d\n", ptr_ptr); //ptr_ptr안에 저장된 ptr의 주소값
printf("ptr_ptr= %d\n", *ptr_ptr); //ptr_ptr안에 저장된 값 = ptr
printf("ptr_ptr= %d\n", **ptr_ptr); // **ptr_ptr = a
}
25강. 배열과 포인터와의 관계 이해
//포인터 + 1 = 포인터가 가리키고 있는 형의 크기만큼 더하게됨, int는 4바이트니까 4가 더해짐.
#include <stdio.h>
int main() {
int a = 10;
int *ptr_a = &a;
printf("ptr_a의 값 : %d\n", ptr_a);
printf("ptr_a +1의 값: %d\n", ptr_a + 1);
}
-배열을 선언하면 실제로 주소값은 4바이트씩 차이나는 형태로 할당되어 있음.
#include <stdio.h>
int main() {
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
for (int i = 0; i < 10; i++) {
printf("&arr[%d] = %d\n",i, &arr[i]); //arr의 주소를 출력해보자
}
}
- arr = &arr[0] 이랑 같다
#include <stdio.h>
int main() {
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("arr의 값: %d\n", arr); //arr[0]의 값과 똑같음!
for (int i = 0; i < 10; i++) {
printf("&arr[%d] = %d\n",i, &arr[i]); //arr의 주소를 출력해보자
}
}
//즉 arr == &arr[0] 똑같은 말임.
//arr +1 == &arr[0] +1 == &arr[1]
★즉 arr+i 는 &arr[i]와 같다
arr[i]가 아니라 주소값인 &arr[i]임!!
#include <stdio.h>
int main() {
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
for (int i = 0; i < 10; i++) {
printf("&arr[%d] = %d\n",i, &arr[i]); // &arr[i]와
printf("arr + %d = %d\n", i, arr+i); // arr+i는 출력값이 같다
}
}
//즉 arr == &arr[0] 똑같은 말임.
//arr +1 == &arr[0] +1 == &arr[1]
#include <stdio.h>
int main() {
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
for (int i = 0; i < 10; i++) {
printf("%d ", arr[i]); //1,2,3,4,5,6,7,8,9,10
}
printf("\n");
for (int i = 0; i < 10; i++) {
printf("%d ", *(arr + i)); //arr+i = &arr[i] //*arr[i] : arr[i]값에 들어있는 주소값을 불러와라 .
}
}
★arr[i] = *(arr[i]) = *(arr + i)
세가지 모두 같은 의미임.
-★☆ 배열과 포인터의 관계
#include <stdio.h>
//이 세개의 for문만 이해한다면 배열과 포인터의 관계를 거의 다 파악.
int main() {
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
for (int i = 0; i < 10; i++) {
printf("%d ", arr[i]); //1,2,3,4,5,6,7,8,9,10
}
printf("\n");
for (int i = 0; i < 10; i++) {
printf("%d ", *(arr + i)); //arr+i = &arr[i] //*arr[i] : arr[i]값에 들어있는 주소값을 불러와라 .
}
printf("\n");
for (int *ptr = arr; ptr < arr + 10; ptr++) {
printf("%d ", *ptr);
}
//int *ptr =arr; 포인터를 하나 선언하고 초기값에 arr(&arr[0])을 집어넣어라
// ptr + 1 = arr + 1 = &arr[1]
}
26강. 배열 가리키기 ( 배열 포인터)
- 배열 포인터에 들어가기전.. 배열의 주소 복습
#include <stdio.h>
//배열 포인터를 배워보자
int main() {
int arr[3] = { 1,2,3};
int *ptr = arr; //이건 배열 포인터가 아니라는 점 명심!!
//arr[i] = *(arr[i]) = *(arr+i) = *(ptr+i) = *(i+ptr) == i[ptr]
// *(ptr + i) == i[ptr]
for (int i = 0; i < 3; i++) {
printf("%d", i[ptr]);
}
printf("\n");
}
☆arr[i] = *(arr[i]) = *(arr + i) = *(ptr +i) = *(i +ptr) = i(ptr)
<배운 개념 정리>
1. arr == &arr[0] <=> ptr == &ptr[0]
2. *ptr == ptr[0]
3. ptr + 1 == ptr에 sizeof(*ptr)을 더한 값. EX)100번지 + 1 하면 104번지
- 배열 전체의 주소를 가리키는 기준값은 배열 첫번째 칸인 arr[0]임.
- 배열을 가리키는 포인터에다 + 1하면 sizeof(arr)만큼 더해짐
#include <stdio.h>
//배열 포인터를 배워보자
int main() {
int arr[3] = { 1,2,3};
printf("arr = %d\n", arr); //14679244
printf("arr + 1 = %d\n", arr+1); //14679248
printf("&arr = %d\n", &arr); //14679244
printf("&arr +1 = %d\n", &arr + 1); //14679256 //왜 12가 더해짐?
//&arr + 1 == &arr에 sizeof(arr)를 더한 값
}
- 배열 포인터 ★내용을 잘 숙지
#include <stdio.h>
int main() {
//배열 포인터: 배열 자체를 가리키는 포인터
int arr[3] = { 1,2,3 };
int(*ptr_arr)[3]; //길이 3인 int형 배열을 가리키는 포인터를 선언
ptr_arr = &arr; //포인터 ptr_arr에 배열의 주소값을 할당
//ptr_arr이라는 포인터는 arr[0]의 주소를 가리킴
for (int i = 0; i < 3; i++) {
printf("%d\n", (*ptr_arr)[i]); //배열포인터가 가리키는 i번째 값을 출력 //저번에 했던 거랑 다름
}
}
27강. 2차원 배열과 배열 포인터
- 들어가기 전 2차원 배열 크기, 주소 복습
#include <stdio.h>
int main() {
int arr[2][3] = { {1,2,3,},{4,5,6} };
printf("%d\n", sizeof(arr)); //24 = 4바이트 * 6
printf("%d\n", sizeof(arr[0])); //12 = 4바이트 * 3
printf("%d\n", sizeof(arr[0][0])); //4 = 4바이트 한 칸
printf("%d\n",&arr); //18086112
printf("%d\n", &arr[0]); //18086112
printf("%d\n", &arr[0][0]); //18086112
}
- 2차원 배열과 배열 포인터
/*
1. arr == &arr[0]
2. *arr == arr[0]
3. arr + 1 == arr에 sizeof(*arr)을 더한 값 //ptr로 고쳐도 됨.
*/
#include <stdio.h>
int main() {
int arr[2][3] = { {1,2,3,},{4,5,6} };
int(*ptr)[3] = arr; //★2차원 배열을 가리키는 배열포인터를 선언해서, 거기에 2차원배열을 넣으면 된다.
//1. ptr[i] == arr[i] 맞음.
//2. ptr[i][j] == arr[i][j] 맞음.
// ptr == arr 맞음.
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", ptr[i][j]); //*ptr[i][j]쓰면 오류남
}
printf("\n");
}
}
결론: 2차원 배열에서
1. ptr[i] == arr[i]
2. ptr[i][j] == arr[i][j]
ptr == arr
28강. 포인터 배열
배열 포인터: 배열을 가리키는 포인터
포인터 배열: 포인터들의 배열
예제1.
//배열 포인터: 배열을 가리키는 포인터
//배열포인터: int(*ptr)[4]; 4개짜리 int형 배열을 가리키는포인터
//포인터 배열 : 포인터들의 배열
#include <stdio.h>
int main() {
// 배열포인터: int(*ptr)[4]; 4개짜리 int형 배열을 가리키는포인터
int arr[4] = { 1,2,3,4 };
int *ptr[4]; // 4개짜리 칸 각각 포인터가 됨.
for (int i = 0; i < 4; i++) {
ptr[i] = &arr[i]; //포인터배열 원소안에 arr의 원소 주소가 들어감
}
for (int i = 0; i < 4; i++) {
printf("%d ", *ptr[i]);
}
printf("\n");
}
예제2.
참고
#include <stdio.h>
int main() {
char str[] = "Hello";
printf("%s\n", &str[0]); //&str[0] == str //첫번째만 가리켜 주면 끝까지 출력해주는 printf
}
#include <stdio.h>
int main() {
char strings[3][10] = { "Hello", "World", "Doodle" };
for (int i = 0; i < 3; i++) {
printf("%s\n", strings[i]); //string[i] == &string[i] == &string[i][0]
}
}
예제3.
#include <stdio.h>
int main() {
char strings[3][10] = { "Hello", "World", "Doodle" };
char* p_str[3]; //3개짜리 포인터배열
for (int i = 0; i < 3; i++) {
p_str[i] = strings[i];
}
for (int i = 0; i < 3; i++) {
printf("%s\n", p_str[i] );
}
}
29강-30강. 종합문제
1. 100개 이하의 정수를 입력 받아 첫 줄에 짝수 번째 숫자들을 순서대로 출력하고,
다음 줄에 홀수 번째 숫자들을 순서대로 출력하는 프로그램을 만들어 보세요.
#include <stdio.h>
int main() {
int n;
int arr[105];
scanf_s("%d", &n);
for (int i = 0; i < n; i++) {
scanf_s("%d ", &arr[i]);
}
for (int i = 1; i < n; i+=2) {
printf("%d ", arr[i]);
}
printf("\n");
for (int i = 0; i < n; i+=2) {
printf("%d", arr[i]);
}
printf("\n");
}
2. 코드를 보고 printf에서 뭐가 출력되는 지 맞춰보자.
#include <stdio.h>
int main() {
int a = 10;
int b = 20;
int *ptr; //포인터 ptr 선언
ptr = &a; //포인터 ptr에 a의 주소값 저장, 포인터는 a를 가리킴
*ptr = 30; // a =30;
ptr = &b; //ptr에 b의 주소값 참조, 포인터는 b를 가리킴
*ptr = 10; // b = 10;
printf("%d\n", a); 30
printf("%d\n", b); 10
printf("%d\n", *ptr); 10
}
3. 코드를 보고 어떤 값이 출력될 지 맞춰보자!!
#include <stdio.h>
int main() {
int arr[10] = { 3,1,4,1,5,9,2,6,5,3 };
printf("%d\n", arr); //&arr[0] 인 100번지 출력
for (int i = 3; i < 7; i++) {
printf("%d %d\n", arr + i, *(arr + i)); // 주소값 112, 116, 120, 124,1,5,9,2
}
}
4. 10*10이하의 정수형 이차원 배열을 입력받아 그 배열의 각 행의 요소의 합을 출력하는 프로그램을 만들라
#include <stdio.h>
int main() {
int n, m; //행과 열의 갯수
int arr[12][12];
scanf_s("%d%d", &n, &m);
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
scanf_s("%d", &arr[i][j]);
}
}
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = 0; j < m; j++) {
sum += arr[i][j];
}
printf("%d\n", sum);
}
}
5. 출력값 예측
&arr =100
arr = 100
*arr = 100
&arr[0] = 100
arr[0] =100
*arr[0] =0
&arr[0][0] = 100
arr[0][0] = 0
6. 출력값 예측
&arr[0][0] = 100
arr[0] + 1 =104
&arr[0] + 1 = 112 //&arr[0] == arr
arr+1 = 112
&arr + 1 = 136//&arr는 2차원 포인터 전체