21. 문자와 문자열 처리 함수

I. 스트림과 데이터의 전송

  • 입.출력에 대한 이해

    • 말그대로 입력과 출력이 무엇인가에 대해 설명 하는거라 pass 하겠다.

 

  • 입.출력이 가능한 이유는 어디에

    • 여기도 간단하게 몇개만 쓰겠다.

      • 표준 입력 스트림 : stdin
      • 표준 출력 스트림 : stdout
      • 표준 에러 스트림 : stderr
      • 스트림 이란 

        • 연속된 데이터의 열을 의미한다.

 

II. 문자 단위 입.출력 함수

  •  문자 출력 함수

    • 하나의 문자를 출력할 때 일반적으로 putchar와 fputc함수이다.

      • putchar : int putchar(int c); 이 함수원형이며 함수 호출시 인자로 받은 문자를 표준출력스트름(대략 모니터) 으로 출력을해준다.
      • fputc : int fputc(int c, FILE* stream) 이 함수원형이며, 기본적으로는 putchar와 같으나 차이점은 문자를 출력할 스트림을 지정할 수 있다는 특징을 가지고 있다. 대부분 파일입출력에 많이 쓰인다.
  • 문자입력 함수

    • 하나의 문자를 입력 받을때 일반적으로 getchar와 fgetc를 사용한다.

      • getchar : int getchar() 가 기본형이며 표준입력스트림(대략 키보드)으로부터 한 문자를 입력 받아서 반환해주는 함수이다.
      • fgetc : int fgetc(FILE* stream) 가 기본형이며 getchar와 같은 기능이며 문자를 입력받을 스트림을 지정할 수 있다는 특징이다. 파일로부터도 데이터를 입력받을수 있기 때문에 파일입출력에서 많이 쓰인다.
  1.  #include <stdio.h>
  2. int main()
    {
     char ch = 0;
     while(ch != 'q')
     {
      ch = getchar();
      putchar(ch);
  3.  }
     return 0;
    }
  • 위의 소스는 getchar와 putchar를 사용한 것이다.

 

  • EOF에 대해서

    • fgetc나 getchar 함수가 파일의 끝에 도달하는 경우에도 EOF가 반환
  1. #include <stdio.h>
  2. int main()
    {
     char ch = 0;
     while(ch != EOF)
     {
      ch = getchar();
      putchar(ch);
  3.  }
     return 0;
    }
  • 위의 소스에서 EOF 발생 할때 까지 입력 받는다.

    • EOF 발생 하려면 ctrl + z or ctrl +c 같은 걸 누르면 된다.

 

  • 문자 단위 입출력 함수가 존재하는 이유!  

    • 책을 읽어보세요

 

III. 문자열 단위 입출력 함수

  • 문자열 출력함수

    • puts : int puts(const char* s)이 함수원형이며 문자열을 표준 출력스트림으로 출력하기 위해 사용하는 함수이다.
    • fputs : int fputs(const char* s, FILE* stream)이 함수원형이며 문자열을 출력할 스트림을 선택할수 있으며 puts와 같다.
  1.  #include <stdio.h>
  2. int main()
    {
     fputs("fputs 함수에 의한 출력,",stdout);
     fputs("I asd",stdout);
     fputs("\n",stdout);
  3.  puts("puts 함수에 의한 출력,");
     puts("i asdf?");
    return 0;
    }
  • 참고로 fputs는 출력을 하는 경우 자동으로 줄바뀜이 안되지만 puts는 자동으로 줄이 바뀌어 진다.

 

  • 문자열 입력 함수

    • gets : char* gets(char* s)가 기본형이며 문자열을 입력받는 함수이다. 우선 입력받을 문자열을 저장하기 위한 배열을 선언한다음, 배열의 시작주소를 인자로 전달하면서 gets함수를 호출하게 된다. 다만 이 함수는 사용을 자제 하자
    • fgets : char* fgets(char* s,int n, FILE* stream)이 기본형이며, gets와 비슷한 기능을 한다. 입력받을 수 있는 최대 문자열의 길이 n을 초과하는 문자열이 입력되는 경우 n-1개까지의 문자만 입력을 받고 마지막에 NULL 문자를 삽입해 준다.

 

IV. 표준 입출력과 버퍼

  • 표준 입출력 기반의 버퍼

    • 표준 입출력 함수를 사용하는 경우에는 버퍼라는 것을 제공받게 된다.
    • 버퍼란 여분의 임시 메모리 공간이라고 생각을 하면 된다.

 

  • 버퍼링을 하는 이유는 무엇인가?

    • 책참조하세요

 

  • 버퍼를 비우는 작업을 하는 fflush 함수

    • fflush : int fflush(FILE* stream)이 함수 원형이며 함수의 인자로 전달되는 스트림의 버퍼를 비워버린다.
  1. #include <stdio.h>
  2. int main()
    {
     char perID[7];
     char name[10];
  3.  fputs("주민등록번호 앞 6자리 입력",stdout);
     fgets(perID,sizeof(perID),stdin);

  4.  fflush(stdin);
  5.  fputs("name : ",stdout);
     fgets(name,sizeof(name),stdin);
  6.  printf("주민등록번호 : %s\n",perID);
     printf("이름 : %s\n",name);
     return 0;
    }
  • fflush를 주석처리 했을때와 안했을 때의 차이를 보면 안했을 때에는 문자가 배열 크기보다 넘어가면 이름을 치지도 못하고 그 넘은 만큼의 문자가 들어가 버린다.

    • 이것을 대비하기 위해서 fflush 를 쓴것이다.

 

V. 문자열 조작함수

  •  문자열의 길이를 반환하는 strlen 함수

    • strlen : #include<string.h> size_t strlen(const char* s)가 함수 원형이며 인자로 문자열의 포인터를 전달받고 문자열의 길이를 계산하여 반환하되 null은 포함되지 않는다.
  1.  #include <stdio.h>
    #include <string.h>
  2. int main()
    {
     char str[100];
  3.  while(1)
     {
      fgets(str,sizeof(str),stdin);
      printf("길이 : %d\n",strlen(str));
     }
     return 0;
    }
  • 위의 소스를 컴파일후 실행시켜 해보았을 때 123 이라 넣으면 4라고 찍히는데 3이 아닌 4일까?

    • 이유는 엔터키까지 포함하였기 때문이다.

 

  • 문자열을 복사하는 strcpy와 strncpy 함수

    • strcpy 함수 : #include<string.h> char* strcpy(char* dest, const char* src)가 함수 원형이며 dest로 전달된 배열에 src로 전달된 문자열을 복사한다.
  1. #include <stdio.h>
    #include <string.h>
  2. int main()
    {
     char str1[10] = "12345678";
     char str2[10];
  3.  printf("원래 문장 : %s\n",str1);
  4.  strcpy(str2,str1);
  5.  printf("새로운 문장 : %s\n",str2);
     return 0;
    }

 

  • strncpy

    • #include<string.h> char* strncpy(char* dest, const char* src, size_t n);이 함수 원형이며 strcpy와 같은 기능이며 즉 src로 전달된 문자열을 dest로 전달된 배열에 복사를 한다.  단 복사하는 문자열의 최대 길이는 n을 넘지 않는다.
  1.  #include <stdio.h>
    #include <string.h>
  2. int main()
    {
     char str1[10] = "12345678";
     char str2[5];
  3.  printf("원래 문장 : %s\n",str1);
  4.  strncpy(str2,str1,sizeof(str2)-1);
     str2[sizeof(str2)-1] = '\0';
  5.  printf("새로운 문장 : %s\n",str2);
     return 0;
    }

 

  • 문자열을 추가하는 strcat와 strncat

    • strcat : #include<string.h> char* strcat(char* dest, const char* src); 가 함수원형이며, src로 전달된 문자열을 첫번째 전달 인자인 dest로 전달된 문자열의 뒤에 추가하는 기능이다.
    • strncat : #include<string.h> char* strncat(char* dest, const char* src, size_t n)이 함수 원형이며, strcat과 같은 기능인데 복사 하고자 하는 문자열의 최대 길이를 인자로 전달하는 기능을 더불어 지니고 있다.
  1.  #include <stdio.h>
    #include <string.h>
  2. int main()
    {
     char str1[35] = "Your favorite language is ";
     char str2[10];
     char *str3 = "12345";
     char str4[10]= {0,};
  3.  fputs("What is your favorite computer language ? :",stdout);
     fgets(str2,sizeof(str2),stdin);
  4.  strcat(str1,str2);
  5.  printf("strcat 생성된 문자열 : %s\n",str1);

  6.  strncat(str4,str3,strlen(str3));
  7.  printf("strncat 생성된 문자열 : %s\n",str4);
  8.  return 0;
  9. }

 

  • 문자열을 비교하는 strcmp 그리고 strncmp 함수

    • strcmp : #include<string.h> int strcmp(const char* s1, const char* s2);이 함수 원형이며 두 개의 문자열 포인터를 인자로 받아서 포인터가 가리키는 문자열의 내용 비교를 한다.
    • strncmp : #include<string.h> int strncmp(const char* s1, const char* s2, size_t n)이 함수 원형이며 strcmp와 같은 기능이며 비교할 문자의 길이를 절달 받아서 비교한다.
  1.  #include <stdio.h>
    #include <string.h>
  2. int main()
    {
     char* str1 = "ABCDase";
     char* str2 = "ABCDEFG";
  3.  int result,result1;
     result = strcmp(str1,str2);
     result1 = strncmp(str1,str2,3);
     if (result == 0)
      printf("두 문자열은 같다.\n");
     else
      printf("두 문자열은 다르다.\n");
     if (result1 == 0)
      printf("두 문자열은 부분적으로 일치\n");
     else
      printf("두 문자열은 전혀 다르다.\n");
  4.  return 0;
    }
  •  문자 및 문자열에 관련된 그밖에 함수들

    • 문자열을 숫조라 변환하는 함수들
    • atoi : #include<stdlib.h> int(long,double) atoi(char *ptr)이 함수 원형이며 문자열을 숫자로 변환해서 리턴해준다.
  1.  #include <stdio.h>
    #include <stdlib.h>
  2. int main()
    {
     char* str1 = "123";
     char* str2 = "321";
  3.  printf("123 + 321 : %d\n",atoi(str1)+atoi(str2));
     return 0;
    }

 

  • 대소문자의 변환을 처리하는 함수들

    • toupper :  #include<ctype.h> int toupper(int c)이 함수 원형이며 소문자를 대문자로 바꾸어 준다.
    • tolower : #include<ctype.h> int tolower(int c)이 함수 원형이며 대문자를 소문자로 바꾸어 준다.
  1.  #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
  2. void convert(char *str);
  3. int main()
    {
     char str[30];
  4.  printf("Enter a string : ");
     fgets(str,sizeof(str),stdin);
  5.  convert(str);
     printf("convert string : %s\n",str);
  6.  return 0;
    }
  7. void convert(char *str)
    {
     int i;
     for (i=0;i<strlen(str);i++)
     {
      if (str[i]>65&&str[i]<=90)
       str[i] = tolower(str[i]);
      else if(str[i]>=97&&str[i]<=122)
       str[i] = toupper(str[i]);
      else
       continue;
     }
    }

이 글은 스프링노트에서 작성되었습니다.

Posted by kid1412
,

19. 함수포인터와 void 포인터

I. 함수 포인터

  • 함수 포인터란 무엇인가?

    • 함수의 이름은 메모리상에 존재하는 함수의 위치를 기리키는 포인터.
  • 함수 포인터의 포인터 타입은 어떻게 되는가?

    • 함수 이름의 포인터 타입을 결정짓는 요수는 리턴형과 전달인자이다.
  1. double fct2(doubel a, double b)
  2. {
  3. double add = a+b;
  4. return add;
  5. }
  •  위와 같은 함수가 있다면 리턴형은 double 이고 double 형 인자를 두 개 전달받는 포인터 타입이다. 라고 말 할 수 있다.

 

  • 적절한 함수 포인터의 선언
  1. int(*fPtr1)(int);
  •  위와 같은 형태로 리턴형(*함수명)(인자값) 이런식으로 쓰면 된다.
  1. #include <stdio.h>
  2. void Add(int a, int b);
    void SPrint(char *str1);
  3. int main()
    {
     char *string = "Function Pointer";
     int a= 10,b=20;
  4.  void (*fPtr1)(int,int ) = Add;
     void (*fPtr2)(char*) = SPrint;
  5.  fPtr1(a,b);
     fPtr2(string);
  6.  return 0;
    }
  7. void Add(int a, int b)
    {
     printf("a + b : %d\n",a+b);
    }
  8. void SPrint(char *str1)
    {
     printf("문자열 ; %s\n",str1);
    }
  • 위의 소스에서 보면 void (*fPtr1)(int,int) = Add라고 써있는데 리턴값이 void이고, int형 인자를 2개 받는 fPtr1함수를 Add라고 정의 한다는 것이다

    • Add는 함수명이니 fPtr1 은 Add 함수와 같다고 보면 되는 것이다.
  1.  #include <stdio.h>
  2. void SelFunction(int s);
    void Add(void);
    void Min(void);
  3. int main()
    {
     int sel;
  4.  while(1)
     {
      printf("선택 : 덧셈(1),뺄셈(2),종료(3)");
      scanf("%d",&sel);
      if (sel == 3)
       break;
      SelFunction(sel);
     }
     printf("프로그램 종료되었습니다. \n");

  5.  return 0;
    }
  6. void SelFunction(int s)
    {
     void(*fPtr)(void);
     if (s==1)
      fPtr = Add;
     else
      fPtr = Min;
     fPtr();
    }
  7. void Add(void)
    {
     int a,b;
     printf("덧셈할 두 수 넣어라:");
     scanf("%d %d",&a,&b);
     printf("덧셈 결과 : %d\n",a+b);
    }
    void Min(void)
    {
     int a,b;
     printf("뺄셈할 두수를 넣어라:");
     scanf("%d %d",&a,&b);
     printf("뺄셈 결과 : %d\n",a-b);
    }
  •  위의 소스를 보면서 함수포인터를 생각핼 보면 쉬울 것이다.

 

II. void형 포인터

  • void형 포인터는 어떤 형태든 담을수 있는 포인터 이다.

    • 단점은 void 포인터를 가지고는 아무런 일을 하지 못하기 때문이다.
    • void형 포인터는 일단 주소 값을 저장해 두고, 포인터의타입은나중에 결정 하는 식이어서 메모리 동적 할당때 유용하게 쓰인다.
  1. int n =10;
  2. void *vp = &n;
  3. *((int*)vp) = 20;
  • 두번째 줄은 void형 포인터 선언 및 초기화를 한 것이고, 세번째 줄은 20으로 변경하기 위해서 int형으로 형변환하고 있는 것이다.

 

III. main 함수도 인자를 받을 줄 알아요.

  • main 함수를 통한 인자의 전달
  1. #include <stdio.h>
  2. int main(int argc, char *argv[])
    {
     int i=0;
     printf("전달된 문자열의 수 : %d\n",argc);
     for (i=0;i<argc;i++)
     {
      printf("%d번째 문자열 : %s\n",i+1,argv[i]);
     }
     return 0;
    }
  •  인자의 형성 과정

    • 위의 소스에 대한 설명이다.

      • 예를 들어 C:\main\main.exe 123 kkk 이렇게 실행을 시켰다고 보자.
      • 그럼 위에 실행 시킨 것이 어떻게 되는지 그림으로 보자.
      •  20.jpg
      • 위 처럼 저장이 된다. 따라서 argc는 3이고, argv 배열에 들어가 있는 것은 위와 같다.
      • 참고로 *argv[] 이렇게 썼었는데 **argv와 동일하다. 

이 글은 스프링노트에서 작성되었습니다.

'2. C/C++ > 01. C' 카테고리의 다른 글

22. 구조체와 사용자 정의 자료형1  (0) 2008.12.07
21. 문자와 문자열 처리 함수  (0) 2008.12.07
18. 다차원 배열 그리고 포인터  (0) 2008.12.07
17. 포인터의 포인터  (0) 2008.12.07
16. 다차원 배열  (0) 2008.12.07
Posted by kid1412
,

18. 다차원 배열 그리고 포인터

I. 2차원 배열 이름의 포인터 타입

  • 2차원 배열 이름이 가리키는 것은?

    • 1차원 배열이름과 마찬가지로 배열의 첫번째 요소를 가리키는 포인터 이다. 다음의 소스를 보자
  1.  #include <stdio.h>
  2. int main()
    {
     int a[3][2] = {1,2,3,4,5,6};
  3.  printf("a[0] : %d\n",a[0]);
     printf("a[1] : %d\n",a[1]);
     printf("a[2] : %d\n",a[2]);
  4.  printf("a : %d\n",a);
  5. printf("a[0][0] : %d\n",&a[0][0]);
     return 0;
    }
  • 위의 소스의 결과값을 보다 시피 a나 a[0]나 &a[0][0] 다 같은 주소값이 나온다.

 

  • 2차원 배열 이름 +1 : 배열 이름을 이용한 포인터 연산
  1. #include <stdio.h>
  2. int main()
    {
     int a[3][2] = {1,2,3,4,5,6};
  3.  printf("a : %d\n",a);
     printf("a+1 : %d\n",a+1);
     printf("a+2 : %d\n",a+2);
     printf("a[0] : %d\n",a[0]);
     printf("a[1] : %d\n",a[1]);
     printf("a[2] : %d\n",a[2]);
     return 0;
    }
  • 위에서 보면  a == a[0], a+1 == a[1], a+2 == a[2] 와 같은 결과가 나온다.

    • 즉 2차원배열 이름은 포인터 연산시 행 단위로 이동을 한다.는 것이다.

 

  •  포인터의 타입에는 이동에 대한 정보가 들어 있다.

    • 임의의 두 포인터 타입이 일치 한다면, 기본적으로 포인터 연산에 의해 증가 및 감소되는 값의 크기가 일치해야 한다고 결론 내릴수 있다.
  1.  #include <stdio.h>
  2. int main()
    {
     int a[3][2] = {1,2,3,4,5,6};
     int b[2][3] = {0,};
  3.  printf("a : %d\n",a);
     printf("a+1 : %d\n",a+1);
     printf("a+2 : %d\n",a+2);
     printf("b : %d\n",b);
     printf("b+1 : %d\n",b+1);
     printf("b+2 : %d\n",b+2);
     return 0;
    }
  • 위의 소스의 결과를 보다 시피 주소값들의 차이는 데이터형의 크기 * 열의 수 이다.

    • 따라서 2차원 배열 이름의 포인터 타입은 어떤 데이터형이자, 포인터 연산 시 배열요소를 몇칸씩 건너 뛰는 포인터 라는 것을 알수 있다.

 

  • 최종 결론! 배열 이름의 포인터 타입

    • 배열 포인터

      • int (*pArr)[4]와 *pArr[4] 차이점
      • int *pArr[4] 는 pArr[][4] 이런식으로 생각을 하면 편할 것이다.

 

  • 2차원 배열에서의 arr[i]와 *(arr+1)
  1. #include <stdio.h>
  2. int main()
    {
     int a[3][2]={0,};
  3.  printf("a[0] : %d\n",a[0]);
     printf("*(a+0) : %d\n",*(a+0));
  4.  printf("a[1] : %d\n",a[1]);
     printf("*(a+1) : %d\n",*(a+1));
  5.  printf("a[2] : %d\n",a[2]);
     printf("*(a+2) : %d\n",*(a+2));
  6.  printf("%d, %d\n",a[1][0],(*(a+1))[0]);
      return 0;
    }
  • 위와 같이 arr[i]와 *(arr+1)는 같은 거라는 것을 알 수 있다. 또 2차원 배열 같은 경우 a[1][0],(*(a+1))[0] 이런식으로 나타 낼수 있다.

문제

18 -1

문제 1

a와 a[0]가 같고 a+1과 a[1]이 가 같은 의미를 지니는 것으로 보인다. 실제로 가리키는 주소 값은 같지만 특성에 있어서는 다소 차이를 지닌다. 다음 예제를 직접 실행해 보고, 어떠한 특성적 차이가 있는지 결론을 내려보기 바란다.

  1. #include<stdio.h>
  2. int main()
  3. {
  4. int arr[3][2] = {1,2,3,4,5,6};
  5. printf("arr : %d\n,",sizeof(arr));
  6. printf("arr[0] : %d\n",sizeof(arr[0]));
  7. printf("arr[1] : %d\n",sizeof(arr[1]));
  8. printf("arr[2] : %d\n",sizeof(arr[2]));
  9. return 0;
  10. }

 

 18 -2

문제 1

다음 코드를 보고 빈칸에 들어갈 적절한 포인터 선언을 해보자

  1. #include<stdio.h>
  2. int main()
  3. {
  4. int* arr1[5];
  5. int* arr2[3][5];
  6.                   = arr1;
  7.                   = arr2;
  8. return 0;
  9. }

이 글은 스프링노트에서 작성되었습니다.

'2. C/C++ > 01. C' 카테고리의 다른 글

21. 문자와 문자열 처리 함수  (0) 2008.12.07
19. 함수포인터와 void 포인터  (0) 2008.12.07
17. 포인터의 포인터  (0) 2008.12.07
16. 다차원 배열  (0) 2008.12.07
14. 포인터와 함수에 대한 이해  (0) 2008.12.07
Posted by kid1412
,

17. 포인터의 포인터

I. 포인터의 포인터에 대한 이해

  • 더블 포인터가 가리키는 것은 싱글포인터
  1. int main()
    {
    double val = 3.14;
    double *ptr1 = &val;
    double **ptr2 = &ptr1;
  2. printf("val : %lf\n",val);
  3. printf("&val : %lf\n",&val);
    printf("ptr1 : %lf\n",ptr1);
    printf("&ptr1 : %lf\n",&ptr1);
    printf("*ptr1 : %lf\n",*ptr1);
    printf("ptr2 : %lf\n",ptr2);
    printf("&ptr2 : %lf\n",&ptr2);
    printf("*ptr2 : %lf\n",*ptr2);
    printf("**ptr2 : %lf\n",**ptr2);
    }
  •  위의 소스를 컴파일 하기 전에 먼저 예상을 해보는 것도 좋다.

    • **ptr2 = *(*ptr2) = *(ptr1) = val 이런식으로 나타 낼수 있다.
    • 그림은 각자 생각해 보자
  • 더블 포인터에 의한 Call-By-Reference

    •  Call-By-Reference가 기억이 안나면 14장으로 돌아가서 한번 다시 보고 오는 것이 좋다.
    •  아래의 소스를 보자
  1.  #include <stdio.h>
  2. void pswap(int *p1,int *p2);
  3. int main(void)
    {
     int A =10,B = 20;
     int *pA, *pB;
  4.  pA= &A,pB = &B;
  5.  printf("pA가 가리키는 변수 : %d\n",*pA);
     printf("pB가 가리키는 변수 : %d\n",*pB);
  6.  pswap(pA,pB);
     
     printf("pA가 가리키는 변수 : %d\n",*pA);
     printf("pB가 가리키는 변수 : %d\n",*pB);
  7.  return 0;
    }
  8. void pswap(int *p1,int *p2)
    {
     int *temp;
     temp = p1;
     p1 = p2;
     p2 = temp;
    }
  •  위의 소스는 결과가 Call-By-Reference가 아닌 Call-By-Value의 결과가 되어 버렸다.

    • 이유는 pA값을 넘겨주면서 값이 복사가 되어서 넘어가기 때문에 교환되는 것은 전혀 다른 것이다.
    • 아래의 소스처럼 바꿔보자
  1.  #include <stdio.h>
  2. void pswap(int *p1,int *p2);
  3. int main(void)
    {
     int A =10,B = 20;
     int *pA, *pB;
  4.  pA= &A,pB = &B;
  5.  printf("pA가 가리키는 변수 : %d\n",*pA);
     printf("pB가 가리키는 변수 : %d\n",*pB);
     pswap(&pA,&pB);
      
     printf("pA가 가리키는 변수 : %d\n",*pA);
     printf("pB가 가리키는 변수 : %d\n",*pB);
     
     return 0;
    }
  6. void pswap(int **p1,int **p2)
    {
     int *temp;
     temp = *p1;
     *p1 = *p2;
     *p2 = temp;
    }
  • 위의 소스를 보면 앞전에 봤던 소스에서 인자를 넘길때 포인터의 주소값을 넘겨준다.

    • 포인터 값을 넘겨주는 것이 아니라 주소를 넘겨주기 때문에 pswap에서는 더블포인터로 선언한 것이고, 값의 복사가 아닌 주소값이 바뀌게 된다.

문제

17 -1

문제1

두개의 int형의 포인터와 길이 5인 int형 배열을 선언한 다음, 총 5개의 정수를 사용자로부터 입력받는다. 그리고 나서 두개의 포인터와 배열을 함수 MaxMin의 인자로 전달한다. 함수 호출이 완료되고 나면 max와 min은 배열의 최대값과 최소값을 가리키고 있어야 한다. 이러한 기능을 지니는 함수 MaxMin을 정의하고, 이에 적절한 main 함수도 구현해 보자. main함수의 마지막에서는 포인터 max와 min이 가리키는 메모리를 지니고 있는 값을 출력하기로 하자. 

이 글은 스프링노트에서 작성되었습니다.

Posted by kid1412
,

16. 다차원 배열

I. 다차원 배열

  • 2차원 배열의 선언

    • 2차원 배열의 선언과 의미
    • 1차원 배열

      •  16.jpg
    • 2차원 배열

      • 17.jpg 
    • 가로가 열 세로가 행을 가리킨다.

      • 자료형 배열이름[행][열]; 이런식으로 선언하면 된다.
  • 실제 메모리상의 그림

    •  18(1).jpg
    • 위와 같은 그림 처럼 메모리에 잡힌다.

 

  • 2차원 배열! 선언과 동시에 초기화 (여기서 부터는 그림 귀찮아서 안 그립니다.)

    • 초기화 case 1: 행 단위로 모든 요소들을 초기화 하는 경우
  1.  int main()
    {
     int somang[3][3]=
     {
      {1,2,3},{4,5,6},{7,8,9}
     };
    }
  • 위와 같이 배열의 개수 만큼 써서 초기화를 해주면 된다. {} 당 한 행으로 보면 된다.

 

  • 초기화 case 2: 행 단위로 일부 요소들만 초기화하는 경우
  1.  int main()
    {
     int somang[3][3]=
     {
      {1},{4,5},{7,8,9}
     };
    }
  • 위와 같이 초기화 할경우 첫째행에 들어가는 수는 1,0,0 이 들어간다. 부족한 부분은 0으로 채워진다.

 

  •  초기화 case 3: 1차원 배열 초기화 형태를 취하는 경우

int somang[3][3] = {1,2,3,4,5,6,7};

  • 위와 같이 하면 1~7까지 들어가고 나머지 0이 들어간다.

 

  • 배열의 크기를 알려주지 않고 초기화 하기

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

 

  • 위와 같이 하면 2*4 행렬 또는 4*2 행렬 1*8 8*1행렬등 어떤식인지 컴터가 몰라 오류가 난다. 다음과 같이 둘중 하나는 알려줘야 한다.

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

 

II. 3차원 그 이상의 배열!

여기서는 별로 설명을 안하겠다.

  • 3차원 이상의 배열은 거의 사용 안한다.
  • 2차원배열을 행렬로 생각하고 3차원 행렬은 큐브 모양으로 되어 있다고 생각하면 쉬울 것이다.

 

문제

16 -1

문제 1

3*9 int형 2차원배열을 선언하자 그리고 그 안에 구구단의 결과를 4단까지 저장하자 제대로 저장되었음을 확인하기 위해서 출력해 보자

 

문제2

A는 2*4 int형 배열이다. 1~8까지로 초기화 시킨 다음 4*2형태로 바꾸고 A에 있는 값으로 초기화 시키자.

이 글은 스프링노트에서 작성되었습니다.

'2. C/C++ > 01. C' 카테고리의 다른 글

18. 다차원 배열 그리고 포인터  (0) 2008.12.07
17. 포인터의 포인터  (0) 2008.12.07
14. 포인터와 함수에 대한 이해  (0) 2008.12.07
13. 포인터와 배열! 함께 이해하기  (0) 2008.12.07
12. 포인터의 이해  (0) 2008.12.07
Posted by kid1412
,

14. 포인터와 함수에 대한 이해

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

  • 함수의 인자 전달 방식

    • 인자 전달의 기본 방식은 복사이다.

3.jpg 

  • 배열을 함수의 인자로 전달하는 방식
  1. #include <stdio.h>
    void fct(int *arr2);
  2. int main()
    {
     int arr1[2] = {1,2};
     fct(arr1);
     printf("%d\n",arr1[0]);
     return 0;
    }
  3. void fct(int *arr2)
    {
     printf("%d\n",arr2[0]);
     arr2[0] = 3;
    }
  •  fct함수를 호출 하면서 배열의 이름을 인자로 전달하는데 이때 배열의 이름 즉, 배열의 주소를 전달하는 것이다.
  1. #include <stdio.h>
  2. int ArrAddr(int *pArr, int n);
  3. int main(void)
    {
     int arr[10] = {1,2,3,4,5,6,7,8,9,10};
     int SumOfArr;
  4.  SumOfArr = ArrAddr(arr,sizeof(arr)/sizeof(int));
     printf("배열의 총합 : %d\n",SumOfArr);
  5.  return 0;
    }
  6. int ArrAddr(int *pArr, int n)
    {
     int sum = 0;
     int i;
     for (i =0;i<n;i++)
     {
      sum += pArr[i];
     }
     return sum;
    }
  • 위의 소스는 배열과 함수 호출의 관계를 잘 알려준다. (배열에 있는 각 요소들의 합을 계산해서 그 결과를 반환하는 함수를 정의한 예제이다.)

 

  • 배열을 인자로 전달받는 함수의 또 다른 선언
  1. #include <stdio.h>
  2. int MaxVal(int pArr[],int n);
  3. int main()
    {
     int arr[10] = {4,8,3,7,2};
  4.  int max;
  5.  max = MaxVal(arr, sizeof(arr)/sizeof(int));
  6.  printf("최대값 : %d\n",max);
     return 0;
    }
  7. int MaxVal(int pArr[],int n)
    {
     int max, i;
     max = pArr[0];
     for (i = 1; i<n;i++)
     {
      if (max < pArr[i])
      {
       max = pArr[i];
      }
     }
     return max;
    }
  •  위의 소스는 최대값을 구하는 소스이다.

    • int pArr[]는 무엇일까?  이것은 *pArr와 같은 것이다. 다만 저렇게 선언 한 것은 배열을 전달 했다고 명확하게 보여주려고 한 것 뿐이다.

II. Call-By-Value와 Call-By-Reference

  • Call-By-Value(값에 의한 호출)

    •  Call-By-Value는 기본 호출 방식이 값의 복사이다.
  1.  #include <stdio.h>
  2. void swap(int a,int b);
  3. int main(void)
    {
     int val1 = 10;
     int val2 = 20;
  4.  swap(val1,val2);
  5.  printf("val1 : %d\n",val1);
     printf("val2 : %d\n",val2);
  6.  return 0;
    }
  7. void swap(int a,int b)
    {
     int temp = a;
     a = b;
     b= temp;
  8.  printf("a : %d\n",a);
     printf("b : %d\n",b);
    }
  •  위의 소스를 보면 swap으로 바꾸어도 값만 복사해서 바꾼거라 메인에서 출력하면 고대로 이다.

    • 그래서 메인에서도 바꾸려면 Call-By-Regerence를 쓰면 된다.
  • Call-By-Reference(참조에 의한 호출)

    • 원래 C에서는  Call-By-Reference의 개념은 없다고 하네요. 그렇게 보이게 하려고 소스를 짠거라는 군요
  1. #include <stdio.h>
  2. void swap(int *a,int *b);
  3. int main(void)
    {
     int val1 = 10;
     int val2 = 20;
  4.  swap(val1,val2);
  5.  printf("val1 : %d\n",val1);
     printf("val2 : %d\n",val2);
  6.  return 0;
    }
  7. void swap(int &a,int &b)
    {
     int temp = *a;
     *a = *b;
     *b = temp;
  8.  printf("a : %d\n",a);
     printf("b : %d\n",b);
    }
  • 위의 소스는 Call-By-Value와 다른 점은 주소값을 사용했다는 점이다.

    • 주소값으로 교환을 하기 때문에 main에서도 바뀌어 보인다.

 

  • 이제는 알 수 있다! scanf 함수 호출시 &를 붙이는 이유

    • scanf 함수 내에서 지역 변수에 접근하기 위해서는 해당 변수의 주소를 알아야 하기 때문에 &를 붙인다.
    • 다만 문자열 일때는 배열 이름 이나 포인터는 배열의 주소를 나타내므로 붙일 필요가 없다.

III. 포인터와 const 키워드

  • 포인터가 가리키는 변수의 상수화
  1. int a = 10;
  2. const int* p = &a;
  3. *p = 30;   // error
  4. a = 30;
  •  위 소스는 *p를 상수화한 소스인데 즉, *p가 가리키는 변수의 값을 못 바꾸게 한다.

    • 더 자세히 말하면 *p를 통해서 변수의 a의 값을 변경하는 것만 막은 것이다.

 

  • 포인터 상수화
  1. int a = 10;
  2. int b = 20;
  3. int* const p = &a;
  4. p = &b;    //error
  5. *p = 30;   //ok
  •  위 int* const p는 상수값은 바꿀수 있지만 주소값을 못 바꾸게 한다.
  1. int a = 10;
  2. int b = 20;
  3. const int* const p = &a;
  4. p = &b;    //error
  5. *p = 30;     //error
  •  이번에는 const int* const p 이다. 위의 소스들을 합친거라고 보면 된다.

    • 즉, 상수값도 못 바꾸고, 주소값도 못 바꾼다는 것이다.

 

  • const를 사용하는 이유
  1. #include<stdio.h>
  2. float PI = 3.14;
  3. int main()
  4. {
  5. float rad;
  6. PI = 3.07;
  7. scanf("%f",&rad);
  8. printf("원의 넚이 : %f\n",rad*rad*PI);
  9. return 0;
  10. }
  • 위의 소스를 보면 PI를 3.14로 정의 했는데 메인에서 또 다르게 정의를 해버렸다. 이것을 모르고 컴파일 하면 당연히 다른 답이 나오게된다.

    • 지금은 소스가 짧아서 오류를 알기 쉽지만 엄청나게 긴 소스를 보게 되면 알기 힘들 뿐더러 컴파일은 오류메시지를 보여주지 않는다.
    •  위와 같은 실수를 해도 컴파일이 오류를 띄우려면 아래와 같이 하면 된다.
  1. #include<stdio.h>
  2. const float PI = 3.14;
  3. int main()
  4. {
  5. float rad;
  6. PI = 3.07;
  7. scanf("%f",&rad);
  8. printf("원의 넚이 : %f\n",rad*rad*PI);
  9. return 0;
  10. }
  •  이런 식으로 소스를 짜면 PI가 값이 변경 되려고 하면 컴파일이 오류를 알려준다.

문제

14 -1

문제1

사용자로부터 정수를 하나 입력받아서 변수 a에 저장한다. 입력받은 값의 제곱을 계산해서 다시 a에 대입해 주는 프로그램을 구현해 보자. 입력받은 값의 제곱을 계산하는 함수를 독립적으로 구현해서 main 함수가 이를 호출하는 형식으로 구현하기로 하자 (두가지 방법으로 함수를 구현할 수 있다.)

 

문제2

두개의 값을 변경 바꾸는 Call-By-Reference 형식의 swap 함수를 공부하였다. 이번에는 변수 a,b,c가 지니는 값을 다음과같이 변경시키는 swap함수를  구현하라.

 

14 -2

문제1

다음 함수의 정의를 보자. 인자로 전달되는 정보를 참조해서 int형 배열의 전체 요소를 출력하는 함수이다.

void print(const int* arr, int size)

{

int i;

for(i=0;i<size;i++)

printf("%d",arr[i]);

}

위 함수에서 매개 변수 arr 선언시 const 키워드를 사용한 이유는 어디에 있겠는가?

 

문제2

다음 예제는 문제를 지니고 있다 컴파일 하면서 문제점을 찾고, 왜 문제가 되는지 결론을 내가

 #include <stdio.h>

void print(const int* ptr);

int main()
{
 int a = 10;
 int *p = &a;
 print(p);
 return 0;
}
void print(const int* ptr)
{
 printf("%d\n",*ptr);
 int *p = ptr;
 *p = 20;
}

 

이 글은 스프링노트에서 작성되었습니다.

'2. C/C++ > 01. C' 카테고리의 다른 글

17. 포인터의 포인터  (0) 2008.12.07
16. 다차원 배열  (0) 2008.12.07
13. 포인터와 배열! 함께 이해하기  (0) 2008.12.07
12. 포인터의 이해  (0) 2008.12.07
11. 1차원 배열  (0) 2008.12.07
Posted by kid1412
,

 13. 포인터와 배열! 함께 이해하기

I. 포인터와 배열의 관계

  • 배열의 이름은 무엇을 의미하는가?

    • 배열의 이름은 포인터다. 단 그 값을 바꿀수 없는 상수라는 점이 일반적인 포인터와의 유일한 차이점
  1. #include <iostream>
  2. using namespace std;
  3. int main()
    {
     int a[5] = {0,1,2,3,4};
     printf("%d, %d\n",a[0],a[1]);
     printf("%d, %d\n",&a[0],&a[1]);
     printf("배열이름 : %d\n",a);
     return 0;
    }
  • 위의 소스를 보면 처음의 printf는 a[0],a[1]의 값을 찍는거고 , 두번째 printf는 각각의 주소값을 세번째 printf는 배열이름에 대한 주소를 찍는다.

    • 결과를 보면 &a[0]와 a는 같다.
비교대상 포인터 배열이름
 비교조건  
 이름이 존재하는가 물론 있다.  당연히 있다.
 무엇을 나타내는가  메모리의 주소  메모리의 주소
 변수인가 상수인가  변수 상수
  • 포인터와 배열이름의 차이점은 배열이름이 상수이다보니 상관 없다. 따라서 상수 포인터라 한다.
  1. int main()
    {
     int a[5] = {0,1,2,3,4};
     int b = 10;
     a = &b;
    }
  •  마지막 줄 a는 상수 이므로 변수인 &b를 넣을수 없다.

 

  •  1차원 배열이름의 포인터 타입

    • int a[10] 이라면 int*형이다.
  • 포인터를 배열의 이름처럼 사용할 수 있다.
  1. #include <iostream>
    using namespace std;
    int main()
    {
     int arr[3] = {0,1,2};
     int *ptr;
  2.  ptr = arr;
  3.  printf("%d,%d,%d\n",ptr[0],ptr[1],ptr[2]);
     return 0;
    }
  •   위 소스처럼 arr를 포인터 처럼 써서 넘겨줄 수 있다.

II. 포인터 연산

  • 포인터는 제한된 형태의 연산이 가능하다
  1. #include <iostream>
    using namespace std;
    int main()
    {
     int *ptr = 0;
     char *ptr1 = 0;
     double *ptr2 = 0;
  2.  printf("%d,%d,%d\n",ptr++,ptr1++,ptr2++);
     printf("%d,%d,%d\n",ptr,ptr1,ptr2);
     return 0;
    }
  • 먼저 ptr,ptr1,ptr2를 찍고 각각 하나씩 증가한다음  각 타입만큼 증가 시켜서 그다음번에 4,1,8을 찍는다.

    • 포인터 연산에 따른 실질적인 값의 변화는 포인터 타입에 따라 다르다.
  1. #include <iostream>
    using namespace std;
    int main()
    {
     int arr[5] = {1,2,3,4,5};
     int *parr = arr;
     printf("%d\n",*parr);
     printf("%d\n",*(++parr));
     printf("%d\n",*(++parr));
     printf("%d\n",*(parr+1));
     printf("%d\n",*(parr+2));
  2.  return 0;
    }
  • 위의 소스를 보면 *(parr+1) 같은것이 보인다.

    • 잘 생각해보면 parr은 배열의 이름(즉 배열의 첫번째 주소값)이 들어가있다. 거기에 +n 을 하면 더한만큼의 배열을 가리킨다.
  •  중요한 결론! arr[i] = *(arr+i)

III. 문자열 상수를 가리키는 포인터

  • 문자열 표현 방식의 이해

    •  변수로 표현하는 방법 : char str1[5] = "ABCD";
    • 상수로 표현하는 방법 : char *str2 = "abcd;
  1. #include <iostream>
    using namespace std;
    int main()
    {
     char str1[5] = "abcd";
     char *str2 = "ABCD";
  2.  printf("%s\n",str1);
     printf("%s\n",str2);
  3.  str1[0] = 'x';
     str2[0] = 'x';
     printf("%s\n",str1);
     printf("%s\n",str2);
     return 0;
    }
  •  위의 소스는 컴파일은 잘된다 하지만 실행시 오류가 난다 어디서 날까?

    •  str2[0] = 'x'; 이것이 잘못 된 것이다. 왜냐하면 str2는 문자열 상수를 변경하려고 하기 때문이다.
  • 문자열 상수에 대한 조금 더 깊은 이해

    • 문자열 상수는 메모리 공간에 할당되면 주소를 반환한다.

1.jpg 

  • 똑같은 문자열을 선언하면 한번만 메모리 공간에 할당된다.
  1. #include <iostream>
    using namespace std;
    int main()
    {
     char *str1 = "ABCD";
     char *str2 = "ABCD";
      printf("%d,%d\n",str1,str2);
     return 0;
    }
  • 좋은 컴파일러는 똑같은 코드라 할지라도 메모리를 효율적으로 사용하기위해서 최적화를 한다.

IV. 배열 요소로 포인터를 지니는 포인터 배열

  • 포인터 배열의 이해
  1. #include <iostream>
    using namespace std;
    int main()
    {
     int a = 10, b= 20, c = 30;
     int* arr[3]={&a,&b,&c};
  2.  printf("%d\n",*arr[0]);
     printf("%d\n",*arr[1]);
     printf("%d\n",*arr[2]);
     
     return 0;
    }
  • 그림으로 설명하겠다.

 2.jpg

 

문제

13-1

문제 1

크기 5인 int형 배열 arr을 선언하고 1,2,3,4,5로 초기화 한다음 포인터 p를 선언해서 배열 arr의 첫 번재 요소를 가리키게 한다. 그 다음 포인터 p를 조작해서 배열 요소의 값을 2씩 증가시킨후, 전체 배열 요소를 출력

 

문제 2

 1번 문제와 유사하다. 크기 5인 int형 배열 arr을 선언하고 1,2,3,4,5로 초기화 한다음 포인터 p를 선언해서 배열 arr의 첫 번재 요소를 가리키게 한다. 그 다음에는 포인터p를 이용해서 배열 요소의 순서를 뒤바꾼 후, 그 결과를 출력하는 프로그램 작성

 

이 글은 스프링노트에서 작성되었습니다.

'2. C/C++ > 01. C' 카테고리의 다른 글

17. 포인터의 포인터  (0) 2008.12.07
16. 다차원 배열  (0) 2008.12.07
14. 포인터와 함수에 대한 이해  (0) 2008.12.07
12. 포인터의 이해  (0) 2008.12.07
11. 1차원 배열  (0) 2008.12.07
Posted by kid1412
,

12. 포인터의 이해

I. 포인터란 무엇인가?

  • 포인터란 메모리의 주소 값을 저장하기 위한 변수이다.
  • 포인터는 타입에 상관없이 그 크기가 4바이트임을 알 수 있다.

pointer.jpg 

  • 포인터 선언하기

    1. int n = 7;
    2. int *pN = n;
  • 주소와 관련된 연산자 : &연산자, *연산자

    • 주소값을 참조할 때 사용하는 연산자 : &
    • 포인터가 가리키는 메모리 참조 : *
    1. int main()
    2. {

      1. int a =2005;
      2. int *pA = &a;
      3. printf("%d",pA);
      4. printf("%d,*pA);
    3. }
    • *pA는 2005로 출력된다.
    • pA는 a의 주소값이 들어가 있다.
    • 포인터에 대한 예제
    1. #include<stdio.h>
    2. int main(void)
    3. {

      1. int a = 2005;
      2. int *pA = &a;
      3. printf("pA : %d\n",pA);
      4. printf("&a : %d\n",&a); //직접 접근
      5. (*pA)++;
      6. printf("a: %d\n",a);
      7. printf("*pA: %d\n",*pA); //간접 접근
      8. return 0;
    4. }
  • 실행 시키면 어떤식으로 돌아가는지 이해 할 것이다.
  • 포인터의 타입은 메모리를 참조하는 방법을 알려주는 역할을 한다.

    • 포인터 int 형 일경우 읽어들인 주소값에서 4바이트 만큼 읽어들이고, double 형일 경우 8바이트를 읽어들인다는 것을 알려 주는 역할

II. 잘못된 포인터의 사용

int main()

{

int *pA;

*pA = 10;

return 0;

}

  •  이 소스는 잘못 된 것이다. 무엇이 잘못 된 것일까?

    •  pA라는 포인터 변수를 초기화 하지 않았을 뿐더러 10을 넣으려고 하면 메모리 어디에 들어갈지 모르니 오류가 발생한다.

int main()

{

int *pA = 100;

*pA = 10;

return 0;

}

  • 이 소스는 잘못 된 것이다. 무엇이 잘못 되었는가?

    • 위 소스는 첫번째 소스와 거의 동급이다 .포인터는 선언 동시에 초기화를 해주는 것이 좋은데 위와 같은 이유로 어디에 들어갈지 모르니 오류가 발생한다.
  • 그럼 어찌 초기화 해야 할까?

int main()

{

int *pA;

int a = 10;

pA = &a;

return 0;

}

  •  이 소스 처럼 pA를 주소값으로 초기화를 시키면 초기화 시킨 주소값이 들어가므로 오류가 나지 않는다.

문제

12 -1

문제 1

다음 프로그램 실행 시 포인터와 변수와의 관계를 나름대로 그림을 그려서 설명해 보자, 출력 결과도 예상해 보자

  1. #include<stdio.h>
  2. int main()
  3. {
  4. int n = 10;

  5. int *p1 = &n;

  6. int *p2 = p1;

  7. printf("%d\n",(*p1)++);

  8. printf(%d\n",(*p2)++);

  9. printf("%d\n",n);

  10. return 0;

  11. }

 

문제 2

char형 변수 a, int형 변수 b, float형 변수 c, double 형 변수 d, 이렇게 총 4개의 변수를 선언하자(초기값은 알아서..) 그리고 포인터 p1, p2, p3, p4를 선언해서 각각 a,b,c,d를 가리키게 하자 그다음에 포인터 p1,p2,p3,p4를 이용해서 a,b,c,d의 값을 1 증가 시키자. 즉, 간접 접근 방식에 의해서 값을 하나 증가시키라는 뜻이다.

 

문제 3

int형 변수 a와 b를 선언과 동시에 각각 10,20으로 초기화시킨다. 그리고 포인터 p1, p2를 선언한 다음 각각 변수 a,b를 가리키게 한다. 그 다음 간접 접근 방식에 의해서 값을 하나 감소 시킨다. 그리고 p1,p2를 swap 시킨다.

이 글은 스프링노트에서 작성되었습니다.

'2. C/C++ > 01. C' 카테고리의 다른 글

17. 포인터의 포인터  (0) 2008.12.07
16. 다차원 배열  (0) 2008.12.07
14. 포인터와 함수에 대한 이해  (0) 2008.12.07
13. 포인터와 배열! 함께 이해하기  (0) 2008.12.07
11. 1차원 배열  (0) 2008.12.07
Posted by kid1412
,

11. 1차원 배열

2. C/C++/01. C 2008. 12. 7. 17:45

11. 1차원 배열

I. 1차원 배열의 선언 및 초기화

1) 1차원 배열의 선언과 접근

  • 배열 선언에 필요한 것 세가지

    • int array[10];

      • 배열 길이 10 인 array라는 이름의 int형 배열 이라는 뜻
      • 배열길이, 배열이름, 배열 형태
      • 참고로 위에 배열은 메모리에 할당되는 크기는 int형(4바이트)*배열크기(10) = 40바이트이다.
  • 배열의 길이 선언은 오직 상수

    1. int main()
    2. {
    3. int size =10;
    4. int arr[size];
    5. }
    • 위와 같은 소스일 경우 arr의 사이즈가 size 변수로 해놓았기 때문에 컴파일시 오류가 납니다.
  • 배열 요소의 접근을 위한 인덱스의 이해

    • 배열의 첫번째 요소의 인덱스는 0이다. 즉, arr[0]이 처음이다.

2) 배열! 선언과 동시에 초기화하기기

  1. int arr1[5] = {1,2,3,4,5};
  2. int arr2[] = {1,2,3,4,5};
  3. int arr3[5] = {1,2};
  • 첫번째 줄의 arr1은 배열을 1,2,3,4,5로 초기화 시킨거고(단, 크기가 5라고 정해졌다.)
  • 두번째 줄의 arr2는 배열 크기는 없지만 초기화를 해줌으로써 크기가 정해진다.
  • 세번째 줄의 arr3는 배열 크기가 5이지만 초기화를 1,2만 해주면 나머지는 0으로 초기화 된다.

II. 배열을 이용한 문자열 변수의 표현

  1. 문자열 상수와 문자열 변수

    1. 문자열 상수

      1. 첫째로 이름이 없다.
      2. 문자열의 내용 변경이 불가능 하다.
    2. 문자열 변수

      1. 문자열을 변수로 선언하는데 있어서 사용 되는 것이 배열
  2. 문자열 변수의 특징과 널 문자에 대한 이해

    1. 배열을 이용한 문자열 변수의 생성

      1. 문자열 변수를 생성할 때는 배열의 크기는 하나 크기 잡아야 한다.
        이유 : 마지막에 이 문자열이 끝났다는 널문자를 넣어주어야 하기 때문에
    2. 널 문자에 대한 이해

      1. 만약 크기가 100인 char형 배열이 있는데 문자열을 저장할 때 너가 25자 정도만 되는 문장 또는 글자를 넣는다고 하자. 그리고 나서 출력 하면 어느정도는 잘나오지만 25자를 쓴 글자 뒤로 쓰레기 값이 엄청나게 나올 것이다.
      2. 그래서 25자를 쓴다음 끝에 \0 을 넣으면 \0(NULL)문자까지만 읽고 끝나 버린다.

III. 연습문제

11 -1

문제 1

소망 빌라는 5층으로 이뤄져 있다. 프로그램 실행 시 사용자로부터 1층부터시작해서 5층까지 각층에 사는 사람의 수를 입력받는다. 입력이 끝나면 소망빌라에 사는 전체 사람의 수를 계산해서 출력하는 프로그램을 작성하자.

문제 2

길이가 9인 int형 정수 배열을 선언하고 나서 사용자로부터 숫자를 하나 입력받는다. 그리고 입력 받은 숫자의 구구단 계산 결과를 미리 선언해 놓은 배열에 저장한다. 마지막으로 배열의 요소 중 에서 짝수 번째 위치에 존재하는 요소들을 출력하는 프로그램을 작성하자. 참고로 짝수번째 위치에 존재하는 배열의 요소를 출력하려면 홀수를 인덱스 값으로 사용해야 할 것이다.

문제 3

길이 26인 char형 배열을 선언해서 문자 'A'부터 'Z'까지 저장한다. 선언과 동시에 초기화하라는 뜻이 아니다. 반복문을 이용해서 저장하는 형태를 취해야 한다. 그리고 배열에 모든 요소를 처음부터 끝가지 출력하는 프로그램을 작성하자.

문제 해결에 들어가기에 앞서서 여러분에게 한가지 질문을 하겠다. 혹시 아스키 코드 표를 참조해야만 문제를 해결할 수 있다고 생각하는가? 그렇다면 아스키 코드값을 모르고도 해결할 수 있는 방법은 없겠는가?


11-2

문제 1

사용자로부터 하나의 문자열을 입력받아서 입력받은 문자열의 길이를 출력하는 프로그램을 작성하자. 널(NULL)문자는 문자열의 길이에서 제외시키는 것으로 하자.

문제 2

사용자가 입력한 문자열을 배열에 저장한 다음, 배열 내에게 문자열을 역순으로 뒤집는다. 그리고나서 제대로 뒤집어졌는지 확인하기 위해서 문자열을 출력해 보는 프로그램을 작성해 보자.

문제 3

문자열을 입력받는다. 입력받은 문자열을 구성하고 있는 문자 중에서 아스키 코드 값이 가장 큰 문자를 찾아서 출력하는 프로그램을 구현해 보자. 예를 들어서 입력된 문자열이 "abc"이라면 이중에서 아스키 코드값이 가장 큰 문자는 'c'이다. 따라서 c를 출력해준다.

참고문헌

 

이 글은 스프링노트에서 작성되었습니다.

'2. C/C++ > 01. C' 카테고리의 다른 글

17. 포인터의 포인터  (0) 2008.12.07
16. 다차원 배열  (0) 2008.12.07
14. 포인터와 함수에 대한 이해  (0) 2008.12.07
13. 포인터와 배열! 함께 이해하기  (0) 2008.12.07
12. 포인터의 이해  (0) 2008.12.07
Posted by kid1412
,

4. C

2. C/C++ 2008. 12. 7. 17:43

C 프로그래밍

I. 차례

11. 1차원 배열

12. 포인터의 이해

13. 포인터와 배열!

14. 포인터와 함수에 대한 이해

16. 다차원 배열

17. 포인터의 포인터

18. 다차원 배열과 그리고 포인터

19. 함수 포인터와 void 포인터

21. 문자와 문자열 처리 함수

22. 구조체와 사용자 정의 자료형

23. 구조체와 사용자 정의 자료형2

24. 파일 입-출력

25. 메모리 관리와 동적 할당

26. 매크로와 전처리기

27. 모듈화 프로그래밍 // 책을 참고하세요

II. 문제들

책에 있는 문제 위주입니다.

참고문헌

열혈강의 C 프로그래밍

이 글은 스프링노트에서 작성되었습니다.

'2. C/C++' 카테고리의 다른 글

4. C++  (0) 2008.12.07
Posted by kid1412
,