Lesson9(문자열)

Strings (문자열)

# 0. 인트로

Intro::

This lesson will discuss C-style strings, which you may have already seen in the array tutorial. In fact, C-style strings are really arrays of chars with a little bit of special sauce to indicate where the string ends. This tutorial will cover some of the tools available for working with strings--things like copying them, concatenating them, and getting their length.

이번 강의는 C 스타일 문자열에 대해 논합니다. 지난번 배열 강의에서 봤던 내용입니다.

사실 C 스타일 문자열은 진짜로 문자 하나하나의 배열입니다. 이때, 문자의 끝을 알리는 아주 특별한 소스가 조금 들어갑니다.

이번 강좌에서는 문자열에 대해 유용한 몇가지 도구들(function) 또한 다룰 예정입니다. -- 예를 들면 복사하거나, 문자열을 이어붙이거나 길이를 알아내는 것 입니다.

# 1. 근데 문자열이 뭐야?

Note that along with C-style strings, which are arrays, there are also string literals, such as "this". In reality, both of these string types are merely just collections of characters sitting next to each other in memory. The only difference is that you cannot modify string literals, whereas you can modify arrays. Functions that take a C-style string will be just as happy to accept string literals unless they modify the string (in which case your program will crash). Some things that might look like strings are not strings; in particular, a character enclosed in single quotes, like this, 'a', is not a string. It's a single character, which can be assigned to a specific location in a string, but which cannot be treated as a string. (Remember how arrays act like pointers when passed into functions? Characters don't, so if you pass a single character into a function, it won't work; the function is expecting a char*, not a char.)

C 스타일 문자열은, 배열인 것도 있고, 정말 말그대로 문자열인 "문자열" 도 있습니다.

실제로 두가지 문자열 유형 모두 단지 문자들의 집합에 지나지 않습니다. 이 문자들의 집합은 컴퓨터의 메모리 상에서 나란히 서로 옆자리에 위치합니다.

이들의 유일한 차이점은 "문자열" 은 수정할수 없지만, 배열인 문자열은 수정 할수 있다는 점입니다. (편의상 앞으로 그냥 문자열 그 자체는 "문자열", 배열인 문자열은 [문자열] 로 쓰겠습니다.)

C 스타일 문자열을 가지는 Functions(프로그래밍에서의 함수를 말합니다.) 는 "문자열"을 수정하지 않는한 받아들입니다.(수정하게 되면 프로그램이 먹통이 될겁니다.)

문자열처럼 보이는 것들은 문자열이 아닙니다. 특히 'a' 와 같이 작은 따옴표로 묶인 것은 문자열이 아닙니다. 그냥 하나의 문자 입니다. 문자열 중에서 특정한 위치에 놓일수는 있지만 문자열로 취급하지는 않습니다. (Functions(함수)에 인자로 넣을때 배열이 마치 포인터처럼 동작하던것을 기억하시나요?-- 배열 강좌 참조.-- 문자 들은 그렇지 않습니다. 그렇기때문에 하나의 문자를 함수에 넣고 싶다면 제대로 동작하지 않을겁니다. 함수는 char*--캐릭터타입 포인터--가 오기를 기대하고 있지, 그냥 단지 캐릭터 타입은 기다리지 않습니다.)

참고로 포인터는 일종의 >위치< 입니다. 그런 개념으로 이해하시면 편합니다.

To recap: strings are arrays of chars. String literals are words surrounded by double quotation marks.

다시 한번 말하지만, 문자열은 문자들의 배열입니다. "문자열"은 큰따옴표로 둘러싸인 단어들입니다.

Remember that special sauce mentioned above? Well, it turns out that C-style strings are always terminated with a null character, literally a '\0' character (with the value of 0), so to declare a string of 49 letters, you need to account for it by adding an extra character, so you would want to say:

위에서 말한 특별한 소스를 기억하세요? C 스타일 문자열은 항상 널 문자, 말그대로 '\0' (0의 값을 가짐.)으로 종료됩니다. 따라서 49글자의 문자열을 선언하고 싶다면, 그보다 한개 더 많은 공간이 필요합니다. 즉, 아래와 같이 표현합니다.

This would declare a string with a length of 50 characters. Do not forget that arrays begin at zero, not 1 for the index number. In addition, we've accounted for the extra with a null character, literally a '\0' character. It's important to remember that there will be an extra character on the end on a string, just like there is always a period at the end of a sentence. Since this string terminator is unprintable, it is not counted as a letter, but it still takes up a space. Technically, in a fifty char array you could only hold 49 letters and one null character at the end to terminate the string.

위의 코드는 길이가 50개 문자들로 이루어진 문자열을 선언합니다. 배열의 인덱스는 1이 아닌 0에서 시작한다는 것을 잊지마시기 바랍니다. 더하여, 우리는 \0 으로 표시되는 널문자를 하나 더 추가하여 글자수를 셌습니다.

문자열의 끝에 추가적인 문자가 들어간다는 것을 꼭 기억하세요. 마치 문장의 끝에 점(.)를 찍듯이 말입니다.

이 문자열의 마침표(\0) 는 모니터로 표시되지 않기때문에(프린트 되지 않음.) 글자로 카운팅하지는 않지만, 메모리 공간을 차지하고 있습니다.

기술적으로, 50 size의 char 타입 배열에는 49개의 글자와 문장의 끝을 나타내는 널문자가 포함됩니다.

Note that something like

can also be used as a string.

위처럼 포인터를 선언하여도 문자열로 사용할수 있습니다.

If you have read the tutorial on pointers, you can do something such as:

which allows you to access arry just as if it were an array.

포인터 강의에서 보았듯이, 메모리를 동적으로 할당하여(데이터가 들어가는 공간을 만듬.) 배열처럼 접근할수 있습니다.

To free the memory you allocated, just use free:

For example:

또한 할당된 메모리를 다시 풀어주기 위해서 위와 같이 free 함수를 사용할수 있습니다. (자세한 내용은 포인터 강의를 참조합니다.)

# 2. 문자열 사용하기

Strings are useful for holding all types of long input. If you want the user to input his or her name, you must use a string. Using scanf() to input a string works, but it will terminate the string after it reads the first space, and moreover, because scanf doesn't know how big the array is, it can lead to "buffer overflows" when the user inputs a string that is longer than the size of the string (which acts as an input "buffer").

문자열은 모든 유형의 긴 입력을 저장하는데 유용합니다. 사용자로부터 이름을 입력받는다고 할 때, 문자열을 사용합니다. scanf() 함수를 사용하여 입력받아도 되지만, scanf()의 경우, 첫번째 ' ' 빈 공란을 만나면 문자열을 읽기를 끝내고, 심지어 배열이 얼마나 큰지 알수 없기때문에 사용자가 메모리에 할당된 공간보다 큰 사이즈를 입력하게 되면 "buffer overflows(버퍼오버플로우)" 문제를 일으킬수 있습니다.

There are several approaches to handling this problem, but probably the simplest and safest is to use the fgets function, which is declared in stdio.h.

이러한 문제를 해결하기 위한 몇가지 접근법이 존재하지만 아마도 가장 간단하면서 안전한 방법은 <stdio.h> 에 선언된 fgets 함수를 사용하는 것입니다. The prototype for the fgets function is:

There are a few new things here. First of all, let's clear up the questions about that funky FILE* pointer. The reason this exists is because fgets is supposed to be able to read from any file on disk, not just from the user's keyboard (or other "standard input" device). For the time being, whenever we call fgets, we'll just pass in a variable called stdin, defined in stdio.h, which refers to "standard input". This effectively tells the program to read from the keyboard. The other two arguments to fgets, str and size, are simply the place to store the data read from the input and the size of the char*, str. Finally, fgets returns str whenever it successfully read from the input.

새롭게 보이는 것들이 몇가지 있습니다. 우선 요상하게 생 FILE* 포인터에 대해서 확실하게 합시다. fgets 함수는 원래 디스크에서 파일을 읽기 위해 사용하는 함수로, 사용자의 키보드(또는 다른 어떤 표준 입력 장치를 통해서든)로부터의 입력만을 위한것은 아닙니다. 당분간은 fgets 함수를 호출할때 stdio.h 에 선언되어 있는 stdin(standard input) 변수를 사용합겁니다. 이 변수는 효과적으로 키보드로부터 값을 읽어 프로그램에게 전달할수 있습니다. 나머지 두 인자는 str과 size 인데, 이는 단순하게 입력장치로부터 읽어낸 데이터를 저장하는 장소와 읽어낼 데이터 사이즈를 의미합니다. 마지막으로 fgets 함수 성공적으로 입력장치로 부터 데이터를 읽어내면 str 을 출력으로 내보냅니다.

When fgets actually reads input from the user, it will read up to size - 1 characters and then place the null terminator after the last character it read. fgets will read input until it either has no more room to store the data or until the user hits enter. Notice that fgets may fill up the entire space allocated for str, but it will never return a non-null terminated string to you.

사실 fgets 함수가 사용자로부터 값을 읽을때는 size-1 만큼의 글자수만 읽을 수 있습니다. 그리고나선 읽어낸 글자 중 맨 마지막에 널문자를 마침표로 추가합니다. fgets 함수는 더이상 데이터를 저장할 공간이 없거나 혹은 용자가 엔터키를 누를때까지 입력을 읽습니다. 명심할 점은 fgets 함수는 str 에 할당된 전체 공간을 채울수도 있지만, 널문자로 끝나지 않는 문자열을 반환하는 일은 절대로 없습니다. Let's look at an example of using fgets, and then we'll talk about some pitfalls to watch out for. 예제를 보면서 fgets 함수에서 주의해야 할 점을 몇가지 살펴봅시다.

For a example:

Remember that you are actually passing the address of the array when you pass string because arrays do not require an address operator (&) to be used to pass their addresses, so the values in the array string are modified. The one thing to watch out for when using fgets is that it will include the newline character ('\n') when it reads input unless there isn't room in the string to store it. This means that you may need to manually remove the input. One way to do this would be to search the string for a newline and then replace it with the null terminator. What would this look like? See if you can figure out a way to do it before looking below:

Here, we just loop through the input until we come to a newline, and when we do, we replace it with the null terminator. Notice that if the input is less than 256 characters long, the user must have hit enter, which would have included the newline character in the string! (By the way, aside from this example, there are other approaches to solving this problem that use functions from string.h.)

Last updated

Was this helpful?