티스토리 뷰

PL/C

[C Language] 문자열 정리

SweetDev 2018. 9. 21. 00:00

참조영상

 

C언어는 다른 언어보다 까다롭다. C언어는 하드웨어와 가까운 언어이기 때문이다(저급언어같은 고급언어)! 

C의 동작원리를 이해하지 않고는 코드를 짜기가 어렵기 마련이다.

 

 

 

C언어에는 사실상 ‘문자열’이 없다. C언어에서는 문자들의 배열을 문자열로 정의하고 사용한다.

하지만 완전히 ‘문자열’의 개념이 없는 것은 아니다. %s 등을 이용해서 문자열에 접근할 수 있다. 

또한 정의할 때도, 큰따옴표(“”)로 감싸면 문자열로 정의될 수 있다.

 

예)

“Hello World!” //문자열

“A”   //문자열

‘a’  //문자

 

 

선언하기

  1. 문자 배열의 크기는 저장할 문자열 길이보다 최소 1 이상 커야한다! \0을 저장해야 하므로.
  2. 선언방법
char string[16];
char string[16]="Hello World";

 

실습

“C 프로그래밍” 을 출력해보세요

 

  1. 매크로 상수를 정의하고 사용할것
  2. for문을 이용할것
  3. 프로그래밍 이 끝나고 여백이 남지 않도록 할것

정답)

#include <stdio.h>
#define STRLNG 20
int main(){
char str[20]="C 프로그래밍";
for (int i=0; i<STRLNG; i++){
printf("%c",*(str+i));
}
return 0;
}

 

 

문자형 포인터 변수를 사용하여 문자열 가리키기

char *p = "Hello!";

 

문자열을 출력하는 다양한 방법?

선언방법

배열로 선언 vs 포인터로 선언

배열첨자 string[i] vs 포인터 이용 *(string+i) vs 배열명 (%s) vs 포인터로 %s

 

여러개의 문자열을 저장하는 방법

 

1)이차원배열 이용

char colors[3][10] = {“red”,”blue”,”white”};

 

2)포인터 배열(pointer array) 이용

==포인터의 배열

char *colors[3] = {“red”, “blue”, “white”};

 

==예제 실습==

문자열 입력: gets()와 puts()함수, sscanf()와 sprintf() 등을 이용할 수 도 있다.

gets와 puts, sscanf와 sprintf함수에 대해서는 다른 포스팅에서 자세하게 다룰 예정이다. 그래도 조금만 알아보자면, gets()와 puts() 표준입출력(standard input, output)으로부터 한번에 한 문자열을 입출력하고, sscanf()와 sprintf() 문자열로부터 입출력한다. 

 

이 포스팅에서 다룰 scanf함수버퍼를 이용한다. 이런 코드가 있다고 가정해보자.

 

#include<stdio.h>
int main(){
char ch;

int i;
for (i=0; i<3; i++){
scanf(“%c”,&ch);
printf(“%c”,ch);
}
}

내가 input으로 apple을 치면 app만 나온다. 이유는? scanf함수가 버퍼를 이용하기 때문이다. 그렇다면 버퍼는 무엇일까? 버퍼는 input으로 받은것을  저장할 수 있는 공간이라고 생각하면 된다. 

“문자를 저장할 수 있는 character형 배열”이라는 표현을 위의 유투브 강의에서 사용했는데, 적절한 표현이라고 생각한다. 

 

다만 차이가 있다면, char ch;는 우리가 직접 확보해준 공간이라면, 버퍼는 운영체제(OS)가 확보해주는것이다. 

 

코드에서 scanf함수가 어떻게 동작하는지 생각해 보자. for 문 안에서 scanf함수는 ch에 문자를 입력받으라고 명령받았다. scanf함수는 키보드로 안가고 바로 버퍼로 간다. 아까 얘기했듯, scanf함수는 버퍼로부터 입력받도록 되어있기 때문이다. 버퍼는 운영체제로 나간다. 운영체제는 콘솔 창에 깜빡깜빡... 하면서 input을 받을 때 까지 기다리고, 개행문자가 나올때까지 input을 받는다.

개행문자(엔터)를  치는 순간 버퍼에 입력되고, scanf함수의 특성 상 엔터 문자까지 같이 버퍼에 입력되게 된다. 

 

우리가 콘솔 창에 "tiger" 라는 단어를 입력했다고 가정해 보자.

 

scanf는 하나의 문자 받아서 ch에 넣는 함수이다. 처음에는 버퍼에서 t를 갖고온다. 그 다음에는 i를 갖고 온다. 그 다음에는 g를 갖고온다... 더 이상 for문이 돌지 않으므로 끝났다. 우리가 쓰지 않은  e, r, 엔터 문자는 여전히 버퍼 안에 남아있게 된다.

 

<ex>

scanf를 이용해서  문자를 받고, 엔터키가 나올 때까지 print 해 보자.

#include <stdio.h>
int main(){
char ch='0';
while(ch ! = '\n'){
scanf("%c", &ch);
printf("%c",ch);
}
return 0;
}

 

 

하지만 이렇게 하면 엔터키는 쓰이지 못한다.

while()의 조건이 input값이 엔터키가 아닌 것 이므로, enter을 받으면 더이상 루프를 시행하지 않기 때문이다.

 

 

그래도 엔터값을 쓰고싶다면? scanf함수의 반환값 쓰기

 

많은 사람들이 사용하지 않지만, 사실 scanf함수는 return값이 있다.

return값은 입력에 성공한 변수의 갯수이다.

그리고 ctrl+z 하면 -1을 반환하게 설계 되어있다. 

 

result = scanf(“%c”, &ch);
while (result != -1){
printf()
res = scanf()
}

 

이렇게 하면 엔터 쳐도 버퍼로 계속 받을 수 있어!

ctrl +z 전까지는 가능

 

scanf로 문자 받을때와 숫자받을때의 차이

근데 scanf의 버퍼에 대해서 배운게 중요한 이유?

scanf가 변환할 때 오류가 나는 경우 있어서이다.

 

scanf()함수가 숫자를 입력하는 과정

int a;

scanf(“%d”, &a);

scanf함수는 버퍼로 가서 데이터를 받아오려고 하는데 버퍼가 비어있으므로 운영체제에게 요청한다=> 커서를 깜빡이면서 키보드의 input기다린다

10치고 엔터쳤다면, 1에 대한 아스키코드, 0에 대한 아스키코드, 엔터에 대한 아스키코드가 버퍼에 들어가게 된다. 세개 다 버퍼에 들어간다. 그리고 scanf함수는 버퍼에 있는 값을 받아서 변환하게 되고, 이 때 변환문자를 이용한다. 버퍼에 있는 아스키코드를 어떻게 변환할까? %d라고 했으니 decimal로 변환하라고 알려주는 셈이다. 

 

즉 버퍼에 있을 때는 문자열의 형태이고, 정수 형태로 변환을 해서 a에 들어가게 된다! 그래서 %d보고 변환문자라고 부르는 것이다. 이러한 과정에서 어디서 오류가 날 수 있는지 살펴보자.

 

(예) 학번과 학점을 입력받는 프로그램이 있다고 해보자

 

int num;
char grade;
scanf(“%d”, &num);
scanf(“%c”, &grade);

20186570 엔터 

이렇게 해버리면 num에는 잘 들어가지만 엔터가 남아서 바로 %c가 끝나버려!

 

어떻게 해결할까?

1)버퍼를 비워버린다

2)\t%c 나 \n%c이용해서 해결

 

getchar를 이용해보자!

scanf보다는 문자에 특화된 함수

 

char ch;
ch = getchar();
while(ch ! = ‘\n’){
 putchar(ch);
 ch = getchar();
}

getchar역시 scanf함수처럼 버퍼로 간다

버퍼에 아무것도 없으니까 OS에 버퍼에 데이터좀 채워달라고 해서 커서 깜빡깜빡하게 만들어줌

 

결론: scanf함수든 , getchar함수든 키보드를 이용해서 입력할때는 버퍼를 쓴다

 

버퍼를 지우는 함수는? fflush

fflush(버퍼 이름)

하면 되는데 사실 메모리에는 여러개의 버퍼 있을 수 있어

입력에 사용하는 버퍼는 stdin

ffush(stdin); 해주면 버퍼 지워진다

 

'PL > C' 카테고리의 다른 글

[C] for문의 동작 순서  (0) 2019.05.31
[C언어] C언어로 전화번호부 만들기  (0) 2018.11.05
C언어로 틱텍토 만들기  (0) 2018.11.05
typedef 쓰기  (0) 2018.10.05
구조체  (0) 2018.10.05
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함