2010-02-21 9 views
1

포인터 연산을 사용하면 한 배열의 문자를 다른 배열에 할당 할 수 있습니다. 제 질문은 임의의 시작 및 정지 점을 주면 어떻게합니까?숙제 : C에서 포인터를 사용하여 배열의 부분 문자열을 얻는 방법은 무엇입니까?

int main(void) 
{ 
    char string1[] = "something"; //[s][o][m][e][t][h][i][n][g][\0] 
    int start = 2, count = 3; 
    char string2[10] = {0}; 
    char *ptr1 = &string1[start]; 
    char *ptr2 = string2; 
    while (*ptr2++ = *ptr1++) { } //but stop after 3 elements??? 
    printf("%s",&string2); 
} 

특정 배열의 요소 수량을 계산/테스트하기 위해 일부 포인터 계산이 없습니다. 루프 계산에 정수를 선언하고 싶지 않습니다! 포인터를 사용하여 모든 작업을 수행하려고합니다. 감사! 정적 배열의 크기 (요소 즉, 수)를 얻기 위하여

+1

더 빠른 방법은 strncpy (string2, string1 + start, count) 일 것입니다. – zebrabox

답변

2
#include <stdio.h> 

int main(void) 
{ 
    char string1[] = "something"; //[s][o][m][e][t][h][i][n][g][\0] 
    int start = 2, count = 3; 
    char string2[10] = {0}; 
    char *ptr1 = &string1[start]; 
    char *stop = ptr1 + count; 
    char *ptr2 = string2; 
    while ((ptr1 < stop) && (*ptr2++ = *ptr1++)); 
    printf("%s",string2); 
    return 0; 
} 
+0

감사합니다! 나는 ptr1 + 카운트의 평범한 추가를 놓치고 끝에 메모리 위치를 테스트했다. 완벽하지는 않지만 나를 올바른 방향으로 인도하기에 충분합니다. –

+0

string2에 널 종결자가 없다면, 나는 두려워한다. –

+1

@Jonathan :'char string2 [10] = {0};' –

0

, 일반적으로 할 것입니다 크기에 따라 배열의 크기 (바이트)를 나눕니다

sizeof(string1)/sizeof(*string1) 

각 요소의 바이트 수 (바이트 단위)로 배열의 요소 수를 나타냅니다.

그러나 분명히 strcpy 클론을 구현하려는 경우 소스 문자 *ptr1'\0' (C 문자열은 제로 종료)이면 루프를 깨뜨릴 수 있습니다. N 문자 만 복사하려는 경우 ptr1 >= string1 + start + count 일 경우 중단 될 수 있습니다.

+0

sizeof (char) == 1. 그것은 표준에 의해 보장됩니다. –

+0

@Graham Lee : 네,하지만 이것은 배열을위한 일반적인 솔루션입니다. – AndiDog

3

ptr1++;을 쓰면 ptr1 = ptr1 + 1;과 같습니다. 정수에 포인터를 추가하면 포인터의 메모리 위치가 가리키는 유형의 크기 (바이트)만큼 이동합니다. ptr10x5678 값을 갖는 char 포인터 인 경우 sizeof(char) == 1이기 때문에 1을 증가 시키면 0x5679이됩니다. 그러나 ptr1Foo *이고 sizeof(Foo) == 12 인 경우 포인터를 증가 시키면 해당 값은 0x5684이됩니다.

이미 포인터가있는 요소에서 3 요소 떨어진 지점을 가리 키려면 해당 포인터에 3을 추가하면됩니다. 귀하의 질문에, 당신이 쓴 :

같은 일이다
char *ptr1 = &string1[start]; // array notation 

:

char *ptr1 = string1 + start; // pointer arithmetic 
다음과 같이 다시 쓸 수

:

const를 사용
int main(void) 
{ 
    char string1[] = "something"; //[s][o][m][e][t][h][i][n][g][\0] 
    int start = 2, count = 3; 
    char string2[10] = {0}; 

    // Ensure there is enough room to copy the substring 
    // and a terminating null character. 
    assert(count < sizeof(string2)); 

    // Set pointers to the beginning and end of the substring. 
    const char *from = string1 + start; 
    const char *end = from + count; 

    // Set a pointer to the destination. 
    char *to = string2; 

    // Copy the indicated characters from the substring, 
    // possibly stopping early if the end of the substring 
    // is reached before count characters have been copied. 
    while (from < end && *from) 
    { 
     *to++ = *from++ 
    } 

    // Ensure the destination string is null terminated 
    *to = '\0'; 

    printf("%s",&string2); 
} 

하고 의미있는 변수 이름을 (from, to, 또는 src, dst 대신 ptr1, ptr2) 실수를 피하는 데 도움이됩니다. assert을 사용하고 문자열이 null로 끝나는 지 확인하면 segfault와 다른 이상한 점을 디버깅하지 않아도됩니다. 이 경우 대상 버퍼는 이미 0으로 설정되어 있지만이 코드의 일부를 복사하여 다른 프로그램에서 사용할 때 그렇지 않을 수도 있습니다.

2

나는 보통 불리는 이러한 상황에서 변수 이름의 특정 세트, 사용 - 소스

  • dst - 대상
  • end -

    • src의 한쪽 끝 소스 (여기에 사용을) 또는 대상 그래서

    :

    ,794,396,198,706,043,210는 는 또는 더 그럴듯 함수로 패키지

    :

    char *copy_substr(char *dst, const char *str, size_t start, size_t len) 
    { 
        const char *src = str + start; 
        const char *end = src + len; 
        while (src < end) 
         *dst++ = *src++; 
        *dst = '\0'; 
        return(dst); 
    } 
    
    int main(void) 
    { 
        char string1[] = "something"; 
        char *end; 
        char string2[10] = {0}; 
    
        end = copy_substr(string2, string1, 2, 3); 
        printf("%s",&string2); 
        return(0); 
    } 
    

    이 기능은 aconventional하고 예에 표시된 혜택을 제공하지 않습니다 문자열의 끝을 가리키는 포인터를 반환하지만 이는 않습니다 당신이 단편적인 캐릭터 라인을 구축 할 때 몇 가지 장점이 있습니다

    struct substr 
    { 
        const char *str; 
        size_t  off; 
        size_t  len; 
    }; 
    
    static struct substr list[] = 
    { 
        { "abcdefghijklmnopqrstuvwxyz", 2, 5 }, 
        ... 
        { "abcdefghijklmnopqrstuvwxyz", 18, 3 }, 
    }; 
    
    int main(void) 
    { 
        char buffer[256]; 
        char *str = buffer; 
        char *end = buffer + sizeof(buffer) - 1; 
        size_t i; 
    
        for (i = 0; i < 5; i++) 
        { 
         if (str + list[i].len >= end) 
          break; 
         str = copy_substr(str, list[i].str, list[i].off, list[i].len); 
        } 
    
        printf("%s\n", buffer); 
        return(0); 
    } 
    

    주요 포인트는 반환 값이다 - 문자열의 끝에 NUL에 대한 포인터 - 당신이 문자열 연결 작업에 필요한 것입니다. (이 예에서는 길이가 알려진 문자열을 사용하여 strlen() 또는 strcat()를 반복적으로 사용하지 않고도이 반환 값 없이도 사용할 수 있습니다. 호출 된 함수가 호출시 결정할 수없는 양의 데이터를 복사하는 경우 루틴에 대한 포인터가 더 유용합니다.)

  • 관련 문제