2013-05-16 2 views
5

D에서 범위로 행을 읽는 방법?문자로 문자열 문자를 D에서 범위로 읽는 방법?

D에 범위가 있음을 알고 있지만 단순히이 개념을 사용하여 문자열의 각 문자를 반복하는 방법을 궁금해했습니다.

가 난 후 무엇을 표시하려면, 이동의 유사 코드는 다음과 같습니다

for _, someChar := range someString { 
    // Do something 
} 
+1

http://ddili.org/ders/d.en/ranges.html – sigod

+0

@sigod, 참으로 알리의 책을 확인 했어야합니다! 지금 당장 D 자료를 읽는 것은 자원으로 이동하는 것입니다. –

답변

12

코드 단위 또는 코드 포인트를 반복 할 것인지 여부에 따라 다릅니다. 당신은 단순히 횡설수설 것 인쇄

foreach(c; "La Verité") 
    writeln(c); 

마지막 두 문자를 입력 한 다음 추론과 foreach를 사용하는 경우, 그래서 é이 있기 때문에 언어 자체 배열 요소에 의해 배열을 반복하고, 문자열, 코드 단위의 배열 인 코드 포인트는 두 개의 UTF-8 코드 단위로 구성되며 개별 코드 단위를 인쇄합니다 (char은 UTF-8 코드 단위 임). 당신이

foreach(dchar c; "La Verité") 
    writeln(c); 

다음 런타임 코드 지점에 코드 단위를 디코딩되며, é 마지막 문자로 인쇄 할 경우에, 반면. 그러나이 중 어느 것도 범위로 문자열에서 실제로 작동하지 않습니다. foreach은 기본적으로 입력 범위 API를 사용하지 않고도 배열에서 작동합니다. 하지 자신의 코드 단위 유형 - 그것은 dchar의 범위와 같은 문자열을 운영
@property bool empty(); 
@property dchar front(); 
void popFront(); 

처럼 그러나 모든 문자열 유형, 범위 API 보인다. 이렇게하면 의미가 없으므로 개별 코드 단위로 작동하는 std.algorithm.filter과 같은 기능의 문제를 피할 수 있습니다. 유니 코드는 코드 포인트와 그래프 등을 결합하는 것과 관련하여 매우 복잡해지기 때문에 코드 포인트에서 작동하는 것은 100 % 올바르지 않습니다. 그러나 코드 포인트에서 작동하는 것은 정확함에 훨씬 가깝습니다 (그리고 범위 추가에 대한 작업이 이루어지고 있다고 생각합니다.) 당신이 그것을 필요로하고 성과를 지불 할 용의가있는 경우를 위해 표준 라이브러리에 대한 graphemes 지원). 그래서, 문자열 dchar의 범위로에서 작동의 범위 API있는 것은 훨씬 더 정확하고

foreach(c; filter!"true"("La Verité")) 
    writeln(c); 

같은 것을했다면 당신은 dchar을 통해 반복하는 것, 그리고 é가 제대로 인쇄됩니다.이 모든 단점은 문자열의 foreach이 기본적으로 코드 단위 수준에서 작동한다는 것입니다. 반면 문자열의 범위 API는 코드 점으로 작동하므로 배열 연산과 범위 기반 연산을 혼합 할 때주의해야합니다 문자열에 대한 연산. 그렇기 때문에 stringwstring은 랜덤 액세스 범위로 간주되지 않습니다. 단지 양방향 범위입니다. 다양한 코드 단위로 구성된 코드 포인트에서 O (1)에서 랜덤 액세스를 수행 할 수 없습니다 (dstring입니다. UTF-32에서는 모든 코드 단위가 코드 포인트).

+0

UFCS 수준에서 필요한 Range-functions을 제공하는 std.array를 가져 오면 어떤 일이 발생합니까? 문자열을 반복하는 것은 여전히 ​​동일할까요? – dav1d

+0

@ dav1d 배열의'foreach'는 배열 API 만 사용합니다. 배열의 경우 범위 기반 함수를 명시 적으로 사용해야합니다. 실제로 foreach와의 불일치만큼 짜증나는 것처럼 std.array를 가져 왔는지 여부에 따라 동작을 변경하는 것은 버그가 발생하기 쉽습니다. 단순히 가져 오기를 추가하거나 제거하면 코드의 동작이 크게 달라질 수 있습니다. 그것은하고 있었다. –

+0

그래, 정말 코드를 바꾸지 않기를 바랬다. 그러나 다른 한편으로 UFCS는 opApply (여기에 잘못되었을 수도 있음) 또는 범위 인터페이스를 구현하지 않는 객체를 반복 할 수 있습니다. 해명 해줘서 고마워. – dav1d

1
foreach(ch; str) 
    do_something(ch); 

문자열이 InputRange입니다. InputRange은 세 가지를 구현합니다 :

  • 빈; 그것은 비어 있습니까?
  • 프론트; 다음 항목을주세요.
  • popFront; 범위를 전진 시키십시오, 그렇지 않으면 정면은 동일을 돌려 보낼 것입니다.

foreach는 범위 작업 방법을 "이해합니다". 따라서 "그냥 작동합니다".

하지만 나는 Go를 말하지 않으므로 동일한 언어를 사용하고 있는지 확실하지 않습니다.

+0

예, 물론, 어, 내가 이것을 잊을 수 있는지 모르겠다. 이미 몇 번 사용 했으므로 나는 그것을 알아야한다. 어젯밤에 수면 부족을 비난해야한다. :) –

+0

나는 당신의 말을 듣고, 나는 지금 완전히 스스로를 명료하지 않다. – 0b1100110

+2

여기에 형식 유추 조심해. 이 코드는 코드 포인트가 아닌 코드 단위를 반복하므로 유니 코드에서 올바르게 작동하지는 않습니다. –

관련 문제