Chapter 10 Strings and Pointers 프로그래밍 기초와 실습 Chapter 10 Strings and Pointers
Contents The End-of-String Sentinel ‘\0’ Initialization of Strings Displaying String and Character Reading Strings from KB An Example : Have A Nice Day Using pointers to Process a String Problem Solving : Counting Words Passing Arguments to main() String-Handling Functions in the Standard Library
Preview String String : 일련의 characters들로 구성 C에서 String 은 char의 one-dimensional array 로 표현. String의 각 Element는 Array index 또는 Pointer로 접근 가능 C에서는 String process를 위한 여러 가지 Built-in Functions을 제공 null character ‘\0’은 Terminate String(End of String)으로 간주
The End-of-String Sentinel ‘\0’ 모든 String은 ‘\0’ (null-String)으로 종료된다. String은 char array를 통해 memory를 확보한다. 확보된 memory에 String을 저장하는 방법 [Ex] char word[100]; /* 최대 99개의 문자를 저장할 수 있다. */ [Ex] word[0] = ‘a’; word[1] = ‘b’; word[2] = ‘c’; word[3] = ‘\0’; /* string의 종료를 위한 null char 삽입*/ word는 “abc”의 값을 갖는다. [Ex] scanf(“%s”, word); KB로부터 String을 입력 받는다.
Initialization of Strings Use array name String의 process를 위해 char array를 사용 [Ex] char word[4] = “abc”; [Ex] char word[4] = {‘a’, ‘b’, ‘c’, ‘\0’ }; [Ex] char word[] = {‘a’, ‘b’, ‘c’, ‘\0’ }; ‘\0’을 생략할 경우 compiler가 자동으로 삽입 [Ex] char word[] = “abc”; compiler에 의해 자동으로 4 char를 위한 array생성 String의 length는 3이지만 필요 size는 최소 4이다. word는 ‘a’, ‘b’, ‘c’, ‘\0’을 저장하고 있다.
Initialization of Strings Use pointer name String의 process를 위해 pointer 사용 String의 출력 [Ex] char *p_word = “abc”; String literal “abc\0”를 memory에 저장, pointer변수 ‘p’_word에 의해 referred [Ex] char *p_word = “abc”; char word[] = “abc”; printf(“%s\n”, p_word); printf(“%s\n”, word); p_word가 refer 하는 ‘a’부터 종료 char ‘\0’까지 출력. puts(p_word);와 동일 결과 &word[0]와 같은 의미 abc
Initialization of Strings Array와 Pointer의 차이점 pointer : variable로 program 수행 중 변경 가능 array : const 로 array name의 값 변경불가 P_word가 point하는 곳의 내용이 변경되는 것이 아니라 새로 def가 저장되고 그 곳의 주소가 p_word에 대입 [Ex] char *p_word = "abc"; printf("%u\n", p_word); p_word="def"; /* ok */ 4325412 4325404 [Ex] char word[] = “abc”; word = “def”; Compile Error!!
Displaying String and characters printf() int printf(char*c, argument-list); /*function prototype */ return - no. of chars written if successful - EOF(-1) if not [Ex] int nchars; char p[ ] = “Hello! the world”; nchars = printf(“%s”, p); printf(“\nnum of chars=%d\n”, nchars); Hello! the world num of chars = 16
Displaying String and characters puts() printf()보다 fast, simple String의 출력 후, next line으로 자동 이동 int puts(char *str); /*function prototype */ return - no. of chars written if successful - EOF(-1) if not [Ex] char p[ ] = “Hi !!”; puts(p); puts(“Hello!!”); Hi !! Hello!!
Reading Strings from the KB scanf() Format의 첫 문자는 non_white space이여야 한다. %s : next white space char올 때까지 read %ns : n개의 chars 를 read, 단 그 전에 white space가 오게 되면 white space까지를 read int scanf(char *format, argument_list); return - no. of successfully matched and input items - 0 if not
Reading Strings from the KB Handong Univ. 입력 시 [Ex] char name[80]; scanf(“%s”, name); /* name <= Handong */ C-Program is 입력 시 [Ex] char name[80]; scanf(“%3s”, name); /* name <= C-P */ scanf(“%8s”, name); /* name <= rogram */ 3개의 char를 read White space올 때까지 read
Reading Strings from the KB 12345 abcdef 입력시 [Ex] /* array Size가 String length보다 작은 경우 */ char a[4], b[4]; scanf(“%s”, b); scanf(“%s”, a); printf(“%s\n%s”, a, b); /* ‘\0’까지 출력 */ Memory a a 메모리에 a, b의 저장공간(4bytes) 확보 b c b d b의 시작위치로부터 12345저장 1 e 2 f 3 \0 a의 시작위치로부터 abcdef저장 (이전 char 삭제) 4 5 \0 abcdef ef
Reading Strings from the KB gets() KB로부터 ‘\n’까지, 즉 line단위로 read ‘\n’은 자동 ‘\0’로 convert되어 string끝에 저장된다. scanf()를 통하여 String을 입력 받는 경우: white space의 skip으로 white space의 read 불가능. Line 단위로 string을 입력 받을 수 없다. char* gets(char *format); return - the address of the string - NULL if EOF (end-of-file) 수현아! Gets함수의 return type은 char*아니니? 그리고 blank line인 경우도 읽어 드린 값은 “‘\0’”이지만 return되는 것은 null char만 저장된 memory address아니니?.. 지난 번에 내가 수정한 것 같은데…. 다시 확인 바람.
Reading Strings from the KB <blank line> 입력 시 종료 [Ex] char data[81], *P; while( *(p = gets(data)) != NULL) { printf(“%s\n”, data); } 초기화가 안된 pointer변수가 올 경우 ex) gets(p) => Runtime Error!! or while( *(gets(data)) != ‘\0’) <[ctrl] + D> 입력 시 종료 [Ex] char data[81], *P; while( gets(data) != NULL) { printf(“%s\n”, data); } or while(gets(data) != 0) ^D를 입력할 때까지 line단위로 read하여 그대로 화면에 출력 하는 program
An Example: Have a Nice Day [Ex] #include <stdio.h> #include <ctype.h> #define MAXSTRING 100 int main(void) { char c, name[MAXSTRING]; int i, sum = 0; printf(“\nHi! What is your name? “); for(i=0; ( c = getchar( ) ) != ‘\n’; ++i) { name[i] = c; if(isalpha(c)) sum += c; } name[i] = ‘\0’; MAXSTRING-1만큼의 문자열을 저장할 수 있음 ‘\n’이 나오기 전까지 계속하여 입력 받음 입력 받은 문자를 array ‘name’에 저장 문자열의 마지막을 표시
An Example: Have a Nice Day [Ex] printf(“\n%s%s%s\n%s”, “Nice to meet you ”, name, “.”, “Your name spelled backward is “); for(--i; i >= 0; --i) putchar(name[i]); printf(“\n%s%d%s\n\n%s\n”, “and the letters in your name sum to “, sum, “.”, “Have a nice day!”); return 0; } char array의 내용을 역순으로 출력 Hi! What is your name? Kim Handong ꎠ Nice to meet you Kim Handong. Your name spelled backward is gnodnaH miK and the letters In your name sum to 992. Have a nice day!
Using Pointers to Process a String [Ex] /* String의 출력 */ #include <stdio.h> int main(void) { char *p; char *buffer = “Hello!”; for(p=buffer; *p != ‘\0’; p++) printf(“%c”,*p); return 0; } printf(“%s”, buffer); 와 동일 Hello!
Using Pointers to Process a String [Ex] #include <stdio.h> int main(void) { char *p= “unix”, *q; q=p; while(*p) p++; while(p>q) { p--; putchar (*p); } putchar(‘\n’); return 0; p q u n i x p \0 xinu
Using Pointers to Process a String [Ex] #include <stdio.h> #define MAXLINE 100 read_in(char s[ ]) { int c, i=0; while((c = getchar( )) != EOF && c != ‘\n’) s[i++] = c; s[i] = ‘\0’; } int main(void) { char line[MAXLINE], *change(char *); printf(“\nWhat is your favorite line? “); read_in(line); printf(“\n%s\n\n%s\n\n”, “Here it is after being changed:”, change(line)); return 0; Return value와 parameter type이 모두 char pointer 인 function prototype
Using Pointers to Process a String char *change(const char *s) { static char new_string[MAX_LINE]; char *p = new_string; *p++ = ‘\t’; for( ; *s != ‘\0’; ++s) if(*s == ‘e’) *p++ = ‘E’; else if(*s == ‘ ‘) { *p++ = ‘\n’; } else *p ++ = *s; *p = ‘\0’; return new_string; What is your favorite line? she sells sea shells Here it is after being changed: shE sElls sEa shElls
Problem Solving: Counting Words [Ex] #include <ctype.h> int word_cnt(const char *s) { int cnt = 0; while(*s != ‘\0’) { while(isspace(*s)) ++s; if( *s != ‘\0’) { ++cnt; while( !isspace(*s) && *s != ‘\0’) } return cnt;
Passing Arguments to main( ) C에서 프로그램을 실행시킬 때 command line에서 주어지는 arguments를 main( ) function에 pass. argc : command line에서 arguments의 개수 argv : arguments의 value를 전달 받기 위한 String array [Ex] int main(int argc, char* argv[]) [Ex] a.out c java pascal argc = 4 argv[0] => “a.out” argv[1] => “c” argv[2] => “java” argv[3] => “pascal”
Passing Arguments to main( ) [Ex] #include <stdio.h> int main (int argc, char * argv[]){ int count; printf(“%s\n”, argv[0]); if(argc>1){ for(count=1; count<argc; count++) printf(“argv[%d] = %s\n”, count, argv[count]); else puts(“No comand line arguments”); return 0; } 실행 프로그램의 파일명을 point > a.out hi hello ꎠ a.out argv[1] = hi argv[2] = hello
Passing Arguments to main( ) cc cal.c –o calc 로 컴파일 [Ex] /* +, -, x, *의 calculator program */ #include <stdio.h> #include<stdlib.h> /* atoi()사용을 위한 header file */ int main (int argc, char * argv[ ]){ int i, s; switch(* argv[1]){ case ‘+’ : s=0; for(i=2;i<argc;i++) s+=atoi(argv[ i]); break; case ‘-’ : s=atoi(argv[2]) – atoi(argv[3]); case ‘*’ : s=1; for(i=2;i<argc ; i++) s*=atoi(argv[ i]); case ‘/’ : s=atoi(argv[2]) / atoi(argv[3]); } printf(“%d\n”, s); calc + 2 4 6 8 ꎠ 20 calc - 5 3 ꎠ 2 calc * 7 8 1 1 ꎠ 56 calc / 5 3 ꎠ 1
String-Handling Functions [Ex] char str1[10], str2[10]; str1= “abc” ; Error!! array name은 program수행도중 변경될 수 없다. [Ex] int length=0 ; for(length = 0; str1[length] != ‘\0’; length++); String의 length를 구하는 code로 function으로 정의 시 호출하여 사용 length계산 ok라고 하신 뜻을 정확하게 이해하지 못했습니다. 제가 예제를 삽입한 이유는 length를 구할때마다 programmer가 for문을 사용해야 하는 번거로움이 있음을 보여주기 위함이었습니다. [Ex] if( str1 == str2 ); str1, str2이 point하는 data의 내용이 아닌 str1, str2의 내용, 즉 address가 같은지를 비교
String-Handling Functions char *strcat(char *s1, const char *s2); s1의 문자열 뒤에 s2의 문자열을 추가 s1은 문자열을 저장할 수 있는 충분한 메모리를 확보해야 함 char *strcpy(char *s1, const char *s2); s1에 s2의 문자열의 내용을 복사 String function의 구현 code를 몇 개 삽입하여 slide의 개수를 늘리면 좋을 것 같다. 예를 들면 strcat, strcpy중 하나, strcmp,strchr,...등 이들 중에서 2~3개 function에 대한 구현 code추가 strcat에서 충분한 memory가 확보되지 않는 경우의 예제 또는 문제점등이 추가 되면 좋을 텐데... [Ex] char str1[100] = “handong”, str2[100] = “university”; strcat(str1, str2); printf(“%s\n”, str1); strcpy(str1, str2); handonguniversity university
String-Handling Functions strcat()의 구현 [Ex] char *strcat (char *s1, const char * s2) { char *p; p=s1; while(*p != ‘\0’) p++; while(*s2 != ‘\0’){ *p=*s2; p++; s2++; } *p = ‘\0’ ; return s1; while(*p) p++; while(*p++ = *s2++); 새로 추가한 슬라이드입니다.
String-Handling Functions 충분한 메모리 확보 없이 strcat을 사용하는 경우 [Ex] #include <stdio.h> #include <string.h> int main(void) { char str1[5]="1234"; char str2[5]="abcd"; printf(“%s, %s\n", str1, str2); strcat(str1, “5678”); } str1 1 2 3 4 5 \0 str2 6 a 새로 추가한 슬라이드입니다. 7 b 8 c \0 d 1234, abcd 12345678, 678 \0
String-Handling Functions int strcmp(const char *s1, const char *s2); string을 구성하는 char의 ascii code값을 하나 씩 비교 return value < 0 : s1 이 s2 보다 ASCII 값이 작을 때 return value = 0 : s1 과 s2가 같을 때 return value > 0 : s1 이 s2 보다 ASCII 값이 클 때 size_t strlen(const char *s1); String의 길이를 return [Ex] char str1[100] = “handong”, str2[100] = “handong”; if(str1 == str2) /* false */ printf(“same address\n”); if(strcmp(str1, str2) = = 0) /* true */ printf(“equal\n”); printf(“length=%d\n”, strlen(str1)); equal length = 7
String-Handling Functions strcmp() 의 구현 strlen() 의 구현 [Ex] int strcmp(const char *str1, const char *str2){ int i=0; while(str1[ i] == str2[ i] ) { if(str1[ i] == ‘\0’) return 0; i++; } return str1[ i] – str2[ i]; 새로 추가한 슬라이드입니다. [Ex] size_t strlen(const char *s){ size_t n=0; for(n=0; *s != ‘\0’; s++) n++; return n; }
String-Handling Functions char* strchr(const char *s1, char c1); s1의 문자열중에서 가장 먼저 나타나는 문자 c1의 pointer를 return c1이 나타내는 문자가 없을 경우 null pointer를 return char* strstr(const char *s1, char* s2); strchr과 유사하지만 문자대신 sub-String을 search 없는 경우 null pointer를 return Null pointer가 아닌 ‘e’를 point하는 pointer의 return으로 결과는 true. [Ex] if(strchr(“hello”, ‘e’ )) printf(“e is in hello”); if(strstr(“hi, there”, “hi”)) printf(“found”); e is in hello found
String-Handling Functions strstr() 의 구현 [Ex] char* strstr(const char* str1, const char *str2) { int i=0, i, tmp_idx; char tmp[30]; char *start; while(str1[ i] != ‘\0’) { tmp_idx=0; start = &str1[ i]; for( j=i; j < i+strlen(str2); j++) { if(str1[ j] == ‘\0’) break; tmp[tmp_idx++] = str1[ j]; } tmp[tmp_idx] = ‘\0’; if(strcmp(tmp, str2) == 0) return start; i++; return NULL; 새로 추가한 슬라이드입니다.
수고하셨습니다. Strings and Pointers skip… 4.7 Function Declarations from the Compiler’s view Point