c 난수 생성 함수

C, C++ 2021. 9. 8. 19:05
728x90
728x90
rand() : 0~32767 사이 랜덤한 숫자 반환

프로그램이 생성될 때 정해지는 값이라 진정한 난수가 아님

int rand(void)

 

필요 헤더파일

<stdlib.h> //C
<cstdlib> //C++

 

 

srand()

프로그램 실행 중에(런타임 동안에) 항상 변하는 seed 값을 넣어주어야 한다.

void srand(unsigned int)
srand(time(NULL));

 

필요 헤더파일

<stdlib.h> //C
<cstdlib> //C++

 

 

time()

1970년 1월 1일 0시 0분 0초를 기점으로 현재까지 흐른 시간을 초단위로 나타낸다.

time_t timer = time(NULL);

 

필요 헤더파일

<time.h> //C
<ctime> //C++

 

 

예제

#include <stdio.h>
#include <string.h>
#include <time.h> //time
#include <stdlib.h> //rand

main()
{
 int you;
 int coin;
 char aspect[][10] = {"", "앞면", "뒷면"};
 
 srand(time(NULL)); //난수 생성
 printf("앞면은 1, 뒷면은 2, 종료는 다른 값을 입력하시오\n");
 
 while(1) {
     coin=rand() %2 + 1;
     printf("동전을 던졌습니다 앞면 뒷면 맞추시오 : ");
     scanf("%d", &you);
     
     if(you<1 || you>2) {
         break;
         
     }else {
         printf("사용자: %s 동전: %s\n", aspect[you], aspect[coin]);
         printf("%s\n", (you==coin)?"맞았음":"꽝");
     }
     printf("\n");
 }
  
}
728x90
728x90
블로그 이미지

coding-restaurant

코딩 맛집에 방문해주셔서 감사합니다.

,
728x90
728x90

보안 검사를 해제하지 않고 컴파일 시키면 빌드 오류가 발생
설정 창에서 SDL검사 옵션을 체크 해제하거나
아래 코드를 #include <stdio.h> 위에 추가

 

#define _CRT_SECURE_NO_WARNINGS
728x90
728x90
블로그 이미지

coding-restaurant

코딩 맛집에 방문해주셔서 감사합니다.

,
728x90
728x90
int main()  int main(void) / void main() / main()
메인함수 형태별 차이점

int main()은 여러 매개 변수를 사용하여 호출할 수 있다.
int main(void)매개변수 없이만 호출이 가능하다. C에서 권장.

 

반응형

 

함수 정의 앞에 붙는 데이터형은 함수의 리턴값의 데이터형입니다.
int main() 하면 main() 함수가 종료할때 정수형 값을 리턴하겠다는 뜻이고,
void main() 하면 main() 함수가 종료할때 아무 값도 리턴하지 않겠다는 뜻이며,
main() 하면 void main() 과 같습니다.

main() 함수는 프로그램의 엔트리포인트로서, 운영체제가 실행시켜주는 함수입니다.
따라서 main() 함수의 리턴값은 운영체제가 받아보게되죠.
운영체제는 프로그램이 종료할때 main() 함수의 리턴값을 받아보고 프로그램이 왜 종료되었는가를 판단합니다.

보통의 경우, main() 함수가 0 을 리턴하면 프로그램이 정상적으로 실행을 마치고 종료한것으로 간주하고,
0 이외의 값을 리턴할 경우 비정상적으로 종료된것으로 간주합니다.

 



그러나, 운영체제가 프로그램의 종료사유를 아는것이 사용자 입장에서는 아무 의미가 없는 동작입니다. 그래서 결론적으로, main() 함수가 어떤 값을 리턴하는지는 운영체제에게만 중요할 뿐, 사용자에게는 전혀 중요하지 않습니다.
그러니, int main() 든 void main() 이든 main() 이든 사용자 입장에서는 아무 차이점이 없고, 다만 운영체제의 입장에서는 약간의 의미가 있을수는 있습니다.

참고로, C언어 표준이 제시하는 가장 이상적인 main() 함수의 정의문은 이렇습니다.
int main( int argc, char *argv[], char *env[] )

argc : 배열 argv[]의 크기 (커맨드라인 인수의 개수 +1)
argv[]는 포인터 배열로 되어 있습니다 (예 : test.exe val1 val2 val3)
argv[0] :  프로그램 파일의 경로와 파일명의 문자열을 가리키는 포인터
argv[1] : 첫 번째 커맨드라인 인수의 문자열을 가리키는 포인터
argv[2] : 두 번째 커맨드라인 인수의 문자열을 가리키는 포인터

콘솔프로그램에서 프로그램을 실행시킬 때 관리자모드로 실행시킨다던가,
파일이나 폴더를 만드는데 readonly 권한으로 만들기 등등으로 이해함

 

예제

#include <stdio.h>
#include <string.h>

main(int argc, char *argv[])
{
    int i;

    if (argc <= 1) { // 인수를 지정 안했을 때 
        printf("11");
        return; // 오류방지
    }
    
    if (strcmp(argv[1], "enum") == 0) { //문자열 비교(길이와 함께)
        for (i = 0; i < argc; i++) {
            printf("argv[%d] : %s\n", i, argv[i]);
        }

    }
    else if (strcmp(argv[1], "count") == 0) {
        printf("커맨드라인 인수의 개수 : %d\n", argc-1);
    }    
}

 

참고1 : https://www.hackerschool.org/

참고2 : 알고리즘이 보이는 그림책

 

 

엔트리포인트 (entry point)

엔트리 포인트는 제어가 운영체제에서 프로그램으로 이동하는 것.
프로세서는 프로그램이나 코드에 진입해 실행을 시작한다

프로그램 실행은 main함수에서 시작된다.
그래서 엔트리 포인트는 main 함수라고 불린다.

728x90
728x90
블로그 이미지

coding-restaurant

코딩 맛집에 방문해주셔서 감사합니다.

,
728x90
728x90

strcmp() : 두 문자열이 같으면 0, 다르면 0 외 값 반환
strncmp() : 원하는 길이만큼 같으면 0, 다르면 0 외 값 반환

 

int strcmp(str1, str2);
int strncmp(str1, str2, size_t num);

 

size_t : 해당 시스템에서 어떤 객체나 값이 포함될 수 있는 최대 크기 데이터를 표현하는 타입. 반드시 unsigned 형으로 나타난다. 

 

strlen() : 문자열의 끝 구하기
#include <stdio.h>
#include <string.h>

int main()
{
    int i, n;
    char a[]="DOG";
    char b[10];
    
    n=strlen(a);
    
    for(i=n-1; i>=0; i--) {
        b[n-1-i] = a[i];
    }
    
    b[n]= '\0';
    
    printf("%s를 거꾸로 읽으면 \n%s", a, b);

    return 0;
}
728x90
728x90

'C, C++' 카테고리의 다른 글

보안 경고 #define _CRT_SECURE_NO_WARNINGS  (0) 2021.09.08
메인 함수(엔트리포인트)  (0) 2021.09.08
[c] 파일포인터와 fopen, fclose, fprintf, fgets  (0) 2021.08.30
[C] strcpy, strncpy  (0) 2021.08.27
c++ define 함수  (0) 2021.05.26
블로그 이미지

coding-restaurant

코딩 맛집에 방문해주셔서 감사합니다.

,
728x90
728x90
2차원 배열 이름의 포인터 타입

 

1차원 배열 이름의 포인터 타입 결정 포인트

포인터가 가리키는 요소의 자료형**
포인터 연산 시 증가하는 바이트의 크기
- 한 번 읽어들일 때 읽어들일 크기..

 

1차원 배열 이름

배열 이름이 가리키는 요소의 자료형이 일치한다면 포인터연산 시 증가하는 값의 크기도 일치
그래서 1차원배열 이름의 경우 가리키는 요소만 참조했다

 

다차원배열의 포인터 타입 결정 포인트

-2차원배열이라고 생각해서 이해해보자
포인터가 가리키는 요소의 자료형**
포인터 연산 시 증가하는 바이트의 크기

 

2차원 배열 이름

포인터가 가리키는 요소의 자료형이 일치해도 포인터연산 시 증가하는 값의 크기가 불일치
포인터 연산 결과도 생각해야 한다

 

2차원배열의 이름 특성 이해
#include <stdio.h>

int main()
{
    int a[3][2]={1,2,3,4,5,6};
    
    printf("a[0] : %d\n", a[0]);
    printf("a[1] : %d\n", a[1]); // 8바이트 증가
    printf("a[2] : %d\n", a[2]);
    printf("a    : %d\n", a); // a[0]주소값과 같다
    
    return 0;
}

 

 

배열의 이름으로 포인터연산을 해보면 역시 행 단위로 건너뜀을 알 수 있다.

#include <stdio.h>

int main()
{
    int a[3][2]={1,2,3,4,5,6};
    
    printf("a    : %d\n", a); 
    printf("a+1  : %d\n", a+1); 
    printf("a+2  : %d\n", a+2); 
    
    return 0;
}

 

 

결론 1 : 2차원 배열 이름의 특성
a[i] == *(a+i)
// 배열의 이름이든 포인터든
// 몇차원 배열이든 언제나 성립하는 공식

 

a[i] == *(a+i) 
// a+i와 *(a+i) 가 가리키는 영역은 같으나
// 어디까지 가르키는지에 따라 sizeof 연산을 하면 다르다
// a[i]과 *(a+i)는 같은 거 맞다

 

 

** 아래 실행 결과가 강의랑 다름. 확인 필요

#include <stdio.h>

int main()
{
    int a[3][2]={1,2,3,4,5,6};
    
    printf("a    : %d\n", a); 
    printf("a+1  : %d\n", a+1); 
    printf("a+1  : %d\n", sizeof(a+1)); 
    printf("a+1  : %d\n", sizeof(a[1])); 
    printf("a+2  : %d\n", a+2); 
    
    printf("a    : %d\n", *(a+0));
    printf("a+1  : %d\n", *(a+1)); 
    printf("a+1  : %d\n", sizeof(*(a+1))); 
    printf("a+2  : %d\n", *(a+2)); 
    
    return 0;
}

 

결론 2 : 2차원 배열 이름의 특성

2차원배열 이상의 포인터 타입 구성

- 가리키는 대상의 자료형
- 포인터 연산 시 증가하는 바이트의 크기

#include <stdio.h>

int main()
{
    int arr1[3][2];
	
    int arr2[2][3];
    //int (*p)[3]; 포인터를 선언한다면
    
    printf("arr1    : %d\n", arr1); 
    printf("arr1+1  : %d\n", arr1+1);
    printf("arr1+2  : %d\n", arr1+2); 
    
    printf("arr2    : %d\n", arr2); 
    printf("arr2+1  : %d\n", arr2+1);
    printf("arr2+2  : %d\n", arr2+2); 
    
    return 0;
}

 

2차원 배열 이름에 일치하는 포인터 선언
int arr[2][4];
// arr의 포인터타입을 적용해 만든 변수
int(*pArr)[4]; //4블럭 건너뛴다
//포인터 타입은 가리키는 요소가 int형 데이터이고
//포인터 연산 시 증가하는 값의 크기(4), 즉 16바이트에 해당이된다

가리키는 정보 왼쪽, 증가하는 데이터 오른쪽

예제

#include <stdio.h>

void show_data(int (*ptr)[4], int a);

int main()
{
    // 4칸씩 건너뛴다
    int arr1[2][4]={1,2,3,4,5,6,7,8};
    int arr2[3][4]={{1}, {2}, {3}};
    
    show_data(arr1, 2);
    show_data(arr2, 3); 
    
    return 0;
}

void show_data(int (*ptr)[4], int a)
{
    int i, j;
    
    printf("---start print---\n");
    
    for(i=0; i<a; i++) {
        
        for(j=0; j<4; j++) {
            printf("%d", ptr[i][j]);
        }
        
        printf("\n");
    }
    
}

 

매개변수로 선언되는 포인터의 또 다른 표현

매개변수로 선언되었을 때만 두 표현이 같아진다.
가독성 좋으라고 허용하는 표현이다.

// 같은 표현
void show_data(int (*ptr)[4], int a);
void show_data(int ptr[][4], int a);
int arr1[2][4]={1,2,3,4,5,6,7,8};
int (*ptr1)[4]=arr1; //ㅇㅋ
int ptr2[][4]=arr1; //에러 (매개변수가 아닌 지역변수로 선언, 값을 빼먹었다고 생각)

 

int* pArr[4]  vs  int (*pArr)[4] 의 차이점

형태는 괄호에 차이가 있다. 

int* pArr[4]  : pArr은 배열인데 int형 싱글포인터를 요소로 지니는 길이가 4인 배열 (포인터배열)
int (*pArr)[4] : int형 요소를 가리키고 포인터 연산 시 4칸씩 건너뛰는 포인터 (배열포인터)

 

각각 16바이트, 4바이트 할당

 

 

다양한 형태의 배열 요소 접근 방법
#include <stdio.h>

int main()
{
    int a[3][2]={{1,2},{3,4},{5,6}};
    
    printf("a[0]   : %d\n", a[0]);
    printf("*(a+0) : %d\n", *(a+0)); 
    
    printf("a[1]   : %d\n", a[1]); 
    printf("*(a+1) : %d\n", *(a+1)); 
    
    printf("a[2]   : %d\n", a[2]);
    printf("*(a+2) : %d\n", *(a+2)); 
    
    printf("%d, %d\n", a[1][0], (*(a+1))[0]);
    printf("%d, %d\n", a[1][0], *(a[1]+2));
    printf("%d, %d\n", a[1][0], *(*(a+2)+1));
    
    return 0;
}


a[i] == *(a+i)
a[1][0] == (*(a+1))[0]

a[1][2] == *(a[1] + 2)
A = a[1]
A[2] == *(A+2)

 

728x90
728x90
블로그 이미지

coding-restaurant

코딩 맛집에 방문해주셔서 감사합니다.

,
728x90
728x90
포인터의 포인터 (더블포인터)

싱글포인터의 주소값을 저장하는 용도의 포인터

double **ptr2 = &ptr1; //더블포인터

더블포인터의 주소값은 ***로 표현하는데 거의 안쓴다.

double **ptr2 = &ptr1; //더블포인터
double ***ptr3 = &ptr2;

개인적 의문) 포인터의 끝은 어딘거지..?

 

더블포인터에 의한 Call-By-Reference 예제

포인터가 가리키는 대상을 서로 바꾸는 swap으로
아래는 효과없는 swap 함수의 호출 예제이다.

#include <stdio.h>

int main()
{
    int A = 10, B=20;
    int* pA, *pB;
    pA=&A, pB=&B;
   
    pswap(pA, pB);
   
    // 호출 후
    printf("pA가 가리키는 변수 : %d\n", *pA);
    printf("pB가 가리키는 변수 : %d\n", *pB);
   
    return 0;
}

// pA, pB 주소값이 p1, p2로 전달된다
// 우리는 p1, p2가 아니라 pA, pB가 가리키는 대상이
// 바뀌어야 하므로 잘못된 예
void pswap(int* p1, int* p2) 
{
    int* temp;
    temp=p1;
    p1=p2;
    p2=temp;
}

무조건  포인터가 갔다고 call-by-reference이지 않다. 상대적인 것이다.

 

 

 

더블포인터 입장에서의 진정한 swap의 예
#include <stdio.h>

int main()
{
    int A = 10, B=20;
    int* pA, *pB;
    pA=&A, pB=&B;
   
    pswap(&pA, &pB); //주소값을 바꿔준다
   
    // 호출 후
    printf("pA가 가리키는 변수 : %d\n", *pA);
    printf("pB가 가리키는 변수 : %d\n", *pB);
   
    return 0;
}
 
void pswap(int** p1, int** p2) 
{
    int* temp;
    temp=*p1;
    *p1=*p2;
    *p2=temp;
}

 

 

포인터 배열과 포인터 타입

1차원 배열의 경우 배열이름이 가리키는 대상을 통해 타입이 결정된다.
(2차원 배열은 달라지는데 다음 단원에서 다룰 것)
포인터 배열도 마찬가지이다.

// 포인터 변수 배열의 예
int* arr1[10]; // int형 변수이고 int형 포인터를 가리키니까 int형 더블포인터
double* arr2[20]; 
char* arr3[30];

 

포인터는 언제 사용되는가

함수 내에서 데이터 조작
메모리 동적 할당
자료구조 구현

728x90
728x90
블로그 이미지

coding-restaurant

코딩 맛집에 방문해주셔서 감사합니다.

,
728x90
728x90
다차원 배열 : 2차원 이상의 배열
다차원배열 선언
int arr[100] // 40바이트 할당, 1차원배열, 선
int arr[10][10] // 10*10, 2차원배열, 면
int arr[5][5][5] // 5*5*5, 3차원배열

 

2차원배열의 선언 : 2차원적 메모리 구조를 구성

12개*4바이트 = 48바이트로 구성되는 배열이 만들어짐.

2차원 배열 요소 접근 방법
#include <stdio.h>

int main()
{
    int arr[3][3];
    arr[0][0]=2; // 첫 번째 요소
    arr[1][0]=4; // 두번째 행 첫번째 요소
    arr[2][2]=8; // 마지막 요소
    

    return 0;
}

 

예제

#include <stdio.h>

int main()
{
    int somang[4][2];
    //int somang[8]; 1차원배열로 바꿀 경우도 생각해 볼 것
    int i,j;
    int popu;
    
    // 가구별 거주인구 입력
    for(i=0; i<4; i++) {
        for(j=0; j<2; j++) {
            printf("%d 층 %d 호 인구 입력 : ", i+1, j+1);
            scanf("%d", &somang[i][j]);
        }
    }
    
    // 소망빌라 층별 인구 수 출력
    for(i=0; i<4; i++) {
        popu=0;
        for(j=0; j<2; j++) {
            popu+=somang[i][j];
        }
        printf("%d 층 전체 인구 : %d \n", i+1, popu);
    }
    
    return 0;
}

 

다차원 배열의 실제 메모리 구성

1차원 배열과 동일하나 ** 접근 방법을 2차원적으로 해석할 뿐이다 **
2차원적으로 이해하는 습관을 가지자.
(시스템의 메모리구조는 1차원적이라 플랫하게 할당되긴 한다)

 

 

2차원배열 선언과 동시에 초기화
// 행 단위로 모든 요소를 초기화
int somag[3][3]={
	{1,2,3},
	{4,5,6},
	{7,8,9},
};

// 행 단위로 일부 요소만 초기화
// 나머지는 0으로
int somag[3][3]={
	{1},
	{4,5},
	{7,8,9},
};

// 1차원 배열 형태의 초기화
int somag[3][3]={1,2,3 4,5,6 7}; 
// 문법적으로는 가능하나 비추
// 내부중괄호를 활용할 것

 

초기화 리스트에 의한 배열 크기의 결정

1차원 배열의 예

int arr[] = {1,2,3,4,5};

2차원 배열의 예

int arr[][] = {1,2,3,4,5,6,7,8}; //에러
int arr[][4] = {1,2,3,4,5,6,7,8}; 
int arr[][2] = {1,2,3,4,5,6,7,8};

 

3차원 배열의 선언과 의미

3차원적 메모리 구조를 의미
일반적으로 필요 앖고 개념만 이해할 것

int a[3][3][3]

 

 

연습문제

1. 가로의 길이가 9, 세로의 길이가 3인 int형 2차원 배열을 선언하여 구구단 2,3,4단을 저장 후 출력하라 (흰트 : 2중 for문)

더보기
#include <stdio.h>

int main()
{
    
    int arr[3][9];
    //2,3,4단 출력
    for(int i=0; i<3; i++){
        for(int j=0; j<9; j++) {
            // 0 + 2, 3, 4
            arr[i][j] = (i+2)*(j+1); //구구단 결과값
            printf("%d x %d = %d\n", i+2, j+1, arr[i][j]);        
        }
    }

    return 0;
}

 

2. 생략, 

3. 3명의 학생 국영수 3 과목의 점수를 입력한 후 4행에는 각 과목의 총점,
4열에는 각 학생 총점을 계산하는 프로그램을 제작해라.

더보기

https://karen0117.tistory.com/52 참고

#include <stdio.h>

int main()
{
    
    int arr[4][4];
    // 행은 과목
    // 열은 사람
    
    int studentTotal;
    int subjectTotal;
    int total = 0;
    
    // 학생별 정보 입력
    for(int i=0; i<3; i++) {
        studentTotal=0;
        
        printf("%d 번째 학생의 점수를 입력하시오\n", i+1);
        
        // 과목별 성적 입력
        for(int j=0; j<3; j++) {
            scanf("%d", &arr[i][j]);
            studentTotal += arr[i][j];
        }
        
        arr[i][3] = studentTotal; //학생별 총점
        total += studentTotal;
        //printf("%d\n",  arr[i][3]);
    }
    
    // 과목별 총점
   for(int i=0; i<3; i++) 
   {
        subjectTotal=0;
        
        for(int j=0; j<3; j++) {
             subjectTotal +=  arr[j][i];
        }
        //마지막에 대입
        arr[3][i] = subjectTotal;
    }
    arr[3][3] = total;
    
    
    // 합쳐서 보여주는 부분
    for(int i=0; i<4; i++) {
        for(int j=0; j<4; j++) {
            printf("%d", arr[i][j]);
        }    
        printf("\n");
    }


    return 0;
}

 

728x90
728x90
블로그 이미지

coding-restaurant

코딩 맛집에 방문해주셔서 감사합니다.

,
728x90
728x90
format()

자리 표시자는 이름붙여진 인덱스{price}, 번호가 매겨진 인덱스{0} 또는 빈 자리 표시자 {}를 사용하여 식별할 수 있다.
중괄호를 찾아가서 배치된다.

age=20
intro="이름은 길동.나이는 {}살입니다"
print(intro.format(age))
wage2020=8590
wage2021=8720
result = wage2021-wage2020
print("2020 최저임금은 {} 원입니다.".format(wage2020))
print("2021 최저임금은 {} 원입니다.".format(wage2021))
print("두 해의 차이는 총 {} 원입니다.".format(result))
// 한 줄에 쓰기
wage2020=8590
wage2021=8720
result = wage2021-wage2020
print("""2020 최저임금은 {} 원입니다.
2021 최저임금은 {} 원입니다.
두 해의 차이는 총 {} 원입니다.""".format(wage2020,wage2021,result))
wage2020=8590
wage2021=8720
result = wage2021-wage2020
# print("""2020 최저임금은 {} 원입니다.
# 2021 최저임금은 {} 원입니다.
# 두 해의 차이는 총 {} 원입니다.""".format(wage2020,wage2021,result))

print("""2020 최저임금은 {2} 원입니다.
2021 최저임금은 {1} 원입니다.
두 해의 차이는 총 {0} 원입니다.""".format(result,wage2021,wage2020))
item="마우스"
quantity=12
item_price=59_000
total_price=quantity*item_price

myorder="{2}원인 {0}의 {1}개에 대한 총 금액은 {3}원입니다."

print(myorder.format(item,quantity,item_price,total_price))
name="길동"
age=27

print("이름은 {0}입니다. {0}의 나이는 {1}세".format(name,age))
my_car="제 차는 {car}이고 색은 {color}"

print(my_car.format(car="트럭", color="용달블루"))
pi=3.141592653589793
txt="원주율은 원 둘레와 지름의 비이고 값은 {:.2f}다"
#둘째자리까지만 출력
print(txt.format(pi))

 

print("hello {:<10} python".format(23))
#10개의 공백 출력 
print("text {0:>20} ".format("샘플"))

print("{0:<10}".format("LEFT")) #왼쪽으로 붙어서 출력 
print("{0:>10}".format("RIGHT")) #10칸 뛰고 우측으로  붙어서 출력 
print("{0:_^10}".format("가운데")) #중앙
print("{0:@^10}".format("가운데")) #중앙



 

서식지정자 %
print("정수형데이터는 %d, 문자형데이터는 %s, 실수형데이터는 %f" %(100, "문자열", 0.54));
#정수형데이터는 100, 문자형데이터는 문자열, 실수형데이터는 0.540000
print("score:%010d" %100)
#score:0000000100
a=0.45 
print("%f입니다"%a)
print("%.2f입니다"%a) #둘째자리까지
print("%.1f입니다"%a) #5보다 작으면 버림

#0.450000입니다
#0.45입니다
#0.5입니다

 

format() 메서드가 가독성과 사용성이 더 편리하긴 하다.

728x90
728x90
블로그 이미지

coding-restaurant

코딩 맛집에 방문해주셔서 감사합니다.

,
728x90
728x90
변수 : 여러 데이터를 담을 컨테이너



age = 29 #age라는 변수를 만들고 값을 할당한다
print(age)

age = age + 1 #할당
print(age)

 

x=3
# y=2x+1 에러
y=2*x+1

print(y)

 

 

자동 자료형 할당; 동적 타이핑 언어
age = 20
print(type(age))

 

변수의 주소값 : id

메모리에 저장되어 있는 변수의 물리적인 위치

age = 20
print(id(age))

 

같은 변수에 다른 문자열을 넣을 수 있다.

 

형변환
height= 185.4
print(int(height)) #185

num = "1234";
print(int(name)) #1234

문자열은 대부분 변환되지 않는다.
문자열 내부구조가 숫자로 이루어졌을 때에만 형변환된다.

 

input()  : 변수의 값을 입력받아서 출력

입력되는 모든 것은 문자열로 취급

변수명 = input(출력 유도문구)
name = input("이름입력\n")
print(name)

 

num1 = int(input("숫자입력\n"))
print(num1+1)

num = input("숫자입력\n")
print(int(num)+1)

 

반응형

 

데이터 들여다보기

정수는 양의정수, 0, 음의정수가 있다. 
큰 수는 언더바를 사용해서 가독성을 높일 수 있다.

num=1_000_000 #가능

정수와 실수를 더하면 결과는 실수다.

num1=123412341234
num2=0
num3=-123412341234

a=1000000
b=1_000_000

print(num1,num2,num3)
print(a==b) #같은지 확인
print(a!=b)

 

논리형데이터가 결과로 나온다.

파이썬은 단일문자 데이터타입이 없고 문자열 데이터타입밖에 없다.
앞에서부터 한글자씩 0부터 순번을 매긴다.

a="hello, python"

print(a[0]) #h

 

len(), find(), not in, in
text="love you"
index = text.find("v")

print(len(text)) #8(공백 포함)
print(index) #2
print('h' not in text) #없으면 true

 

upper : 문자열의 모든 문자를 대문자 변경
text="love you" 
big_text = text.upper()
print(big_text) #LOVE YOU
print(big_text.lower()) #love you

 

slice : x인덱스부터 y인덱스 직전까지
text="love you" 

print(text[3:5]) #e

 

replace : 문자열바꾸기
text="love you" 

print(text.replace("you", "me")) #love me

 

split : 문자열쪼개기
text="l.o.v.e" 

print(text.split(".", 2)) #['l', 'o', 'v.e'] #리스트

#공백을 기준으로 자르기
#print(text.split())

 

 

논리형 데이터 - 참 / 거짓 bool

print(1==1) #true
print(1!=2) #true
print(1<=1)#true
num=200
print(isinstance(num,int)) #true

 

and, or, not
print(bool(0)) #bool형으로 형변환, false 출력
print(bool(1))
print(int(False))
print(int(True))
print(bool(None))

 

728x90
728x90
블로그 이미지

coding-restaurant

코딩 맛집에 방문해주셔서 감사합니다.

,
728x90
728x90
산술연산자

정수 : int, 실수 : float
거듭제곱 : **
나눈 몫 : //

print("3+1=", 3+1)
print(3-1)
print(-12-1)
print(-2*1)
print(13/2)
print(2**4)
print(15//2) #몫
print(15%2) #나머지

 

print(16*2**-3) #2.0

 

2진수로 계산해서 근사값을 주기 때문에 이렇게 나올 때가 있다.
실수의 연산은 소수점 아래 15자리까지 출력한다.

print(3.5+1.3) 
print(1.4-0.1) 
print(2.6*7.1)

 

사칙연산 순서로 괄호, 나눗셈과 곱셈, 덧셈과 뺄샘 순으로 실행된다

print(1+2-3*4/5)

 

 

728x90
728x90
블로그 이미지

coding-restaurant

코딩 맛집에 방문해주셔서 감사합니다.

,
728x90
728x90
내 손으로 파이썬! 에디터에서 실습하며 하룻밤에 끝내는 파이썬 정복

 

출력과 주석
print("hello, python")
print(1+3j);

#주석
"""
여러줄
여러줄
여러줄
"""

파이썬에서 복소수는 i가 아닌 j를 쓴다

 

문자열 출력
print("hello, python")
print('hello, python')
print(123+1)
#print('123' +1) #에러

print('i\'d like') #이스케이프

 

문자열연산
print("더하면" + "붙어요")
print("*" * 10) #반복출력
# 문자열과 문자열을 곱할 수는 없다

 

print()  함수의 옵션
print("hello, python")

#help()
#기능설명
help(print)

 

콤마( , )는 서로다른 문자열 구분을 위해 사용한다. 기본적인 띄어쓰기를 제공.
한 개의 데이터인지, 여러 개의 데이터인지가 다르다.

print("hello python")
print("hello", "python") 
#둘 다 hello python 출력
#두 코드는 하나의 문자열, 두개의 문자열로 이루어진 점이 다르다

 

 

 

 

사이사이에 넣어주기

print("hello", "you", sep = "...")
print("hello", "you", sep = " fuck ")

 

문자열이 끝나고 나서 붙이기

print("hello", end="\n")  #생략된 것, 개행문자
print("hello", end="python")  #뒤에 붙고 개행이 실행되지 않는다

 

로스트링, 익스케이프 코드 비활성화 (프로그램 경로 표시 등에 쓰임)

print("\"" )   
print(r"\"" )   #역슬래시 비활성화

 

멀티라인기법

print("청춘은 청춘에서만 들어 것이다. 보배를 같은 너의 운다. 만천하의 실로 들어 심장은 것이다. 풀이 이것이야말로 곳으로 안고, 있는 있는가? 같이 살았으며, 위하여 가지에 봄날의 같이, 수 교향악이다. 주며, 얼음 얼음에 너의 이상은 바이며, 동력은 얼마나 속에서 이것이다. 품으며, 봄바람을 유소년에게서 것이다. 귀는 시들어 노래하며 것이다. 산야에 같이 불러 원질이 끓는 황금시대를 있으랴? 우리의 피고, 천하를 불러 이것이야말로 안고, 끓는 힘있다.

맺어, 부패를 길지 풀밭에 때에, 그들에게 위하여 봄바람을 보라. 곧 이상의 남는 황금시대다. 봄바람을 거선의 안고, 구하지 웅대한 풀이 곳이 부패뿐이다. 같으며, 피부가 이 구하지 용기가 예가 피다. 별과 얼마나 우는 이상 석가는 그들의 생생하며, 우리 약동하다. 끝까지 소금이라 곳으로 교향악이다. 앞이 이 온갖 불어 인류의 이것이다. 것이다.보라, 많이 꽃이 어디 대중을 있다. 가는 얼마나 열락의 그것은 얼음이 생의 인간의 황금시대의 찬미를 위하여서. 내려온 할지라도 힘차게 뛰노는 것이다.

따뜻한 않는 위하여 인간의 충분히 이 만천하의 황금시대다. 작고 천지는 가장 그들의 청춘의 그리하였는가? 보배를 열매를 고동을 것이다. 청춘의 풀이 무엇을 시들어 이것이야말로 인간의 이것이다. 천지는 불러 가슴에 그들의 이상은 만천하의 위하여 칼이다. 청춘의 설레는 천고에 아니한 놀이 인생을 우리의 사막이다. 공자는 길지 용기가 때까지 옷을 찾아다녀도, 있다. 이는 봄바람을 불러 사막이다. 아니한 무엇을 우리 창공에 있는 사랑의 하는 인간의 끓는 뿐이다." )   

#error

역슬래시와 함께 줄을 바꾸거나 큰따옴표로 감싸준다.

print("청춘은 청춘에서만 들어 것이다. \
보배를 같은 너의 운다. 만천하의 실로 들어 심장은 것이다.\
 풀이 이것이야말로 곳으로 안고, 있는 있는가? 같이 살았으며 " )  
   
 print("청춘은 청춘에서만 들어 것이다."
"보배를 같은 너의 운다. 만천하의 실로 들어 심장은 것이다."
 "풀이 이것이야말로 곳으로 안고, 있는 있는가? 같이 살았으며 " )

 

 

728x90
728x90
블로그 이미지

coding-restaurant

코딩 맛집에 방문해주셔서 감사합니다.

,
728x90
728x90
이번 단원에 알아두어야 할 핵심개념 : call-by-reference, call-by-value

 

함수의 인자로 배열 전달하기

기본적인 인자 전달 방식 : 값의 복사에 의한 전달

정확히는 val을 전달하는 게 아닌, val이 지니고 있는 값을 전달
'복사'해서 a를 초기화하고 있다.

 

배열의 함수 인자 전달 방식 : 배열이름(배열주소, 포인터)에 의한 전달

배열전체를 복사하여 함수의 인자로 넘길 수는 없다 (나중에 구조체로는 가능)
그래서 주소값만 복사해 전달하여 사용한다.

배열 전달의 예

#include <stdio.h>

void fct(int *arr2);

int main ()
{

  int arr1[2] = { 1, 2 }; //arr1 배열이름이자 포인터는 int형 포인터, 주소를 가리킨다

  fct (arr1); // arr1이 지닌 주소값을 배열의이름으로 전달하면서 fct 함수를 호출하면서 전달한다
  printf ("%d\n", arr1[0]);

  return 0;
}

void fct(int *arr2) 
{
    // arr2는 arr1의 주소값을 받는다
    // int형 변수의 주소값이기 때문에 int형 포인터여야 한다 **
    printf("%d\n", arr2[0]); 
    // *(arr2+0)와 같은 문장...
    // *(arr2+0)이라는 주소값이 가리키는 메모리공간을 참조하라
    // 1 출력
    
    arr2[0]=3;
    // *(arr2+0) = 3; 과 같은
}

 

 

배열이름, 포인터의 sizeof 연산

배열이름 : 배열전체 크기를 바이트로 반환
포인터 : 포인터의 크기를 바이트로 반환

#include <stdio.h>

int main()
{
    int arr[5];
    int* pArr=arr;
    
    printf("%d\n", sizeof(arr)); //배열 이름 : 배열전체 크기를 바이트단위로 반환 (20)
    printf("%d\n", sizeof(pArr)); // 포인터의 크기를 바이트단위로 반환(4 or 8)
    //printf("%d\n", sizeof(*pArr)); //4
     
    printf("%d\n", sizeof(int)); // 4byte
    
    return 0;
}

 

배열의 길이는 인자로 전달받은 함수 내에서 계산이 불가능하고
함수를 호출할 때 아래처럼(sizeof(배열)/sizeof(자료형) 계산하여 전달을 해야 한다...

#include <stdio.h>

int ArrAdder(int* pArr, int n);

int main()
{
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    int SumOfArr;

	// 배열의 길이가 바뀌어도 아래 코드는 그대로 쓸 수 있다.
    SumOfArr = ArrAdder(arr, sizeof(arr)/sizeof(int));
    // SumOfArr = ArrAdder(arr, 10); //하드코딩
    // sizeof(int) int의 크기는 시대에 따라 다를 수 있다
    
    printf("배열의 길이체크 : %d\n", sizeof(arr)); //40
    printf("배열의 총 합 : %d\n", SumOfArr); 
    
    return 0;
}

//배열의 시작번지, 배열의 길이
int ArrAdder(int* pArr, int n)
{
    int sum = 0;
    int i;
    
    // n 대신 sizeof(pArr)를 쓰면 배열의 길이가 아니고 포인터 크기가 반환
    for(i=0; i<n; i++)
        sum+= pArr[i];
    
    return sum;
}

 

 

int* pArr vs int pArr[ ]

int* pArr을 많이 쓰기를 권해드림. 배열과 포인터를 혼동하기 때문이다.
둘은 같은 의미이나, 선언 int pArr[ ] 은 함수의 매개 변수 선언 시에만 사용 가능
매개변수 선언 시가 아니면 불가

// int function(int* pArr)
// 변수의 주소값 전달인지, 배열의 이름 전달인지 알수가 없다

// 배열이 인자로 전달됨을 알 수 있다 -- 의미명확
// 매개변수 선언 시 아래 방식을 선호한다

// 배열의 이름이 아니고 진짜 포인터다
// sizeof 연산 시 포인터 크기가 나온다
int function(int pArr[]) 
{
	int a = 10;
	pArr = &a;
	return *pArr;
}

 

배열이 갖고있는 요소 중 최대값을 반환하는 예

#include <stdio.h>

int MaxVal(int pArr[], int n);

int main(void)
{
    int arr[10] = {4,8,3,7,2};
    int max;

    max = MaxVal(arr, sizeof(arr)/sizeof(int));
    printf("최대값 : %d\n", max); 
    
    return 0;
}

// 배열의 시작번지, 배열의 길이
// int pArr[]은 포인터변수
// int MaxVal(int *pArr, int n)
 int MaxVal(int pArr[], int n) 
{
    int max, i;
    
    printf("sizeof(pArr): %d\n", sizeof(pArr));

    max=pArr[0];    
    for(i=1; i<n; i++)
        if(max<pArr[i])
            max=pArr[i];
    
    return max;
}
#include <stdio.h>

int MaxVal(int pArr[], int n);

int main(void)
{
    int arr[10] = {4,8,3,7,2};
    int max;
	
    //int *p;
    //int p[]; //error - 배열 선언인데 size 생략했다고 판단됨
    
    max = MaxVal(arr, sizeof(arr)/sizeof(int));
    printf("최대값 : %d\n", max); 
    
    return 0;
}

// 배열의 시작번지, 배열의 길이
// int pArr[]은 포인터변수
// int MaxVal(int *pArr, int n)
 int MaxVal(int pArr[], int n) 
{
    int max, i;
    
    printf("sizeof(pArr): %d\n", sizeof(pArr));

    max=pArr[0];    
    for(i=1; i<n; i++)
        if(max<pArr[i])
            max=pArr[i];
    
    return max;
}

 

 

Call-By-Value

값의 복사에 의한 함수의 호출
call : 함수 호출을 뜻함
가장 일반적인 함수 호출 형태

#include <stdio.h> 

int add(int a, int b);

int main() 
{ 
    int val1 = 10;    
    int val2 = 20;
    
    printf("결과: ", add(val1, val2)); 
    //call by value
    
    return 0; 
}

// 복사
int add(int a, int b)
{
    // val1과 다른 변수
    return a+b;
}

 

call-by-value에 의한 swap

swap함수 : 서로 바꾸는 기능을 하는 것
가짜 swap? 찐 swap은 val2와 val1의 진짜 값이 변경됨
직접적으로 val1, val2의 값을 바꿀 수 없고, 코드 실행 후에도 그대로이다.

#include <stdio.h>

int main()
{
    int val1=10;
    int val2=20;
    swap(val1, val2);
    
    printf("val1 : %d\n", val1);
    printf("val2 : %d\n", val2); 

    return 0;
}

void swap(int a, int b)
{
    int temp=a;
    a= b;
    b=temp;
    
     printf("a : %d\n", a); 
     printf("b : %d\n", b); 
}

 

note : previous implicit declaration of 'swap' was here swap(...
묵시적 선언 오류 : 함수 선언을 하지 않고 먼저 사용했다는 뜻.

묵시적 선언 오류 수정 후

#include <stdio.h>

void swap(int a, int b);

int main()
{
    int val1=10;
    int val2=20;
    swap(val1, val2);
    
    printf("val1 : %d\n", val1);
    printf("val2 : %d\n", val2); 

    return 0;
}

void swap(int a, int b)
{
    int temp=a;
    a= b;
    b=temp;
    
     printf("a : %d\n", a); 
     printf("b : %d\n", b); 
}

 

 

call-by-reference

참조(참조를 가능케하는 주소값)를 인자로 전달하는 형태의 함수 호출
main함수 내 지역변수에 접근할 수 있었다.

#include <stdio.h>

int main()
{
    int val = 10;
    
    adder(&val);
    // val의 주소 전달
    
    printf("val: %d", val);
    // 11 출력

    return 0;
}

void adder(int* pVal)
{
    // val의 주소값이 전달됨 (Ox10 등..)
    
    // 포인터변수 pVal이 가리키는 변수의 값 1 증가
    (*pVal)++;
}

 

call-by-reference에 의한 swap
#include <stdio.h>

int main()
{
    int val1 = 10;
    int val2 = 20;
    
    printf("before val1: %d\n", val1);
    printf("before val2: %d\n", val2);
    
    swap(&val1, &val2); //주소전달
    
    printf("After val1: %d\n", val1);
    printf("After val2: %d\n", val2);

    return 0;
}

void swap(int* a, int* b)
{
    int temp = *a;
    *a=*b;
    *b=temp;
}

 

 

call-by-value는 값을 전달 / call-by-reference는 주소 값을 전달하는 함수 호출이다.
call-by-value는 값을 복사해 전달해서 다른 메모리공간을 접근, 값을 변경할 수 없고
call-by-reference는 주소값을 전달해서 주소값에 해당하는 메모리공간에 접근 가능하다.

 

scanf 함수 호출 시 &를 붙이는 이유

scanf는 메인함수의 val에 접근하여 값을 대입하는 것
접근하려면 주소값을 알아야 한다. (call-by-reference 방식)

#include <stdio.h>

int main()
{
    int val;
	scanf("%d", &val);
#include <stdio.h>

int main()
{
    char str[100];
    printf("문자열 입력 : ");
	scanf("%s", str);
    // 배열 이름이 주소값이기 때문에 &를 붙이지 않는다

 

포인터와 const 키워드

const는 선언 첫부분, 포인터 이름 앞에, 두 군데 모두 붙일 수 있다.

1. 포인터가 가리키는 변수의 상수화

int a = 10;
const int* p = &a; 
// 포인터가 가리키는 대상(a)을 상수화
// 포인터를 이용한 변경이 불가하다
// p의 관점에서 a가 상수화

// *p=30; //error
a=30; //ok

 

2. 포인터 상수화

int a = 10;
int b = 20;

int* const p = &a; 
// 포인터가 갖고있는 값 자체를 상수화
// 한번 가리킨 포인터의 대상 변경 x 주소값 변경 ㄴ
// 변수는 변경 가능

// p=&b //error
*p=30; //ok

 

3. 둘 다

const int* const p = &a;

 

 

const  키워드를 사용하는 이유

컴파일 시 잘못된 연산에 대한 에러메시지
프로그램을 안정적으로 구성

#include <stdio.h> 
float PI = 3.14;

int main() 
{ 
    float rad;
    PI = 3.07; //실수..바뀌면 안되는 대상
    // 그러나 컴파일에러도 없다
    // 경고메세지까지 구현했어야 함
    
    scanf("%f", &rad);
    printf("원의 넓이는 %f\n ", rad*rad*PI);
    
    return 0; 
}

 

아래처럼 컴파일에러가 발생될 수 있게 하여 안정적으로 코드를 짜도록 한다.

#include <stdio.h> 
const float PI = 3.14;

int main() 
{ 
    float rad;
    PI = 3.07; // 컴파일에러 발생
    
    scanf("%f", &rad);
    printf("원의 넓이는 %f\n ", rad*rad*PI);
    
    return 0; 
}

 

728x90
728x90
블로그 이미지

coding-restaurant

코딩 맛집에 방문해주셔서 감사합니다.

,

v