2017-02-21 4 views
-2

은 다음과 * 우리는 문자를 정의 가정 :void *의 끝에 char *를 추가하는 방법?

char *x; 

우리는 같은 기능을 가지고

void append(void *y, char *z); 

이 함수는 그것의 추가 포인터 Z가 가리키는 두 번째 매개 변수 () 포인터가 문자열의 끝에 y이 시작됨을 나타냅니다. 내가 첫 번째 매개 변수를 가지고 제한하고 이유는 무효가 될 * 내가 libcurl 함수를 재정의 할 필요가 있다는 것입니다 :

size_t header_callback(char *buffer, size_t size, size_t nitems, void *userdata); 

header_callback 기능 내가의 끝에 버퍼를 추가 할 필요가 호출 될 때마다 사용자 데이터. 사용자 데이터 포인터가 문자열의 시작을 가리 킵니다.

+0

'void * y'는'std :: string'을 가리 킵니까? 아니면'char' 버퍼? – Galik

+1

알몸 포인터가 있고 그것에 추가하는 것은 경계를 벗어나지 않는 한 확실히 안전하지 않습니다. –

+1

'void'포인터를 처음에 제공 한 유형으로 되돌려 보내고 필요한 모든 작업을 수행하고 수행하십시오. 'buffer * '로 작업하기 위해 일반적인 문자열을 사용하는 트릭을 믿을 수는 없으므로'size * nitems'를 제공해야합니다. – user4581301

답변

-1

당신의 질문은 C (not C++) 접근법을 더 참조하는 것처럼 보입니다.

  1. 는 Y
  2. realloc을
  3. 이의 마지막 바이트를 설정 새로운 장소 + 1
  4. 방어 적이기/memmove를 y를 크기의 될 수있는 Y의 크기를 알고 : 그런 다음 필요
  5. 새 포인터와 새 버퍼의 크기를 반환합니다.
  6. 필요에 따라 이전 버퍼를 비 웁니다.

C++에서 htdwer에는 std :: vector와 같은 컨테이너를 사용해야하는데,이 컨테이너를 사용하면 1 바이트를 추가 할 수 있습니다.

+1

대답하기에 좋은 질문이 아닙니다. 너무 많은 미지수. 예를 들어, 버퍼 크기를 조정할 필요가 없을 수 있습니다. – user4581301

+0

그런 다음 질문에 답을하지 말고 downwote하십시오. – dmi

+0

정확히 내가 한 일. 또한 투표를 마감했습니다. – user4581301

0

그것은 구현하는 것은 불가능합니다 당신은 null 이외의 종료 문자 순서를 추가 할 수있는 방식

void append(void *y, char *z); 

.

콜백에 제공된 char *buffer은 null이 아닌 종료됩니다.

또한 append를 호출하기 전에 void 포인터를 콜백의 올바른 버퍼 유형으로 변환 할 수 있습니다. 그것은 결국 당신이 무효화 할 것이 없기 때문에 끝내야합니다.

추가 기능이 거의 없으므로 외부 기능이 거의 필요하지 않습니다.std::stringvoid* 점을 가정하면

auto bytes = size * nitems; 
auto str = (std::string*)userdata; 
str->append(buffer, bytes); 
+0

문제는 append()가 대상 버퍼를 "확장"할 수 없다는 것입니다. 특히 그것이 std :: string에서 나온 것이라면. 적절한 버퍼를 미리 할당하고 추가가 외부에서 실행되지 않도록해야합니다. – Swift

+0

@Swift 왜 추가 할 수없는 대상 버퍼가 증가합니까? 특히'std :: string'이라면, 성장을위한 inbuilt 기능을 가지고 있습니다. 요청을 보내기 전에 응답 길이를 알지 못하면 미리 사전 할당 할 수 없습니다. 통신 프로토콜을 다룰 때 종종하지 않는 것입니다. – user2079303

+0

우리는 버퍼를, 즉 스토리지를 변경할 수 있다면 ... 우리가 제공하는 문자열의 길이를 알면 대답의 길이를 알 수 있습니다. 제공된 코드는 std :: string 클래스를 통해 소스에서 데이터를 대조하여 새 버퍼를 만듭니다. 그러나 반환하려고 시도하는 것은 불법 일 수 있습니다. 표시된 프로토 타입은 버퍼 주소 반환이 허용되지 않는 것처럼 보입니다. – Swift

0

그 일을 버퍼에 데이터를 추가하려면 정의해야합니다

    대상 버퍼의 버퍼에 존재하는 데이터의 대상 버퍼의
  • 허용 크기
  • 대상 버퍼에 복사 할 데이터의 양

C에서 realloc()은 버퍼의 위치를 ​​변경하거나 변경하지 않을 수있는 오래된 내용의 새 버퍼를 만드는 데 사용할 수 있습니다. C++에는 비슷한 동작을 허용하는 새로운 연산자가 있습니다.

저장된 데이터가 null로 끝나는 문자열이라고 가정하면 2 번째와 3 번째가 알려져 있습니다. - 버퍼의 크기는 append()가 알 수없는 버퍼의 크기입니다. 따라서, 함수

void append(void *y, char *z); 

무효 Y 실제로 어떤 구조 나 클래스가 아니면, 를 작업에 부적합하거나 매우 불안전 아마도 불명확 하나 보인다 (그러나 그와 같은 공극 ??? 통과)한다.

귀하는 구현 또는 설명을 제공하지 않았습니다. 외모로 보면 다소 제한적이어야합니다. 적절한 크기의 버퍼를 미리 할당하고 append()가 해당 범위를 벗어나 실행되지 않도록해야합니다. 목표 버퍼를 재 할당 할 수 없으므로, 으로 이미 할당 된 메모리로 제한됩니다. 실제로 형식 매개 변수로 void **y 또는 void &* y있을 것입니다 목표 버퍼 APPEND를 재 할당하려면 (realloc을() 수도 변경 포인터와 새로운 버퍼 된 버퍼에서 복사 데이터를 않습니다)

이 아키텍처 문제를 제기 - 버퍼의 소유권. 우리가 제어하는 ​​버퍼를 넘겨 주면 제대로 할당하고 그것을 append()에 넘겨 주거나 소유권을 append()에 전달하여 재 할당 할 수 있습니다. 우리가하지 않으면, 우리는 일시적인 버퍼를 만들어야하지만 ... 그 후에 임시 버퍼를 사용할 수 있습니까?

사용자 정의 헤더 쓰기 기능을 사용하지 않는 한 요점은 논쟁 거리입니다. 사용자 데이터 포인터는 CURLOPT_HEADERDATA입니다.이 포인터는 유효한 FILE에 대한 포인터이며 _fwrite() 데이터를 사용해야합니다 ... 또는 CURLOPT_WRITEFUNCTION 및 CURLOPT_READFUNCTION 콜백을 구현하는 경우 해당 포인터는 콜백 디자이너의 재량에 따라 사용할 수 있습니다. 유용한 데이터 컨테이너에 대한 포인터 (libcurl은 fwrite를 기본 콜백으로 사용함).

1

는 링크 된 문서에 따르면, 유저 데이터 이전 CURLOPT_HEADERDATA에 공급 포인터입니다. 이 같은 것이 당신을 위해 일할 수도 있습니다.

size_t header_callback(char *buffer, size_t size, size_t nitems, vector<string> *userdata) 
{ 
    userdata->push_back(string(buffer, size*nitems)); 
    return size*nitems; 
} 

//... 
vector<string> headers; 
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &headers); 
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback); 
//... 
+0

커스텀 HEADERDATA에 새로운 콜백을 정의해야한다. 기본값은 FILE이어야한다. * – Swift

+0

@Swift'CURLOPT_HEADERFUNCTION'은 새로운 콜백이므로,'CURLOPT_HEADERDATA'의 기본값은 적용되지 않는다. @Bediver, 콜백의 마지막 인수는 필요한 프로토 타입과 일치시키기 위해'void * '이어야합니다. – user2079303

+0

@ user2079303 두 함수 모두 다시 정의되고 OP_had_가 CURLOPT_WRITEDATA 옵션을 사용하여 새 값을 설정하는 경우에만 해당됩니다. 다시, 너무 많은 미지수. 무엇을 써 주 었는지, char *로 설정되었다는 인상을 받았기 때문에 append()가 – Swift