한 것을 그대로 출력하는 것이 아니라,
불필요한 부분은 제외하고 출력하는 것
원리.
즉, 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 |