2017-09-23 5 views
0

sscanf 작품 :버퍼 대신 입력 문자열에 대한 포인터가있는 sscanf의 변형이 있습니까? 이 같은

int main(const int argc, const char *argv[]) { 
    char buf1[1024] = {0}; 
    char buf2[1024] = {0}; 
    char buf3[1024] = {0}; 
    char *str = "abc, 123; xyz"; 
    sscanf(str, "%[^,], %[^;]; %s", buf1, buf2, buf3); 
    printf("'%s' '%s' '%s'", buf1, buf2, buf3); // Prints: "'abc' '123' 'xyz'" 
    return 0; 
} 

버퍼 (buf1, buf2, buf3)에 str의 내용을 복사하거나 새로운 메모리를 할당 필요로하지 않는 함수가 있는지 궁금 해요. 대신 포인터 (ptr1, ptr2, ptr3)를 str의 일치하는 부분을 가리 키도록 설정하고 null은 일치 이후에 오는 것을 종료합니다.

int main(const int argc, const char *argv[]) { 
    char *ptr1 = NULL; 
    char *ptr2 = NULL; 
    char *ptr3 = NULL; 
    char *str = "abc, 123; xyz"; 
    // 
    // str = "abc, 123; xyz\0" 
    // 
    _sscanf(str, "%[^,], %[^;]; %s", &ptr1, &ptr2, &ptr3); 
    // 
    // str = "abc\0 123\0 xyz\0" 
    //  ^ ^ ^
    //  ptr1 ptr2 ptr3 
    // 
    printf("'%s' '%s' '%s'", ptr1, ptr2, ptr3); // Prints: "'abc' '123' 'xyz'" 

    return 0; 
} 

나는 strtok_r 등의 기능과 사용 될 수있는 regex.h 라이브러리가 알고 있지만, 나는이 입력 문자열을 수정할 수 있습니다 경우에 더 편리 할 것이라고 생각합니다.

+0

이 문제가 sscanf''에 의해 구문 분석 입력이 * 항상 * 널 (null)로 종료 할 수없는 것을! 'regex.h'는 서브 그룹 매치의 * 범위 *를 반환합니다 - 그것은 할 수 있습니다. –

+0

귀하의 질문에 말도 안되는 중간에 어딘가에 원래의 문자열을 종료하는 경우, 당신은 str의 크기가 맞다면 나머지를 이동하더라도 당신이 뭔가 BTW를 덮어 씁니다 결코 더 이상 같은 문자열 str되지 않습니다 증가하고 가장 재할당하는 재 할당이 필요할 것입니다. –

+0

일부 경우에 제가 말했습니다. 어떤 경우에는 입력 문자열이 수정되는지는 상관하지 않습니다. –

답변

4

토큰의 시작과 끝까지 인덱스를 캡처하는 데는 %n 지정자가 사용될 수 있습니다. 오류 검사는 인덱스와 종료 값이 원래 문자열의 위치에 char *를 가리키는 포인터로 끝나는 표준화 된 변형이 없다하지 -1

#include <stdio.h> 

int main(int argc, char *argv[]) { 
    int index1 = -1; 
    int end1 = -1; 
    int index2 = -1; 
    int end2 = -1; 
    int index3 = -1; 
    int end3 = -1; 
    char *str = "abc, 123; xyz"; 
    sscanf(str, " %n%*[^,]%n, %n%*[^;]%n; %n%*s%n", &index1, &end1, &index2, &end2, &index3, &end3); 
    printf("'%.*s' '%.*s' '%.*s'", end1, str + index1, end2 - index2, str + index2, end3 - index3, str + index3); // Prints: "'abc' '123' 'xyz'" 
    return 0; 
} 
1

있는지 확인합니다. POSIX에는 각 문자열 항목에 대해 메모리를 할당하고 데이터를 복사하는 변형이 있습니다.

sscanf()의 기능은 fscanf() 및 기타 변형의 기능과 일치하며 매우 넓은 범위 내에서 하나의 변형에 적용되는 것은 모두에 적용됩니다. 그러나, 당신이 찾고있는 것은 파일 기반 변형에 적용될 수 없기 때문에 존재하지 않습니다.


문자열에 메모리를 할당하는 변형 인 sscanf()이 있습니다. sscanf()의 POSIX 2008 변형과 m 수정 자입니다.

[CX] ⌦ %c, %s%[ 변환 지시자는 널 종료 문자를 포함 변환 된 메모리 버퍼는 문자열을 보유하기 위해 할당되게한다 선택적 할당 할당 문자 'm'를 허용한다 . 이 경우 변환 지정자에 해당하는 인수는 할당 된 버퍼에 대한 포인터를 수신하는 포인터 변수에 대한 참조 여야합니다. 시스템은 malloc()이 호출 된 것처럼 버퍼를 할당해야합니다. 응용 프로그램은 사용 후 메모리를 해제 할 책임이 있습니다. 버퍼를 할당 할 메모리가 충분하지 않은 경우 함수는 errno[ENOMEM]으로 설정해야하며 변환 오류가 발생합니다. 함수가 EOF를 리턴하면,이 호출에 의해 할당 할당 문자 'm'을 사용하여 매개 변수에 성공적으로 할당 된 메모리는 함수가 리턴하기 전에 해제됩니다. ⌫

C 표준 (그래서 m 개질제 표준 C의 일부가 아니고, 사방 지원되지 않음)을 통해 연장하고 ⌦ 및 ⌫ 심볼 범위를 표시하여 [CX] 표기 자국이 확장의

구현이 지원한다면 (예 : Linux는 macOS Sierra가 지원하지 않습니다.) sscanf()의 변형이 있으며 올바른 크기의 버퍼를 할당하며 char ** 인수가 필요합니다.

리눅스 매뉴얼 페이지가 말한다 :

옵션 'm'문자. 이것은 문자열 변환 (%s, %c, %[)과 함께 사용되며 호출자에게 입력을 보관할 해당 버퍼를 할당해야하는 필요성을 해소합니다. 대신 scanf()은 충분한 크기의 버퍼를 할당하고이 버퍼의 주소를 해당 포인터 인수는 char * 변수에 대한 포인터 여야합니다 (이 변수는 호출 전에 초기화 할 필요가 없습니다). 호출 원은, 필요하지 않게되었을 때에, 이후에이 버퍼를 해방해야한다 (3).

#include <stdio.h> 
#include <stdlib.h> 

int main(void) 
{ 
    char data[] = "The hills are alive with the sound of music"; 
    char *w[9]; 

    if (sscanf(data, "%ms %ms %ms %ms %ms %ms %ms %ms %ms", 
       &w[0], &w[1], &w[2], &w[3], &w[4], &w[5], &w[6], &w[7], &w[8]) != 9) 
    { 
     fprintf(stderr, "Oops!\n"); 
     return 1; 
    } 
    printf("Forwards: %s\n", data); 
    printf("Reversed:"); 
    for (int i = 8; i >= 0; i--) 
     printf(" %s", w[i]); 
    putchar('\n'); 
    for (int i = 0; i < 9; i++) 
     free(w[i]); 
    return 0; 
} 

출력 :

Forwards: The hills are alive with the sound of music 
Reversed: music of sound the with alive are hills The 
+0

그래도 여전히 문자열을 복사합니다. OP가 요구 한 것 인 입력 문자열에 포인터를 반환하지 않습니다. – zwol

+0

@zwol : 오, 처음으로 질문을 잘못 읽었습니다. 나는 그에 맞게 대답을 수정했다. –

+0

'm' 수정자는 Posix'scanf'와'fscanf'에서도 작동합니다. (나는 당신이 그것을 안다는 것을 압니다. 그러나 당신의 대답은 오해 될 수 있습니다.) – rici