[아두이노] [강좌] 18. String (1) - 문자형(char) 배열과 String
이번 강좌는 비교적 간단하니까 쉬어가는 페이지인걸로.
String은 문자열을 쉽게 사용할 수 있게 하기 위해 아두이노에서 제공하는 클래스이다. 개인적으로는 다른 문법의 String 클래스보다 쓰기 쉽고 유용하다고 생각한다. 출력형 변수(%d, %s 등)를 사용할 수 없다는 점은 조금 아쉽지만.
MFC나 자바 등의 객체 지향 언어를 사용해보지 않은 사람은 String이라는 클래스가 낯설지도 모르겠다. “char*” 형태 또는 “char a[]” 형태의 문자 배열이 익숙할지도. 아두이노에도 당연히 문자 배열을 사용할 수 있지만, 이 문자 배열을 더 효율적이고 유용하게 사용하기 위해String이라는 클래스를 제공하고 있다.
String의 첫 문자가 대문자라는 것에 유의.
우선 두 개의 예제 소스를 살펴볼까? 두 개의 문자열을 저장한 후 하나로 합해서 시리얼 모니터로 출력하는 예제이다. 하나는 문자 배열을 사용하고, 하나는 String 클래스를 사용해서.
CharArrayTest.ino |
char string1[] = "Hello,"; char string2[] = "Arduino."; char stringSum[32] = "abcdefghijklmnopqrstuvwxyz";
void setup() { Serial.begin(9600); }
void loop() { int cnt=0; for(int i=0; i<6; i++) { stringSum[cnt++] = string1[i]; }
for(int i=0; i<9; i++) { stringSum[cnt++] = string2[i]; }
Serial.println(stringSum); while(1) ; } |
엇, for() 반복문이 처음 나왔나? for() 문은 정해진 횟수만큼 반복하는 함수이다. for() 문에 대한 자세한 내용은 마지막의 “*참고”를 참조.
우선 문자형 배열을 사용하는 예제 소스이다. ‘string1’이라는 문자형 배열에 “Hello,”라는 문자열을 저장하고, ‘string2’라는 문자형 배열에 “Arduino.”라는 문자열을 저장했다. 그리고 ‘stringSum’이라는 문자형 배열을 32바이트 크기로 할당한 후 "abcdefghijklmnopqrstuvwxyz"라는 문자열로 초기화한다.
문자형 배열은 선언과 동시에 문자열로 초기화할 경우 자동으로 해당 문자열의 크기만큼 크기가 정해지기 때문에 ‘string1’ 배열의 길이는7, ‘string2’ 배열의 크기는 9가 된다. 읭? 왜? “Hello,”는 6글자이고 “Arduino.”는 8글자인데? 모든 문자열은 문자열의 끝임을 알리는 ‘\0’이라는 문자(널(NULL) 문자라고 읽으며, ‘\’와 ‘0’을 합해서 하나의 문자로 취급한다)가 붙기 때문에 실제 문자의 개수보다 하나가 많게 된다는 점.
그래서 loop() 함수에서 for() 반복문으로 stringSum 배열에 문자를 복사할 때, ‘string1’은 문자 개수만큼 6번 반복했지만 ‘string2’는 마지막 문자 ‘\0’까지 복사하기 위해 문자 개수에 1을 더한 9번을 반복한 것이다.
아두이노 보드에 업로드 한 후 결과를 확인해보자.

‘string1’ 문자열과 ‘string2’ 문자열이 더해진 “Hello,Arduino.” 문자열이 출력됐다.
만일 끝 문자 ‘\0’를 복사하지 않으면 어떻게 될까? 두 번째 for() 반복문을 “for(int i=0; i<8; i++)“로 바꿔서 업로드 해보자.

Serial.print() 또는 Serial.println() 함수에서는 문자열이 입력됐을 때 ‘\0’ 문자를 문자열의 끝으로 인식하고 출력한다. 즉 ‘\0’ 문자가 나올 때까지 값을 출력한다는 말.
원래 ‘stringSum’ 배열에는 “abcdefghijklmnopqrstuvwxyz”라는 문자열이 저장되어 있었고, for() 반복문으로 0번째 문자부터 차례로 덮어썼고, ‘\0’ 문자가 없으니 stringSum[] 배열의 값을 모두 출력한 것. 처음 저장된 “abc…”에도 ‘z’ 다음에 ‘\0’이 저장되어 있었을 것이므로 ‘z’까지 출력한 후 완료.
즉, ‘\0’로 문자열을 끝내주지 않으면 원하지 않는 문자들까지 출력될 수 있다는 말이다. ‘\0’은 컴파일러에서 자동으로 문자열의 끝에 붙이게 되어 있지만, 만일 배열의 길이가 문자열의 길이보다 작거나 같다면 ‘\0’ 문자를 저장하지 못한다. 때문에 문자 배열의 길이를 정해두고 사용해야 할 경우에는 반드시 문자열의 길이보다 1만큼 크게 설정해야 한다.
만일 문자열을 중간에 끊고 싶다면 강제로 ‘\0’ 문자를 넣어줄 수도 있다.
stringSum[14] = ‘\0’; |
요렇게.
의외로 ‘\0’ 문자 때문에 쓰레기 값이 출력되고, 원인을 찾지 못하는 경우가 많으므로 유의해두도록 하자. 참고로 ‘\0’ 문자는 아스키 코드로 ‘0’이므로, ‘\0’이라는 문자 대신 숫자 ‘0’을 넣어도 된다.
자, 그럼 두 번째로 ‘String’ 클래스를 사용해서 위의 예제와 동일한 예제를 만들어보자.
StringTest.ino |
String string1 = "Hello,"; String string2 = "Arduino."; String stringSum = "abcdefghijklmnopqrstuvwxyz"; void setup() { Serial.begin(9600); } void loop() { stringSum = string1 + string2; Serial.println(stringSum); while(1) ; } |
업로드 한 후 시리얼 모니터를 실행해보면 첫 번째 예제와 동일한 결과가 나오는 것을 볼 수 있을 것이다.
소스 코드를 살펴보자. 훨씬 짧아지고, 훨씬 알아보기 쉽다. 문자열 두 개를 더해서 하나의 문자열을 만든다는 것을 직관적으로 알아볼 수 있다. ‘\0’ 문자는 전혀 신경 쓰지 않아도 된다.
박수. 짝짝짝.
일단 String 클래스를 사용하면 엄청 편하다는 건 알겠다. 하지만 이게 다가 아닐텐데?
더 편리한 String의 기능을 알아보는건 다음 강좌에서. 오늘은 이만, 안녕~