C언어 문자열과 관련한 내용을 정리한다


스트림

. 스트림(Stream)은 특정한 프로그래밍 언어 및 운영체제에서 컴퓨터 프로그램과 구동 환경 간에 미리 연결된 일종의 입출력을 위한 통로

1
2
3
stdin			표준 입력 스트림		키보드 대상 입력
stdout			표준 출력 스트림		모니터 대상 출력
stdeer			표준 에러 스트림		모니터 대상 출력

. 해당 스트림은 프로그램 시작과 동시에 자동으로 형성되고, 종료 시 자동으로 삭제 됨

문자 단위 입출력

1
2
3
4
5
6
7
8
9
...
// 하나의 문자 출력
int putchar(int a);						// 인자로 전달된 단일 문자 모니터에 출력
int fputc(int a, FILE * stream);		// FILE * stream을 통해 출력 대상 지정 가능	
	
// 하나의 문자 입력
int getchar(void);						// 키보드로 입력된 단일 문자 반환
int fgetc(FILE * stream);				// 문자를 입력 받을 대상정보 인자로 전달
...  

. 함수 호출 실패 시 EOF 반환 (입력의 경우, 파일의 끝에 도달하여도 EOF 반환)

EOF (End of File)

. 파일의 끝을 표헌하기 위해 정의해 놓은 상수, int형 데이터로 -1

. EOF 반환을 putchar, fputc, getchar, fgetc 에서 파악하기 위해 반환형을 int 로 지정함

. 함수 호출이 실패하였을 때, 파일의 끝에 도달하였을 때, 윈도우에서 CTRL + Z, 리눅스에서 CTRL + D 입력 시 발생

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>

int main(void)
{
	int ch;
	while(1){						// 입력된 문자는 EOF를 만날 때 까지 버퍼에 유지
		ch = getchar();
     	if(ch == EOF)		
        	break;
     	putchar(ch);
  	}
	return 0;
}

3

문자열 단위 입출력

1
2
3
4
5
6
7
8
...
// 문자열 출력
int puts(const char * s);							// 자동 개행
int fputs(const char * s, FILE * stream);			// 자동 개행 없음, 출력 대상 지정 가능

// fputs의 사용
fputs(str, stdout); printf("\n");					// 자동 개행이 없기 때문에, 강제 개행 필요
...

. 함수 호출 성공 시 0 반환, 실패 시 EOF 반환

1
2
3
4
5
6
7
8
9
10
11
12
...
// 문자열 입력
char * gets(char * s);								// 메모리 오버플로어 문제가 발생할 수 있음
char * fgets(char * s, int n, FILE * stream);		// n -> 일반적으로 sizeof(type)-1만큼 입력

// 사용 방법 
char str[10];

gets(str);
fgets(str, sizeof(str), stdin);						// 공백, 엔터 입력도 문자열로 받아들이고 저장
while(getchar() != '\n');							// 버퍼 비움 !? 맞는지 확인 필요
...  

. 파일 끝에 도달 or 함수 호출 실패 시 NULL 포인터 반환

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>

int main(void)
{
  char str[10];
  int i;
  
  for(i=0; i < 2; i++)
  {
    fgets(str, sizeof(str), stdin);
    printf("Read %d: %s \n", i+1, str);
  }
  return 0;
}

4

. 출력 결과를 보면, 개행이 두 번 이루어짐

. 이는 입력 시의 Enter \n 가 문자열에 포함되고, fgets 함수의 동작으로 인해 입력 문자열에 자동으로 개행문자가 삽입되었기 때문

표준 입출력 버퍼

1
2
3
4
5
6
7
...
int fflush(FILE * stream);							// 출력 버퍼를 지움
													// 출력 버퍼에 저장된 데이터를 목적지로 전송함

while(getchar() != '\n');							// 입력 버퍼를 비우기 위한 명령
													// 일반적으로 함수로 구성
...

. 함수 호출 성공 시 0, 실패 시 EOF 반환

. 입력 버퍼의 경우, 버퍼를 비우면 데이터가 소멸됨

기타 함수

문자열 길이 반환

. NULL 값을 발견할 때 까지, 문자를 카운팅함

1
2
3
4
5
#include <string.h>
...
// typedef unsigned int size_t;
size_t strlen(const char * s);
...

문자열 복사

1
2
3
4
5
#include <string.h>
...
char * strcpy(char * dest, const char * src);
char * strncpy(char * dest, const char * src, size_t n);
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <string.h>

int main()
{
    char str1[20] = "1234567890";
    char str2[20];
    char str3[5];
    
  	
    strcpy(str2, str1);    // 두 배열의 크기가 동일해야 함
    puts(str2);
    
  	/** error case **/
    strncpy(str3, str1, sizeof(str3));  // strncpy는 Null값 관계 없이 복사
                                        // NULL 값의 유무 판단 안함, 단순 복사
    puts(str3);
    
    strncpy(str3, str1, sizeof(str3)-1);    // NULL 값 위한 공간 확보
    str3[sizeof(str3)-1] = 0;               // NULL 값 대입
    puts(str3);
    
    return 0;
}

1

. error case 에서 str1에서 str3의 복사시, NULL 값의 유무와 관계 없이 데이터 단순 복사

. 따라서, str3을 출력 시, 문자열의 끝인 NULL값을 찾지 못하여, 쓰레기 값 출력

문자열 붙이기

1
2
3
4
5
#include <string.h>
...
char * strcat(char * dest, const char * src);
char * strncat(char * dest, const char * src, size_t n);	// 자동 NULL 값 삽입
...

문자열 비교

1
2
3
4
5
6
7
8
9
#include <string.h>
...
// s1 > s2 == +
// s1 < s2 == -
// s1 == s2 == 0
  
int strcmp(const char * s1, const char * s2);
int strncmp(const char * s1, const char * s2, size_t n);
...

문자열 형변환

1
2
3
4
5
6
#include <stdlib.h>
...
int atoi(const char * str);			// 문자열 -> int 형
int atol(const char * str);			// 문자열 -> long 형
int atof(const char * str);			// 문자열 -> double 형
...