[C언어] 5. 문자와 문자열 관련 함수




제가 책(윤성우의 열혈 C 프로그래밍)을 보다가 까먹었던 부분만 포스팅 하는 것입니다!

순서가 뒤죽박죽이어도 이해해주세요~~!

스트림과 데이터 이동



프로그램 안으로 데이터가 흘러 들어오는 것이 입력이고, 프로그램 밖으로 데이터가 흘러 나가는 것이 출력입니다.

데이터를 입출력하기 위해 다리가 필요한데, 그 다리의 역할을 하는 매개체를 스트림이라고 합니다.

운영체제는 외부장치와 프로그램과의 데이터 송수신의 도구가 되는 스트림을 제공하고 있습니다.



스트림의 생성과 소멸



콘솔(키보드,모니터) 입출력과 파일 입출력 사이에는 차이점이 있는데,

파일과의 연결을 위한 스트림의 생성은 우리가 직접 요구하지만,

콘솔과의 연결을 위한 스트림의 생성은 요구할 필요가 없다는 것입니다~

콘솔 입출력을 위한 ‘입력 스트림’과 ‘출력 스트림’은 프로그램이 실행되면 자동으로 생성되고,

프로그램이 종료되면 자동으로 소멸되는 스트림입니다.

즉, 이 둘은 기본적으로 제공되는 표준 스트림입니다~

stdin	표준 입력 스트림	키보드 대상으로 입력

stdout	표준 출력 스트림	모니터 대상으로 출력

stderr	표준 에러 스트림	모니터 대상으로 출력



그리고 스트림은 단 방향으로만 데이터가 전송됩니다.



문자 출력 함수: putchar, fputc



모니터로 하나의 문자를 출력할 때 일반적으로 사용하는 함수는 다음과 같습니다.

#include<stdio.h>

int putchar(int c);

int fputc(int c,FILE *stream);

//함수호출 성공 시 쓰여진 문자정보가, 실패시 EOF를 반환합니다



fputc는 스트림에 stdout을 전달하면 모니터 출력하고,

파일의 스트림 정보를 전달하면 파일로도 데이터를 전송할 수 있습니다.



문자 입력 함수: getchar, fgetc



키보드로부터 하나의 문자를 입력받을 때 일반적으로 사용하는 함수는 다음과 같습니다.

#include<stdio.h>

int getchar(void);

int fgetc(FILE *stream);


//파일의 끝에 도달하거나 실패시 EOF를 반환합니다



fputc는 스트림에 stdin을 전달하면 키보드로부터 데이터를 전송받고,

파일의 스트림 정보를 전달하면 파일로부터도 데이터를 전송받을 수 있습니다.

중요한 것은 \n도 문자이기에 엔터키도 입력으로 간주합니다~

또 EOF란 End Of File의 약자로서, 파일의 끝을 표현하기 위해 정해 놓은 상수 입니다.

getchar함수와 fgetc함수는 함수호출이 실패하거나 CTRL+Z(window), CTRL+D가 입력된 경우

EOF를 반환합니다~~

단순히 문자 하나를 입출력 하는 것이 목적이라면 위의 함수를 쓰는 것이 메모리와 속도 면에서 좋습니다.



문자열 출력 함수: puts, fputs



모니터로 하나의 문자열를 출력할 때 일반적으로 사용하는 함수는 다음과 같습니다.

#include<stdio.h>

int puts(const char *s);

int fputs(const char *s ,FILE *stream);


//함수호출 성공 시 음수가 아닌 값을, 실패시 EOF를 반환합니다



fputs는 스트림에 stdout을 전달하면 모니터 출력하고,

파일의 스트림 정보를 전달하면 파일로도 데이터를 전송할 수 있습니다.

또 puts와 fputs의 차이점이 있는데,

puts 함수가 호출되면 문자열 출력 후 자동으로 개행이 이뤄지지만,

fputs 함수가 호출되면 문자열 출력 후 자동으로 개행이 이뤄지지 않습니다.



문자열 입력 함수: gets, fgets



문자열 입력 함수는 다음과 같습니다.

#include<stdio.h>

char* gets(char* s); 

char* fgets(char *s, int n , FILE *stream);


//파일의 끝에 도달하거나 실패시 NULL 포인터 반환



fputs는 스트림에 stdin을 전달하면 키보드로부터 데이터를 전송받고,

파일의 스트림 정보를 전달하면 파일로부터도 데이터를 전송받을 수 있습니다.

gets 함수는 다음과 같이 호출됩니다


int main(void)
{
	char str[7]; //7바이트의 메모리 공간 할당 
	gets(str); //입력 받은 문자열을 배열 str에 저장
}



하지만 gets는 미리 마련해 놓은 배열을 넘어서는 길이의 문자열이 입력되면 오류 발생하므로,

다음의 형태로 fgets 함수를 호출하는 것이 좋습니다.


int main(void)
{
	char str[7]; 
	//stdin으로부터 배열크기만큼(NULL문자포함) 문자열 입력 받아서 str에 저장
	fgets(str,sizeof(str),stdin); 	
}



그리고 gets와 fgets 함수는 \n을 만날 때까지 문자열을 읽어 들이는데,

gets는 \n은 문자열에서 제외시키고,

fgets는 \n을 제외시키거나 버리지 않고 문자열의 일부로 받아들입니다.

참고로 scanf 함수는 공백을 문자열로 읽어들일 수 없습니다!!



버퍼링



메모리 버퍼는 데이터를 임시로 모아두는 메모리 공간입니다

키보드를 통해 입력되는 데이터는, 일단 입력버퍼에 저장된 다음에(버퍼링 된 다음) 프로그램에서 읽혀지고,

프로그램으로부터 나오는 데이터도, 일단 출력버퍼에 저장된 다음에 모니터로 출력됩니다!

즉, fgets 함수가 읽어 들이는 문자열은 입력버퍼에 저장된 문자열 입니다~

또, 키보드로부터 입력된 데이터가 입력 스트림을 거쳐서 입력버퍼로 들어가는 시점은 엔터키가 눌리는 시점입니다~!

그렇다면 버퍼링(입출력버퍼에 저장)은 왜 하는 것일까요??

이는 ‘데이터 전송의 효율성’과 관련이 있는데,

창고에 물건을 나르는 경우,

손으로 하나씩 나르는 것보다 손수레에 가득 채워서 나르는 것이 더 빠르고 효율적이라는 것과 같은 이치입니다.



입출력 버퍼 비우기



출력버퍼를 비우는 함수는 fflush 함수이고 다음과 같습니다.

#include <stdio.h>
int fflush(FILE *stream)

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



출력버퍼가 비워진다는 것은 출력버퍼에 저장된 데이터가 버퍼를 떠나서 목적지로 이동 됨을 뜻합니다.

그리고 입력버퍼를 비울 때는 다음과 같이 입력합니다.


void ClearLineFromReadBuffer(void)
{
	while(getchar()!='/n') //  '\n'을 만날 때 까지 문자를 읽는다.
}



입력버퍼를 비운다는 것은 데이터의 소멸을 뜻합니다~!



입출력 이외의 문자열 관련 함수



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

#include <string.h>
int length=strlen(str);

//전달된 문자열의 길이를 반환하되, 널 문자는 길이에 포함하지 않는다.



//문자열을 복사하는 함수: strcpy, strncpy

#include <string.h>

char str1[30]="I like you";
char str2[30];

strcpy(str2,str1); //str1의 문자열을 str2에 복사

strncpy(str2,str1,sizeof(str2)); //str1의 문자열을 str2에 sizeof(str2)만큼 복사

//(단, null문자를 넣을 공간을 마련한 후 직접 null문자를 넣어야한다.)



//문자열을 덧붙이는 함수: strcat, strncat

#include <string.h>

char str1[30]="First~";
char str2[30]="Second";

strcat(str1,str2); //str1의 문자열 뒤에 str2를 복사

strcat(str1,str2,3); //str2의 문자열 중 최대 3개를 str1의 뒤에 복사

//(단, 3개의 문자에는 널문자가 포함되지 않으며, 뒤에 추가적으로 null문자 자동으로 삽입 됨)



//문자열을 비교하는 함수: strcmp, strncmp

#include <string.h>

printf("%d",strcmp(str1,str2)); //str1과 str2가 같으면 0 

printf("%d",strncmp(str1,str2,2)); //앞에서부터 2개의 문자가 같으면 0 



//문자열로 된 정수와 실수를 정수나 실수 데이터로 변환: atoi

#include <stdlib.h>

char str1[20]="1234";
char str2[20]="3.14";

int num1=atoi(str1);
double num2=atoi(str2);