Chapter 7 - 1. Pointers, Arrays, and References

The C++ Programming Languages




7.1 Introduction



메모리를 참조하는 방법을 다룰 것.

이름으로 객체를 접근할 수 있지만 특정 메모리의 주소에 객체들이 존재하고 주소와 그것의 타입을 알면 접근할 수 있다.. 

주소를 쥐고, 사용하기 위한 C++ 언어의 수단은 포인터와 레퍼런스.


7.2 Pointers 

포인터는 T* 와 같이 '*' 를 타입 뒤에 붙여 T 타입의 객체의 주소를 쥘 수 있게 한다. 

포인터에 사용할 수 있는 기본 연산자는 dereferencing(indirection) 인데, 포인터에 의해 가리켜지는 객체에 접근한다. 

배열의 포인터에 대해서는 산술 연산이 가능하다.


포인터의 구현은 실제로 런타임 머신의 어드레싱 메커니즘을 직접적으로 매핑한 것이다. 대부분의 머신들은 1 바이트에 접근가능하다. 그렇지 못한 것들은 words 로부터 바이트를 추출할 수 있는 하드웨어를 갖는 경향이 있다. 반면에, 아주 적은 수의머신들 만이 각각의 비트를 지접적으로 참조 할 수 없다. 

결과 적으로, 독립적으로 할당되고 포인팅 될 수 있는 빌트인 포인터 타입은 char 이다.

bool 은 실제로 char 만큼의 공간을 차지 한다는 것을 기억해 두자. 콤팩트하게 더 작은 값들을 저장하기 위해 bitwise 논리 연산들을 사용하거나, 구조체들의 비트 영역을 사용하거나, bitset 을 사용해야 한다.


타입이름 뒤에 붙이는 *는 pointer to 를 의미한다. 불행히도 배열이나 함수를 포인팅하기 위해서는 더 복잡한 개념을 사용해야 한다.


char** ppc    // char 를 가리키는 포인터를 가리키는 포인터

int* ap[15]    // 인트타입의 포인터의 15개 배열

int (*fp)(char*)    // int 를 리턴하고 char* 를 인자로 하는 함수의 포인터 

int* f(char*)    // char* 인자를 받아 인트 포인터를 리턴하는 함수 


7.2.1 void*



저수준코드에서, 우리는 때때로 어떤 타입의 객체가 실제로 저장되어 있는지 모르는 채로 주소를 넘기거나 저장할 필요가 있습니다.

이때 사용할 수 있는 것이 void* 이고, 의미는 "알려지지 않은 타입의 객체에 대한 포인터" 로 이야기 할 수 있습니다.

하지만 함수 포인터나 멤버포인터로는 사용할 수 없습니다. 게다가, void* 는 다른 void* 로 할당 될 수 있으며, void* 는 동등성을 비교하는 데 사용될 수 있으며, 명시적으로 다른 타입으로 변환될 수 있습니다. 실제로 어떤 타입의 객체가 저장되어있는지 컴파일러는 알 수 없기 때문에 다른 연산들은 안전하지 않을 수 있습니다. 결과적으로 컴파일 타임 에러로 연결 될 수 있습니다. 실제로 이용하기 위하여 명시적으로 변환 될 필요가 있습니다.


void* pv = pi;

*pv; // error 

pv++ // error, unknown size


void* 를 캐스팅 하여 사용하는 것은 타입에 대해 추정하여 이뤄지는 것이므로 위험한 작업이 될 수 있다. void* 를 리턴하는 함수는 그렇지 않은 인터페이스로 완벽하게 숨기는 것이 좋다. 


7.2.2 nullptr



포인터 타입에 할당 될 수 있는 null pointer.

어떤 주소도 0으로 할당되지 않았기 때문에 예전에는 0을 널포인터의 용도로 사용하였다. 하지만 최근에는 0이 포인터의 상수 ( constant of pointer )로 사용되도록, 멤버타입의 포인터로 사용되도록 허용 함에 따라 이렇게 사용할 수 없게 되었다.

nullptr 의 등장에따라 정수를 인자로 받는 함수와 포인터를 인자로 받는 오버로드함수의 모호성을 제거하였다.


7.3 Arrays



배열은 스택영역 / 힙영역에 선택적으로 할당 될 수 있다.


int a1[10]; // static storage 

void f()

{

int a2[20]; // stack

int* p = new int[40]; // heap

}


더 고수준의 인터페이스로 숨겨져 있는 편이 좋다. 배열의 이름은 첫번째 요소의 포인터가 된다. 하지만 이런 묵시적 변환은 에러를 만들 수 있다. 힙영역에 생성했으면 delete[] 를 잊지 말자.  (string / vector / unique_ptr 과 같은 리소스 핸들링을 통해 쉽게 처리될 수 있다.) 

7.3.1 Array Initializers 



[] 로 지정한 사이즈보다 initializer list 의 요소수가 더 적은경우 나머지는 default 값으로 채워진다.

기본 복사 생성자는 배열에 대해 존재하지 않는다. 


int v6[8] = v5; // error - can't copy


비슷하게 값으로 어레이를 전달 할 수 없다. 


객체의 콜렉션에 대해 할당이 필요하다면 vector / array (STL) / valarray 를 대신 사용하도록 한다.

char 배열은 string 리터럴을 이용하여 쉽게 초기화 될 수 있다.


7.3.2  String Literals



쌍따옴표로 감싸진 문자 시퀀스이다. 보이는 것보다 한개의 문자를 더 갖고 있다. '\0' 

string 리터럴의 타입은 const char[] 와 같다.

최신 C++ 11부터는 char* 에 (const 가 아닌) 문자열 리터럴을 할당할 수 없다.. ( C++11 의 예전 버전에서까지만 해도 허용 )

이런 조치는 명확성에 대해서만 이점이 있는 것이 아니라 구현상의 상당한 최적화 효과를 볼 수 있다.


반드시 바뀔 수 있는 문자열을 원한다면 non-const 배열을 사용한다. 


문자열 리터럴은 정적으로 할당되므로 함수에서 리턴하는 것도 안전하다.


const char* function()

{

return "~~~~"; // safe 

}

"~~~~" 를 갖고 있는 메모리는 호출이 끝난 뒤에 어디로 날아 가지 않는다. 


완전히 동일한 문자열 리터럴이 한 배열에 할당될지 / 두 배열에 할당될지는 구현에 달려있다.


7.3.2.1 Raw Character Strings 



역슬래쉬를 특수문자를 리터럴에 넣기위해 사용하기는 간편하지만, 그 숫자가 많을수록 관리하기 어려워지며 정규식의 경우 이를 이스케이프문자와 문자클래스들에(\w 와 같이) 사용하는 두가지를 표현하기 위해 사용한다. 

이런 혼란을 피하기위해 raw string literals 이 존재한다. 


string s = R"(\w\\w)"; // 역슬래쉬로 구분된 두 문자


괄호는 이스케이프되지 않은 쌍따옴표를 허용하기 위해 필요하다. 


그럼, )" 를 포함하는 문자열을 raw string literal 에 넣으려면 ?

다행히 default 구분자에 불과하다. 단순히 '(' 전에 원하는 구분자를 넣는 것으로 처리 될 수 있다.


R"***("quoted string ("))")***"     //"quoted string("))"

) 뒤의 구분자는 반드시 ( 앞의 구분자와 같아야한다. 


또 raw string literals 는 개행을 포함할 수 있다.


7.3.2.2 Larger Character Sets


L"angst" 와 같은 문자열은 와이드 캐릭터 문자열을 나타낸다. 타입은 const wchar_t[] 가 된다. 

이런 문자열은 L'\0' 로 종료된다. 


유니코드를 지원하는 캐릭터 리터럴은 6가지 종류가 있다. 8, 16, 32 그리고 각각 일반용 리터럴과 raw 용 리터럴, 이렇게 6개이다.


UTF-8 은 1~4바이트의 문자로 이뤄져 있다. 1바이트짜리는 ascii 와 일치한다. '\0' 으로 종료.

UTF-16 은 u'\0' 으로 종료

UTF-32 는 U'\0' 으로 종료.


일반적인 영어 문자열을 다양한 방법으로 표시할수 있다.


u8"folder\\file"

u"folder\\file"

U"folder\\file"


u8"\u00E6" 와 같이 유니코드 문자를 표기할 수 있음.


u'04030' ( Cyrillic lowercase latter "a" ) 는 UTF-8 에서 D0B0, UTF-16 에서 0403, UTF-32 에서 00000403 로 표기할수 있는데, 

이와 같은 헥사데시멀 값은 universal character names 라고 불린다.



정규식 - 기본 구문

개발툴 2014. 7. 3. 21:02

msdn 발췌.

http://msdn.microsoft.com/ko-kr/library/ae5bf541(v=vs.90).aspx

일치 항목

/^\s*$/

빈 줄을 찾습니다.

/\d{2}-\d{5}/

2자리 숫자, 하이픈 및 추가 5자리 숫자로 구성된 ID 번호의 유효성을 검사합니다.

/<\s*(\S+)(\s[^>]*)?>[\s\S]*<\s*\/\1\s*>/

HTML 태그를 찾습니다.

다음 표에는 정규식 컨텍스트의 메타문자와 그 동작에 대한 전체 목록이 들어 있습니다.

문자

설명

\

다음에 오는 문자를 특수 문자, 리터럴, 역참조 또는 8진수 이스케이프로 표시합니다. 예를 들어, 'n'은 문자 "n"을 찾지만 '\n'은 줄 바꿈 문자를 찾습니다. 시퀀스 '\\'는 "\"를 찾고 "\("는 "("를 찾습니다.

^

입력 문자열의 시작 부분에서 위치를 찾습니다. RegExp 개체의 Multiline 속성이 설정되어 있으면 ^에서는 '\n'이나 '\r' 다음의 위치도 찾습니다.

$

입력 문자열의 끝 부분에서 위치를 찾습니다. RegExp 개체의 Multiline 속성이 설정되어 있으면 $는 '\n'이나 '\r' 앞의 위치도 찾습니다.

*

앞의 문자나 부분식을 0개 이상 찾습니다. 예를 들어, zo*는 "z"과 "zoo"를 찾습니다. *는 {0,}에 해당합니다.

+

앞의 문자나 부분식을 1개 이상 찾습니다. 예를 들어, 'zo+'는 "zo"와 "zoo"는 찾지만 "z"는 찾지 않습니다. +는 {1,}에 해당합니다.

?

앞의 문자나 부분식을 0개나 1개 찾습니다. 예를 들어, "do(es)?"는 "do"나 "does"에서 "do"를 찾습니다. ? 는 {0,1}에 해당합니다.

{n}

n은 음이 아닌 정수입니다. 정확히 n개 찾습니다. 예를 들어, 'o{2}'는 "Bob"의 'o'는 찾지 않지만 "food"에 있는 두 개의 o는 찾습니다.

{n,}

n은 음이 아닌 정수입니다. n개 이상을 찾습니다. 예를 들어, o{2,}는 "Bob"의 "o"는 찾지 않지만 "foooood"의 o는 모두 찾습니다. 'o{1,}'은 'o+'에 해당합니다. 'o{0,}'은 'o*'에 해당합니다.

{n,m}

M 및 n은 음수가 아닌 정수이며 n <= m입니다. n개 이상 m개 미만을 찾습니다. 예를 들어, "o{1,3}"은 "fooooood"의 처음에 오는 3개의 o를 찾습니다. 'o{0,1}'은 'o?'에 해당합니다. 쉼표와 숫자 사이에는 공백을 넣을 수 없습니다.

?

*, +, ?, {n}, {n,}, {n,m} 등의 다른 수량자 뒤에 바로 이 문자가 오면 일치하는 패턴은 non-greedy입니다. non-greedy 패턴은 가능한 한 검색 문자열을 적게 찾습니다. 반면 기본 greedy 패턴은 가능한 한 검색 문자열을 많이 찾습니다. 예를 들어, "oooo" 문자열에서 'o+?'는 "o" 하나만 찾는데 'o+'는 모든 'o'를 찾습니다.

.

"\n"이외의 모든 단일 문자를 찾습니다. '\n'을 비롯한 모든 단일 문자를 찾으려면 '[\s\S]' 패턴을 사용합니다.

(pattern)

패턴을 찾아 일치하는 항목을 캡처하는 부분식입니다. $0…$9 속성을 사용하여 결과로 생성된 Matches 컬렉션에서 캡처된 일치 항목을 검색할 수 있습니다. 괄호 문자( )를 찾으려면 '\('이나 '\)'를 사용합니다.

(?:pattern)

패턴은 찾지만 일치하는 항목은 캡처하지 않는 부분식, 즉 나중에 사용하기 위해 저장하지 않는 비캡처링 일치 항목입니다. 패턴의 일부를 "or" 문자(|)를 사용하여 결합할 때 유용합니다. 예를 들어 'industr(?:y|ies)는 'industry|industries'보다 더 경제적인 표현입니다.

(?=pattern)

양의 미리 보기 검색을 수행하는 부분식으로 패턴에 일치하는 문자열이 시작된 위치에서 문자열을 찾습니다. 이는 비캡처링 일치, 즉 나중에 사용하기 위해 캡처하지 않는 일치입니다. 예를 들어 'Windows (?=95|98|NT|2000)'는 "Windows 2000"의 "Windows"는 찾지만 "Windows 3.1"의 "Windows"는 찾지 않습니다. 미리 보기는 문자를 소비하지 않습니다. 즉, 일치가 나타나면 미리 보기를 구성하는 문자 다음이 아니라 마지막 일치 항목 바로 뒤에서 다음 일치 항목에 대한 검색이 시작됩니다.

(?!pattern)

음의 미리 보기 검색을 수행하는 부분식으로 패턴에 일치하지 않는 문자열이 시작된 위치에서 검색 문자열을 찾습니다. 이는 비캡처링 일치, 즉 나중에 사용하기 위해 캡처하지 않는 일치입니다. 예를 들어 'Windows (?!95|98|NT|2000)'는 "Windows 3.1"의 "Windows"는 찾지만 "Windows 2000"의 "Windows"는 찾지 않습니다. 미리 보기는 문자를 소비하지 않습니다. 즉, 일치가 나타나면 미리 보기를 구성하는 문자 다음이 아니라 마지막 일치 항목 바로 뒤에서 다음 일치 항목에 대한 검색이 시작됩니다.

x|y

x 또는 y를 찾습니다. 예를 들어 'z|food'는 "z" 또는 "food"를 찾습니다. '(z|f)ood'는 "zood" 또는 "food"를 찾습니다.

[xyz]

문자 집합. 괄호로 묶인 문자 중 하나를 찾습니다. 예를 들어, '[abc]'는 "plain"에서 'a'를 찾습니다.

[^xyz]

음수 문자 집합. 괄호로 묶이지 않은 문자를 찾습니다. 예를 들어, '[^abc]'는 "plain"에서 'p'를 찾습니다.

[a-z]

문자의 범위. 지정한 범위에서 문자를 찾습니다. 예를 들어, '[a-z]'는 'a'에서 'z'까지의 범위에서 소문자 영문자를 찾습니다.

[^a-z]

음의 범위 문자. 지정한 위치에 있지 않은 문자를 찾습니다. 예를 들어, '[^a-z]'는 'a'에서 'z'까지의 범위에 있지 않은 문자를 찾습니다.

\b

단어 경계, 즉 단어와 공백 사이의 위치를 찾습니다. 예를 들어, 'er\b'는 "never"의 'er'은 찾지만 "verb"의 'er'은 찾지 않습니다.

\B

비단어 경계를 찾습니다. 'er\B'는 "verb"의 'er'은 찾지만 "never"의 'er'은 찾지 않습니다.

\cx

x로 표시된 제어 문자를 찾습니다. 예를 들어 \cM은 Control-M이나 캐리지 리턴 문자를 찾습니다. x의 값은 A-Z이나 a-z의 범위에 있어야 합니다. 범위를 벗어나면 c는 리터럴 'c' 문자로 간주됩니다.

\d

숫자를 찾습니다. [0-9]에 해당합니다.

\D

숫자가 아닌 문자를 찾습니다. [^0-9]에 해당합니다.

\f

용지 공급 문자를 찾습니다. \x0c와 \cL에 해당합니다.

\n

줄 바꿈 문자를 찾습니다. \x0a와 \cJ에 해당합니다.

\r

캐리지 리턴 문자를 찾습니다. \x0d와 \cM에 해당합니다.

\s

공백, 탭, 용지 공급 등을 비롯한 모든 공백 문자를 찾습니다. [\f\n\r\t\v]에 해당합니다.

\S

공백이 아닌 문자를 찾습니다. [^ \f\n\r\t\v]에 해당합니다.

\t

탭 문자를 찾습니다. \x09와 \cI에 해당합니다.

\v

세로 탭 문자를 찾습니다. \x0b와 \cK에 해당합니다.

\w

밑줄을 비롯한 모든 문자를 찾습니다. '[A-Za-z0-9_]'에 해당합니다.

\W

비단어 문자를 찾습니다. '[^A-Za-z0-9_]'에 해당합니다.

\xn

n을 찾는데, 여기서 n은 16진수 이스케이프 값입니다. 16진수 이스케이프 값은 정확히 두 자리 수입니다. 예를 들어, '\x41'은 "A"를 찾습니다. '\x041'은 '\x04' & "1"에 해당합니다. ASCII 코드가 정규식에 사용될 수 있습니다.

\num

num을 찾는데, 여기서 num은 양의 정수입니다. 캡처된 일치에 대한 역참조입니다. 예를 들어, '(.)\1'은 두 개의 연속된 동일 문자를 찾습니다.

\n

8진수 이스케이프 값이나 역참조 중 하나를 식별합니다. \n 앞에 n개 이하의 캡처된 부분식이 오면 n은 역참조입니다. 그렇지 않고 n이 8진수(0-7)이면 n은 8진수 이스케이프 값입니다.

\nm

8진수 이스케이프 값이나 역참조 중 하나를 식별합니다. \nm 앞에 nm개 이하의 캡처된 부분식이 오면 nm은 역참조입니다. \nm 앞에 n개 이하의 캡처가 오면 n은 뒤에 리터럴 m이 오는 역참조입니다. 처리 조건이 없으면 \nm은 n과 m이 8진수(0-7)일 때 8진수 이스케이프 값 nm을 찾습니다.

\nml

n이 8진수(0-3)이고 m과 l이 8진수(0-7)인 8진수 이스케이프 값 nml을 찾습니다.

\un

n을 찾는데, 여기서 n은 네 자리 16진수로 표현된 유니코드 문자입니다. 예를 들어 \u00A9는 저작권 기호(©)를 찾습니다.


'개발툴' 카테고리의 다른 글

python 콘솔등에서 출력 텍스트 컬러  (0) 2014.07.25
Mac Os Terminal Color  (0) 2014.07.24
정규식 - 특정 문자열 제외  (1) 2014.07.03
mac os 업데이트 후 brew path 가 맞지 않는 경우  (0) 2014.07.01
SVN  (0) 2014.06.23

정규식 - 특정 문자열 제외

개발툴 2014. 7. 3. 20:55

정규식에서 특정 단어를 제외하고 검색하고 싶으면


^((?!<문자열>).)*$


라인시작으로부터 ( ^ ) , <문자열>이 일치하지 않고 (?!) 어떤 문자들이 뒤에 위치할 수도 있은 뒤에 ( (.)* ) 라인 종료 ($)


역시 우리의 스택오버 플로우로부터. 


http://stackoverflow.com/questions/406230/regular-expression-to-match-string-not-containing-a-word



Note that the solution to does not start with “hede”:

^(?!hede).*$

is generally much more efficient than the solution to does not contain “hede”:

^((?!hede).)*$

The former checks for “hede” only at the input string’s first position, rather than at every position.

'개발툴' 카테고리의 다른 글

python 콘솔등에서 출력 텍스트 컬러  (0) 2014.07.25
Mac Os Terminal Color  (0) 2014.07.24
정규식 - 기본 구문  (0) 2014.07.03
mac os 업데이트 후 brew path 가 맞지 않는 경우  (0) 2014.07.01
SVN  (0) 2014.06.23