본문 바로가기

C_Data Structure_Algorithm/C String

5) (예제2)C isspace, read_line(줄단위 읽기 )

한 것을 그대로 출력하는 것이 아니라,

불필요한 부분은 제외하고 출력하는 것

원리.


즉, imput 을 보면, 공백을 입력받기도 하는데, 이와 같이 불필요한 입력값들은 저장하지 말고, 필요한 것들만 compressed 라는 이름의 문자배열에 저장해서 출력하기.

공백은 제거

필요한 값들은 저장하기.

IS 뒤에 있는 공백은 저장하되, 그 뒤에 이어지는 공백 2개는 없애야지

그렇다면 어떻게 이것을 가능하게 하냐

어떻게 필요한 공백을 선별적으로 추출할 수 있는가

우선 문자는 다 compressed 에 저장하기

공백을 보면, 그것을 compressed 에 저장할지 말지, 선택하는 코드를 넣기.

를 어떻게 해 ?

현재 compressed 에서 화살표는 compressed 의 i 번째 문자.이다.

만일 " i - 1 " 번째에, 공백이 아닌 문자가 저장되어 있다면,

이 공백은 저장을 해야 하지만,

이 공백을 저장하고 나면, i 가 한칸 전진하여 compressed[ 3 ] 을 가리키게 될 것이다. compressed[ 2 ] 에는 공백이 저장되어 있고,

그 다음 공백을 읽을 때는 이제 i - 1 번째, 즉, compressed [ 2 ]에는 공백이 저장되어 있겠지. 이는 2개 이상의 공백이 연속되어 있다는 뜻이다. 그래서 이번에 만나는 공백은 무시하면 된다.

아래는 위의 원리를 반영한 코드이다.

즉, 돌아가는 원리는 다음과 같다.

compressed[ ] 는, 우리가 문자열을 저장할 배열이다.

i 는 처음에 0에서 시작,

while 에서 한문자씩 읽어서 그것이 '\n' 을 만날 때까지 반복한다.

그리고, 그것이 특정한 조건을 만족할 때만

compressed[ i++ ] = ch; 와 같이 저장한다.

그런데 왜 if ( i < limit - 1) 이야 ?

왜냐하면, 우리가 compressed [ i ] = '\n' 와 같이, 줄바꿈 문자를 추가해야 하니까.

( ! isspace( ch ) || i < 0 && ! isspace ( compressed [ i -1 ] ) )

isspace : 어떤 문자가, 공백, tab등 눈에 보이지 않는 문자이냐 아니냐를 검사해주는 것.

물론, 이것을 ch ! = ' ' 이라고 해도 된다 ( 공백이 아니다 )

같은 얘기이므로, 하지만 이렇게 하는 것보다

! isspace( ch )

이렇게 하게 되면, 공백이 아니더라도, tab 등의 다른 입력값에 대해서도 적용이 가능하다.

! isspace (ch )

즉, 어떤 문자가 "공백, tab등 눈에 보이지 않는 문자" 가 아니라면,

저장을 해야 하는 것이고

( ! isspace ) || : 즉, 혹은,

( i > 0 ) && ( ! isspace ( compressed [ i -1] )

i 가 0이라면 무시한다.

즉, i 가 0이라는 것은 무슨 말인가 ?

 

( i = 0 ) && ( ! isspace ( compressed [ i -1] )

i 가 0 이라는 얘기는, ( compressed 배열 기준으로 보자 )

아직 공백이 아닌 문자가, 하나도 입력되지 않았는데, 얘는 공백이다 ! 라는 것이다.

이 경우에는 그냥 무시하면 된다.

그래서 i > 0 이 되는 것이다.

 

( i > 0 ) && ( ! isspace ( compressed [ i -1] )

즉,

i 가 0은 아니면서,

( ! isspace ( compressed [ i -1] )

직전의 문자, i - 1 번 위치.

직전에 저장되어 있는 문자가 공백이라면 무시,

공백이 아닐때만 그 공백 문자를 저장

즉, i 가 0보다 크면서,

즉, 이미 저장되어 있는 문자가 1개 이상이면서,

직전에 저장된 문자가 공백이 아닐 때에만,

설령 그것이 공백이더라도

copressed [ i ++ ] = ch ; 를 통해 저장하는 것이다.

봐봐, ? 이랑, \n 사이에 공백이 2개가 있잖아,

그런데 ? 다음에 공백은,

직전에 공백이 아닌 문자 즉, ? 가 있으니까,

compressed 문자열에 저장된다.

그리고 \n은 문자이므로, 자연스레 compressed 에 저장되겠지.

여기서 문제는 우리가 compressed 라는 배열을 총 출력하게 되면,

? 랑 \n 사이에 불필요한 '공백' 도 포함되어 출력되는 것이지.

그렇다면 우리는 이 불필요한 '공백'을 지워줘야 한다.

이것을 제거해 주기 위해서,

if ( i > 0 && isspace ( compressed [ i - 1 ] ) )

즉, i 가 0보다 크면서, 즉, 적어도 하나 이상의 문자가 저장되면서 !!

만약 i > 0 이 조건이 없으면 어떤 일이 발생할까 ?

만약 아무것도 입력하지 않고, 엔터키를 누르게 되면,

int main( ) {

char line[80];
while( 1 ){
	printf("$ ");
	int length = read_line_with_compression( line , 80 );
	printf( "%s: %d\n" , line , length ) ;
}
return 0;
}

int read_line_with_compression( char compressed[], int limit) {

int ch , i = 0;

while ( ( ch = getchar( ) ! = '\n') {

if ( i <limit -1 && ( ! isspace ( ch ) || i > 0 && ! isspace ( compressed [ i-1 ] ) _) )

compressed [ i ++ ] = ch ;

}

if ( isspace( compressed [ i -1 ] )
	i--;
compressed[i] = '\0'

return i ;

}

 

즉, 위에 while 문에서, 아무것도 입력이 안됬을 때, 그냥 바로 while 문을 빠져나와서,

if ( isspace( compressed [ i -1 ] )

이 부분을 만날 것인데, 그러면 i 가 0 인데,

compressed [ i -1 ] 을 실행하게 된다.

그렇기 때문에 compressed [ -1 ] 에 대한 검사가 되므로

run 타임 오류가 된다.

int main( ) {
    
    char line[80];
    while( 1 ){
    	printf("$ ");
    	int length = read_line_with_compression( line , 80 );
    	printf( "%s: %d\n" , line , length ) ;
    }
    return 0;
    }
    
    int read_line_with_compression( char compressed[], int limit) {
    
    int ch , i = 0;
    
    while ( ( ch = getchar( ) ! = '\n') {
    
    if ( i <limit -1 && ( ! isspace ( ch ) || i > 0 && ! isspace ( compressed [ i-1 ] ) _) )
    
    compressed [ i ++ ] = ch ;
    
    }
    
    if ( isspace( compressed [ i -1 ] )
    	i--;
    compressed[i] = '\0'
    
    return i ;
    
    }

 

i > 0 이라는 조건을 넣은 다음에

i — 을 해준다는 것은, i 값을 1 줄여주기

여기서 i 는 입력된 문자열, compressed 배열의 길이를 표현해주기 때문에.

i 를 1 줄여주면, 문자열의 길이가 1 줄어든다고 생각하면 되는 것이다.

return i ;

를 하게 되면,

이렇게 return 된 값이 length 가 된다.

'C_Data Structure_Algorithm > C String' 카테고리의 다른 글

4) (예제1)scanf, fgets, gets 함수 차이점  (0) 2020.02.26
3) 파일로 입출력하기  (0) 2020.02.26
2) 문자열 기본 함수  (0) 2020.02.25
1) 문자열 개요  (0) 2020.02.25