전산 SMP 8 주차 2015. 11. 21 김범수 bskim45@gmail.com Special thanks to 박기석 (kisuk0521@gmail.com)
지난내용복습 Dynamic Memory Allocation
왜쓰나요? 배열의크기를입력받아그크기만큼의배열을만들고싶을때 int main(void) { int size; scanf( %d, &size); } int array[size]; Compile Error! 선언은항상맨위에와야한다. 선언후에배열이할당되어야하는데 이럴때는어떻게? 프로그램실행중에메모리를할당해데이터를저장할공간을생성하는방법
A Conceptual View of Memory We can refer to memory allocated in the heap only through a pointer.
Accessing Dynamic Memory
malloc 지정하는크기 (byte) 만큼메모리 ( 힙 ) 를할당 기본적으로 void * 로리턴 원하는타입으로 casting 해줘야한다 할당에실패한경우 NULL 리턴 void *malloc (size_t size); int* p = (int *)malloc(sizeof(int) * 4); int 형의크기가 4byte 이기때문에 16byte 의공간이동적으로할당 char *str = (char *)malloc(sizeof(char) * 10);
calloc void *calloc (size_t count, size_t size); count * size 만큼의메모리를할당하고해당힙영역을 0 으로초기화하여반환 int *p = (int *)calloc(4, sizeof(int)); char *str = (char *)calloc(10, sizeof(char)); malloc(sizeof(int)*4) calloc(4, sizeof(int))
realloc 할당받은메모리공간을새로운크기로재할당 void *realloc(void *ptr, size_t newsize); int *p = (int *)calloc(4, sizeof(int)); p = (int *)realloc(p, sizof(int) * 6); char *str = (char *)calloc(10, sizeof(char)); str = (char *)realloc(str, 20*sizeof(char));
free 동적할당한메모리반환 사용하지않을때 & 프로그램의마지막에반드시반환해야한다! void free (void * ptr); free(ptr); free(str);
동적할당으로 2 차원배열만들기 포인터배열 int **table; table = (int **)calloc (3, sizeof(int *)); table[0] = (int *)calloc(4, sizeof(int));
포인터의부적절한사용으로인한주요부작용들 Unreachable Memory ( 이공간을가리키는포인터가존재하지않는다 ) Dangling Pointer ( 어딘가가리키고있기는하지만, 그위치에뭐가있는지알수없다.) Buffer Overflow ( 할당되어있는양이상으로메모리를다루게되는경우 ) Segmentation Fault ( 잘못된주소접근 ) 11
허공에뜬메모리공간 (unreachable memory) { char *str; (1) str = (char *) malloc(200 * sizeof(char)); (2) (no free()!!) str = (char *) malloc(123 * sizeof(char)); (3) } (1) (2) (3) str str str??? 200 byte space 200 byte space Another 123 byte space
길잃은포인터 (dangling pointer) char *cp = NULL; (1) /*... */ { char c; cp = &c; (2) } /* c로할당되었던메모리공간이이시점에서할당해제된다. */ /* cp는이제길잃은포인터 (dangling pointer) 가되어버렸다. */ (3) (1) (2) (3) cp NULL cp cp??? c c c 변수가사라진상황. 이후에이공간이어떻게사용될지아무도모른다.
Buffer overflow 버퍼 (buffer) 컴퓨터내에서사용되는임시저장소 ( 메모리공간 ) 컴퓨터에서일어나는대부분의작업은효율을위해버퍼를많이사용한다. Buffer overflow Overflow = 넘친다 저장한내용이할당되어있는버퍼의영역바깥으로넘치는것 만일넘친영역이다른용도로사용되고있었다면, 그원래의값을파괴해버린다. 넘친영역의값이파괴됨을이용하여대상컴퓨터를혼란시켜침입하는기법이많이사용된다.
잘못된연산오류 (Segmentation fault) 지정한영역이외에엉뚱한위치 ( 주로 null 혹은쓰레기값 ) 를가리키는포인터가가리키는위치에다가어떤값을써넣으려고시도하는경우에발생한다. 현재각포인터가가리키는위치가유효한지꼼꼼히살펴봐야한다. e.g. int *p; // 초기화없이선언 *p = 123; // 초기화되지않은포인터 dereferencing 여긴어디나는누구? printf("%d\n", *p); //???
Tidy Up 동적으로할당된메모리는반드시시스템에반환해야함! 그래야다른프로그램이메모리공간을활용할수있다. ( 메모리 leak) 실행전에미리할당 vs 실행중에동적으로할당하고반환 공간이필요한만큼만쓰기때문에효율적! 메모리공간의크기는정해져있다. 얼마나큰공간이필요한지알수없을때 적당히크게? 공간이부족하거나, 공간이낭비되거나
오늘할것 Enumeration, Structure, Union String (Advanced) - 하는데까지
Structure
The Type Definition (typedef) A type definition, typedef, gives a name to a data type by creating a new type that can then be used anywhere a type is permitted. 프로그래머는길게쓰는것을싫어한다 typedef int INGETER;
Derived Type 프로그래머가임의로만든타입
Enumerate Type 항목혹은선택지, 일종의상수항목을만들때사용 각항목들에대해 identifier 로써하나의정수 (enumeration constant) 가할당됨 상황 ) 메뉴를만들고숫자하나입력받아서 switch 문으로각기다른함수를실행해야한다. 그냥숫자 0, 1, 2, 3 으로나누면나중에헷갈리고불편함
Declaring an Enumerated Type enum typename { identifier list }; enum COLOR { RED, BLUE, GREEN, WHITE }; enum COLOR skycolor;
Initializing Enumerated Constants enum MONTHS {JAN, FEB, MAR, APR}; identifier 자동배정 0 1 2 3 enum MONTHS {JAN = 1, FEB, MAR, APR}; enum COLORS {RED, ROSE=0, CRIMSON=0, BLUE, AQUA=1};
Operations on Enumerated Types enum COLORS color1, color2; color1 = BLUE; color2 = color1; if (color1 == color2) if (color1 == BLUE) switch (color1) { case BLUE:
Enumeration Type Conversion int 형과자동으로호환됨 int x; enum COLORS y; x = BLUE; y = 2; enum COLORS y; y = (enum COLORS) 2;
Anonymous Enumeration: Constants enum {space =, comma =,, colon = : }; enum {OFF, ON};
Structure Type 관련되는 element 들의집합. 어떤타입의변수라도올수있다. 단, 함수는구조체의 element 로안된다. 오직변수만가능
Structure Declaration
Initializing Structures
Accessing Structure Elements (*pointername).fieldname pointername - >fieldname.
Nested Structure
Arrays in Structures
Array of Structures
Passing Structures Through Pointers
Structure Application Structure 배열 Structure 포인터배열 struct AA ary[10]; struct AA *ary[10]; 한 Structure 안의포인터 element 가다른 Structure 를가리킨다 Linked List 의핵심개념!!
Example 이름, 나이, 성별 (enum), 학년 (enum) 을포함하는구조체 크기 5 짜리구조체배열만들고여기있는사람에대한정보하나씩넣기 for 문으로각구조체에들어간거전부출력 학년 FRESHMAN SOPHOMORE JUNIOR SENIOR 성별 MALE FEMALE
Union Types 구조체와비슷하다. 선언및사용도구조체처럼 단, Element 들이메모리를공유 전체구조체크기 = 구조체내부의가장큰변수의크기
Example typedef union { short num; char chary[2]; } SHORTCHAR; SHORTCHAR data; data.num = 16706; // 1000001 01000010 = 65 66
Union Application 메모리공간을절약할수있고, 두가지구조체역할을할수있으므로간단 단, 헷갈리지않는다면
String
문자열 (string) 도결국은배열이다 char 형의배열 끝에널문자 \0
문자열의선언 char str[15] = Good Day ; 할당한용량을모두사용할필요는없습니다. char month[] = January ; 배열크기가문자열의길이에맞춰자동으로설정 char *pstr = Good Day ; char str[9] = { G, o, o, d,, D, a, y, \0 };
문자열의포인터 배열의이름은첫번째 element 의주소와같다. 그래서 scanf 로 %s 받을때 & 안붙인다! str[0] H e l l o W o r l d! \0 str &str[0]
문자열포인터사용주의점 반드시동적할당해주거나어떤문자열의주소를넣어주어야한다.
String Copy? char str1[6] = Hello ; char str2[6]; str2 = str1; //?
String Input/Output Functions #include <stdio.h> formatted input/output functions scanf/fscanf printf/fprintf special set of string-only functions get string (gets/fgets) put string ( puts/fputs ).
FLUSH 스트림버퍼를비우는역할을한다. Scanf 등입력받는함수사용시 The string conversion code(s) skips whitespace. ex) int a; char b; scanf( %d, &a); scanf( %c,&b); printf( %d %c\n, a, b); fflush(); #define FLUSH while(getchar!= \n )
Formatted String Input char str[10]; scanf( %9s, str); str - 배열포인터 & 가붙지않음 입력문자개수를반드시정의해주자
String-only Input: gets/fgets
gets( ) char * gets(char *str); Reads characters from stdin, until either a newline or EOF Params str: pointer to an array of chars 길이제한없음 ( 보안상취약 ) Return value Success: returns str (incl. \0 at the end) EOF: feof() set, 여태까지읽은 str return 아무것도못읽으면 : NULL
fgets( ) char * fgets (char *str, int num, FILE *stream); Reads characters from stream, until (num-1) characters have been read OR either a newline or the EOF Params str : pointer to an array of chars num : Maximum number of characters (incl. null) 문자는최대 (num-1) stream : Pointer to a FILE that identifies an input stream Return value Success: returns str (incl. \0 at the end) EOF: sets EOF(feof), 여태까지읽은 str 리턴 아무것도못읽으면 : NULL
Difference btw. Input functions gets/fgets gets does not include newline ( \n ), fgets does. gets does not allow to specify a maximum size for str (which can lead to buffer overflows). Scanf/gets scanf 는단어단위로 (space), gets 는줄단위로 (newline)
String-only Output: puts/fputs
puts( ) int puts ( const char * str ); Writes str to stdout and appends a newline character ('\n') until null( 0\ ). Terminating null-character is not copied to the stream. Params str: pointer to an array of chars Return value Success: returns a non-negative value Error: returns EOF(-1) and sets the error indicator (ferror)
fputs( ) int fputs ( const char * str, FILE * stream ); Writes str to the stream until null ('\0'). Terminating null-character is not copied to the stream. Params str: pointer to an array of chars stream: Pointer to a FILE object that identifies an output stream. Return value Success: returns a non-negative value Error: returns EOF(-1) and sets the error indicator (ferror)
Difference btw. Output functions puts appends a newline( \n) at the end automatically fputs does not write additional characters
입력한문자열에서입력한문자개수세기 #include <stdio.h> main() { char str[30],ch; int i=0, cnt=0; // scanf("%s",str); // scanf쓰면 apple의마지막엔터가 ch에들어가므로쓰면안됨 gets(str); // scanf("%c", &ch); // 한문자입력은 scanf, getchar 모두가능 ch=getchar(); while(str[i]!='\0'){ if(str[i++]==ch) cnt++; } printf("%s에서 \'%c\' 문자가 %d개입니다.\n", str, ch, cnt); } 57
String Manipulation Functions #include <string.h> String Length and String Copy String Compare and String Concatenate Character in String Search for a Substring and Search for Character in Set String Span and String Token String to Number
String Length unsigned int strlen ( const char * str ); Returns the length of the C string str, until null( \0 ). Params str: pointer to an array of chars Return value The length of string.
Example char mystr[100]="test string"; sizeof(mystr) evaluates to 100 strlen(mystr) returns 11.
String Copy char * strcpy ( char * destination, const char * source ); char * strncpy ( char * destination, const char * source, unsigned int num );
String Compare int strcmp ( const char * str1, const char * str2 ); int strncmp( const char * str1, const char * str2, int size); Results for String Compare 문자비교 - 아스키코드순으로
String Concatenation char * strcat ( char * destination, const char * source ); char * strncat ( char * destination, const char * source, unsigned int num );
Character in String char * strchr ( const char * str, int character ); Return Value A pointer to the first occurrence of character in str. If the character is not found, the function returns a null pointer.
String/Data Conversion #include <stdio.h> String to Data Conversion Data to String Conversion
sscanf( ) Read formatted data from string sscanf is a one-to-many function. It splits one string into many variables.
sscanf ( ) int sscanf (const char *str, const char *format, ); Reads data from str and stores them according to parameter format into the locations given by the additional arguments scanf stdin/ sscanf str Params str: Pointer to source char arrays format: Pointer to a format string... (additional arguments): Sequence of additional arguments depending on the format string with the appro priate type. Additional arguments are ignored. Return value Success: returns the number of items in the argument list successfully filled. Failure: EOF(-1) is returned.
Example int main () { char sentence []="Rudolph is 12 years old"; char str [20]; int i; sscanf (sentence,"%s %*s %d",str,&i); printf ("%s -> %d\n",str,i); } return 0; Output: Rudolph -> 12
sprintf( ) Write formatted data to string sprintf is a many-to-one function. It joins many pieces of data into one string.
sprintf ( ) int sprintf ( char * str, const char * format,... ); Composes a string and stores it as a C string in the buffer pointed by str according to the format. printf stdout, sprint str A terminating null character( \0 ) is automatically appended after the content. Parameters str: Pointer to a buffer where the resulting C-string is stored. The size of the buffer should be large enough to contain the entire resulting string (snprintf for a safer version). format: C string that contains a format string... (additional arguments): a sequence of additional arguments, depending on the format string. Additional argumen ts are ignored. Return value Success: the total number of characters written is returned. (w/o null-character) Failure: a negative number is returned.
Example #include <stdio.h> int main (void) { char buffer [50]; int n, a=5, b=3; n = sprintf (buffer, "%d plus %d is %d", a, b, a+b); printf ("[%s] is a string %d chars long\n",buffer,n); return 0; } Output: [5 plus 3 is 8] is a string 13 chars long
More at http://www.cplusplus.com/reference/string/ 수업시간에한것들은한번씩찾아보고사용법익히기
Assn #4 - Prob 1: String 처리함수구현하기 int mystrlen(char *str); char *mystrcpy(char *tostr, char *fromstr); char *mystrcmp(char *str1, char *str2); char *mystrcat(char *str1, char *str2); char *mystrchr(char *str, char ch); int myatoi(char *str); 이건저번어싸인에서했고 위에서기본적인원리는다했죠? ^^
Assn #4 Prob 2 최소 5 개이상의함수작성 - 파일로부터리스트를생성하는부분 (1 개의함수 ) 과각메뉴 (4 개의함수 ) 특정학생의정보및과목정보는구조체의변수에저장, 프로그램내부에서동적할당된구조체포인터의배열을이용하여관리 = 필요할때마다동적할당해서쓰세요 C:\> assn4.exe students.txt Argument Passing - int main(int argc, char* args[]) 예외처리 - 파일읽기에서읽을파일이존재하지않을경우 : fopen 의 r 모드리턴값 NULL 파일읽기 fgets 가 NULL 을리턴할때까지 (EOF)
Assn #4 Prob 2 typedef struct { int id; char name[11]; char dept[7]; int level; int sub_num; TAKING_SUBJECTS subjects[max_taking_subject_num]; } STUDENT; 1. 학생별성적 stu_list 한번돌면서 STUDENT 안에 subjects 배열한번돌고 2. 과목별성적 학생명단을출력하는게좀짜증나는데, 역시 stu_list 돌면서 subjects 배열에해당과목이있으면출력해주면되겠죠 ~ STUDENT* stu_list[max_student_num]; SUBJECT* sub_list[max_subject_num]; 3. 저장하기 For 문으로배열돌면서주어진틀에맞춰서 fputs 만잘써주면되겠네요 ~
다음시간 어싸인너무쉽다 Various Data Structures implemented with Lists