레이블이 string인 게시물을 표시합니다. 모든 게시물 표시
레이블이 string인 게시물을 표시합니다. 모든 게시물 표시

2015년 7월 15일 수요일

자바(JAVA)의 문자열 객체 String, StringBuilder, StringBuffer 비교


 자바에서 문자열을 저장하는데 사용되는 객체는 String, StringBuilder, StringBuffer 세 가지가 있다. 보통 문자열을 저장하는데 String 객체를 사용하지만 문자열을 빈번하게 수정할 필요가 있는 경우 String 객체보다는 StringBuilder 객체가 성능면에서 더 유리하다.

[표 1] 문자열 저장 객체간 비교
클래스명
특징
성능
메모리
String
불변하는 문자열 저장시 주로 사용

가장 낮다.
StringBuilder
수시로 가변하는  문자열 저장시 주로 사용
가장 높다.

StrungBuffer
다른 쓰레드 간 동기화가 필요한 경우 StringBuilder대신 사용



가변하는 문자열을 다루는데 있어서의 속도를 알아보기 위해서 다음과 같은 간단한 벤치마크 프로그램을 실행해 보았다. (JDK8 이용)


package tut_20;
import static java.lang.System.nanoTime;
public class Tut_20 {
 public static void main(String[] args) {
     long ls, le;
     long iter = 100000;

     ls = nanoTime();
     String str = "";
     for (int k = 0; k < iter; k++) {
         str += 'a';
     }
  System.out.println("String       :"+(nanoTime()-ls)/1e9+ "sec.");
       
       ls = nanoTime();
       StringBuilder strb = new StringBuilder();
       for (int k = 0; k < iter; k++) {
           strb.append('a');
       }
 System.out.println("StringBuilder:"+(nanoTime()-ls)/1e9+ "sec.");
       
       ls = nanoTime();
       StringBuffer strbf = new StringBuffer();
       for (int k = 0; k < iter; k++) {
           strbf.append('a');
       }
 System.out.println("StringBuffer :"+(nanoTime()-ls)/1e9+ "sec.");     
   }
}
실행 결과
String       :4.884195203sec.
StringBuilder:0.001943612sec.
StringBuffer :0.0015706sec.

결과는 보다시피 StringBuilder가 가장 빨랐고 StingBuilder 와 StringBuffer 는 차이가 별로 나지 않았다. (JDK5 이상에서는 String 객체도 수정이 일어날 때 내부적으로 StringBuffer로 변환되어 사용된다고 알고 있었는데 좀 의외다.)

 다음으로 문자열 내에서 검색하는 속도를 마찬가지로 간단한 프로그램을 실행하여 측정해 보았다. (JDK8 사용)

package tut_20;
import static java.lang.System.nanoTime;
import java.util.Random;

public class Tut_20 {
   public static void main(String[] args) {
       long ls, le;
       long iter = 100000000;

       String str = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG";
       int len = str.length();
       char ch;
       Random rand = new Random();

       ls = nanoTime();
       for (int k = 0; k < iter; k++) {
           ch = str.charAt(rand.nextInt(len));
       }
 System.out.println("String       :"+(nanoTime()-ls)/1e9+ "sec.");
       
       StringBuilder strb = new StringBuilder(str);
       ls = nanoTime();
       for (int k = 0; k < iter; k++) {
           ch = strb.charAt(rand.nextInt(len));
       }
 System.out.println("StringBuilder:"+(nanoTime()-ls)/1e9+ "sec.");
       
       StringBuffer strbf = new StringBuffer(str);
       ls = nanoTime();
       for (int k = 0; k < iter; k++) {
           ch = strbf.charAt(rand.nextInt(len));
       }
 System.out.println("StringBuffer :"+(nanoTime()-ls)/1e9+ "sec.");
   }
}
실행 시간
String       :1.258389526sec.
StringBuilder:1.414282314sec.
StringBuffer :3.205902914sec.

결과에서 나타났듯이 String 이 근소하게 StringBuilder 에 비해서 빨랐다.

 따라서 다음과 같이 정리해 볼 수 있겠다.

  1. 수정될 필요가 없는 문자열은 String 객체로 사용한다.
  2. 빈번에게 수정되는 문자열을 다룰 때는 StringBuilder 객체를 사용한다.
  3. 빈번에게 수정될 뿐만 아니라 서로 다른 쓰레드간 동기화를 시켜야 할 경우에는 StringBuffer를 사용한다.

2015년 7월 7일 화요일

자바(JAVA) 문자열 객체와 System.out.println()함수

 자바에서는 문자열(string)을 처리할 수 있는 String 클래스를 제공한다. 클래스에 대해서는 아직 설명하지 않았지만 문자열은 간단하게라도 알고 넘어가야 한다. 자바에서 문자열은 기본형이 아니라 참조형이고 큰따옴표를 이용하여 표현한다. 그리고 문자열 변수를 선언/초기화하는 것은 String은 클래스이지만 기본형의 변수를 선언하고 초기화하는 방법과 동일하다.

String name; //문자열 선언
name = “홍길동”; // 문자열 초기화

String title = “선생님”;//선언과 동시에 초기화

다음과 같이 화면에 출력할 수도 있다.

System.out.println(name); // name 문자열의 내용이 화면에 출력된다.

두 개의 문자열을 서로 연결하는 데 ‘+’연산자를 이용할 수도 있다.

String fullName = name + title; // 두 문자열 연걸
String sayHi = “안녕하세요. “ + name;
String sayHello = “안녕하세요. “ + name + title; //세 개 이상도 연결 가능

다음과 같이 System.out.println() 함수에 문자열 연결식을 직접 입력할 수도 있다.

System.out.println(“안녕하세요. “+name+”씨.”);

이렇게 하면 불필요한 문자열 변수를 생성하지 않고 직접 연결된 문자열을 화면에 출력할 수 있다.

 어떤 기본형 변수의 값을 출력할 때에도 System.out.println()함수를 사용할 수 있다.

double da = 11.2;
System.out.println(da);

함수 System.out.println() 는 문자열을 인자로 주어야 하는데 이경우 변수값 da는 내부적으로 문자열로 자동으로 변환되어서 System.out.println()에 그 문자열을 넘겨준다. 따라서 다음과 같이 연결하는 것도 가능하다.

double da = 11.2;
System.out.println(“da 값은 “ + da + “입니다.”);

이 경우 연결이 일어나기 전에 da값은 문자열로 변환되어 세 개의 문자열을 연결한 새로운 문자열이 System.out.println()에 인자로 넘어가는 것이다.

2015년 6월 25일 목요일

MATLAB의 문자열(string)과 관련 함수

 MATLAB에서 행렬의 원소로 문자열을 사용하는 것이 가능하다. 문자열은 작은 따옴표나 큰따옴표로 묶는다.

>> A=['hi']
A = hi
>> B="there"
B = there

두 번째 예를 보면 문자열은 그 자체로 행벡터임을 알 수 있다.. 벡터의 각 요소는 하나의 문자인 것이다. 따라서 행렬의 인덱싱도 가능하다.

>> size(B)
ans =
  1   5

>> B(3)
ans = e

>> B(1)="T"
B = There

따라서 다음과 같이 두 행렬을 한 행렬로 표현함으로써 문자열의 합성도 가능하다.

>> C=[A B]
C = hiThere

문자열 행렬도 생성 가능한데 문자열 자체가 행벡터이므로 한 행에 하나의 문자열을 지정해 주면 된다.

>> D=['hi';'there']
D =
hi
there

>> size(D)
ans =
  2   5

위의 예에서 행렬 D는 첫 번째 행의 크기는 2(문자)이고 두번째 행의 크기는 5(문자)인데 행렬이 구성되었다. 이경우 빈 곳은 공백문자로 채워진다.

 문자열 관련 함수들은 다음과 같다.

[표 1] 문자열 관련 함수들
함수
기능
strcat(s1, s2, …)
strvcat(s1,s2,...)
문자열들을 하나의 행벡터로 합친다.
문자열들을 한 행렬로 합친다.(각 문자열을 별도의 행으로 지정)
char(x)
숫자(아스키코드) 행렬로 부터 문자열을 생성한다.
ischar(x)
x가 문자열이면 논리1(true)반
num2str(x)
숫자를 문자열로 바꾼다.
sprintf(FORMAT, A,B,...)
C 언어의 printf() 와 같은 기능을 수해하여 문자열 생성
lower(s)
upper(s)
문자열을 소문자로 변환
문자열을 대문자로 변환
strcmp(s1,s2)
s1과 s2가 같다면 논리1(true)반환, 그렇지 않다면 논리0(flase)반환
findstr(s1,s2)
둘 중 긴 문자열에서 짧은 문자열이 시작되는 인덱스 반환


2015년 6월 17일 수요일

싸이랩(scialb)의 문자열을 실행하는 함수

 Scilab명령어를 담은 문자열을 실행시킬 수 있는 명령어들이 있다. 세 개가 있는데 다음 표에 정리하였다.

[표 1] 문자열을 실행시키는 함수들
함수명
기능
execstr
Scilab 명령 문자열을 실행한다.
eval
evstr
Scilab expression 실행(행렬 반환)
위와 기능은 동일하나 에러를 traping할 수 있음
 먼저 execstr()은 Scilab 명령을 담은 문자열을 실행하는 것이다. (MATLAB의 eval 함수의 기능에 해당됨.)
>> execstr('a=1+sin(%pi/2)')
>> a
a  =
    2.  
이 예에서 보듯이 execstr()함수는 세미콜론이 붙지 않은 명령이라도 그 결과를 콘솔창에 표시하지 않는다. 만약 문자열에 명령 에러가 있다면 execstr()함수는 실행이 멈추게 된다. 다음 예를 보자.
>> execstr('a=2#4'), c=%i
 a=2#4
     !--error 276
Missing operator, comma, or semicolon.
in  execstr instruction    called by :  
execstr('a=2#4'), c=%i
이 예에서 ‘a=2#4’라는 명령은 문법 오류가 있으므로 거기서 실행이 멈춰버리고 에러메서지를 밷는다. 따라서 c=%i 라는 그 뒤의 명령은 실행되지 않는다.

만약 실행을 멈추지 않고 에러의 발생 여부를 처리하고 싶다면 다음 예와 같이 옵션을 사용하면 된다.

>> ier = execstr(['a#2','b=%pi'], 'errcatch','n'), c=%i
ier  =
   4.  
c  =
   i    
   
두 번째 인수로 ‘errcatch’ 를 주었는데 이것은 에러가 발생하면 실행을 멈추지 말고 단순히  ier에 그 결과를 반환하라는 것이다. 세 번째 인수가 ‘n’ 이라면 에러의 개수를 ‘m’ 이라면 에러메세지를 반환하다. 이 경우는 execstr()함수 뒤의 c=%i 가 실행된다는 점이 앞으 경우와 다르다. execstr()함수에는 두개의 명령 ‘a#2’ 와 ‘b=%pi’ 가 들어갔는데 두 번째 명령은 오류가 없음에도 첫 번째 명령에 에러가 있으면 두 번째 것이 실행되지 않고 에러를 캐치하고 넘어가 버린다. 따라서 변수 b도 생성되지 않고 c만 생성이 된 것이다.
 함수 eval()과 evstr()은 문자열 행렬의 값을 구해서 행렬로 반환해 주는 함수이다. 두 함수의 차이점은 에러를 캐치할 수 있느냐(evstr 함수), 없으냐(eval)이다. 예를 들면 다음과 같다.
>> a=%i; b=%e;
>> A=eval(['a' 'b'; 'a+b' 'a-b'])
A  =
   i                  2.7182818        
   2.7182818 + i    - 2.7182818 + i  

 evstr()함수는 두 번째 출력 인수를 지정해 주면 그것에 에러의 번호를 반환하고 함수 자체는 실행이 멈추지 않고 정상적으로 종료된다.

>> A=eval(['a' 'c'; 'a+b' 'a-b']); d=10;
!--error 4
Undefined variable: c
at line       3 of function %eval called by :  
at line      20 of function eval called by :  
A=eval(['a' 'c'; 'a+b' 'a-b']); d=10;
 
이 예에서 eval()함수 내부의 c변수는 없는 변수이므로 에러를 발행하고 실행이 거기서 멈춰버린다. 따라서 뒤에 있는 d=10; 이라는 명령은 실행되지 않는다. 반면에 다음 예를 보자.
>> [A,ier]=evstr(['a' 'c'; 'a+b' 'a-b']); d=10;
>>d
d  =
   10.

이 예에서 evstr()은 eval()과 같은 일을 수행하지만 만약 에러가 발행한다면 두 번째 출력인수 ier에 에러의 코드를 반환하고 정상적으로 종료한다. 따라서 그 뒤에 오는 명령인 d=10;도 정상적으로 수행된다.


싸이랩(scialb)의 문자열 조작

 함수  part() 는 문자열의 일부분을 추출하는 기능을 수행한다.
       ❶ part(str, n) // 문자열 str의 n번째 문자 추출
       ❷ part(str, n1:n2) // 문자열 str의 n1번째 부터 n2번째 까지 추출
       ➌ part(str,[n1, n2, n3…]) // 문자열 str의 n1, n2, n3… 번째 문자들을 추출하여 단일 문자열로 반환
예를 들면 다음과 같다.

>> str = "This is a sample string."
str  =
This is a sample string.  

>> strp1 = part(str, 4)
strp1  =
 s  

>> strp1 = part(str, 6:9)
strp1  =
 is a  

>> strp1 = part(str, [11 13 15 19])
strp1  =
 smlt  
만약 입력문자의 크기가 넘어가는 문자열의 범위를 지정하면 공백 문자로 채워진다. 이 예제에서 str의 길이는 24이다. 다음 예는 24를 넘어가는 인덱스에 대해서는 공백문자로 채워짐을 보이고 있다.
>> '|'+part(str,20:30)+'|'
ans  =
|ring.      |
 함수 grep(vstr1, str2)은 문자열 벡터 vstr1 의 요소(문자열) 중에서 str2가 포함된 것의 인덱스를 반환한다. 예를 들어서 다음과 같이 문자열 벡터가 정의되었다고 하자.

>> str1 = ['abcdefghijk', 'xyz', 'jklm']
이후에 grep()함수를 사용했을 때의 결과는 다음과 같다.

>> grep(str1, 'jk')
ans  =
   1.    3.  
 
즉, str1의 첫 번째와 세 번째 요소(문자열)에 ‘jk’라는 문자열이 포함되었다는 것이다. 검색할 문자열이 두 개 이상이라면 이것들을 요소로 하는 문자열 벡터를 두 번째 인수로 넣어주면 된다.
>> grep(str1, ['jk','y'])
ans  =
     1.    2.    3.  

이 예에서는 str1 문자열 벡터의 요소 중에서 ‘jk’ 나 ‘y’ 를 포함하는 것의 인덱스를 구한다.
 함수 strindex(str1, vstr2)는 문자열 str1에서 vstr2 가 시작되는 지점의 인덱스를 구해준다.

>> str1 = '[12.34;56.789;10.123]'
str1  =
 [12.34;56.789;10.123]  

>> strindex(str1, ';')
ans  =
    7.    14.  

>> strindex(str1, [';', '.', ']'])
ans  =
    4.    7.    10.    14.    17.    21.  
 
이 함수 strindex()의 첫 번째는 반드시 단일 문자열이어야 하며 결과 값은 이 문자열의 첫 문자를 1로 보았을 때의 인덱스 값이다. 위의 예들 중 마지막 예에서는 str1 문자열에서 앞에서부터 ‘;’ 또는 ‘.’ 또는  ‘]’ 인 것의 인덱스를 차례로 찾아서 반환해 준다.
 함수 sci2exp()는 입력을 Scilab 명령의 문자열로 변환시켜 준다.
>> A=[1 2;%i, %pi]
A  =
   1.     2.        
   i      3.1415927  

>> str3 = sci2exp(A)
str3  =
 [ 1, 2;%i, 3.1415927]  

>> typeof(str3)
ans  =
 string