코드는이 라인에 충돌합니다 :
strcat(data,strtok_r(NULL," ",&save));
당신이 data
을위한 공간을 예약하지 때문입니다. strcat
은 NULL
메모리 주소에 쓰려고 시도합니다.
줄의 끝을 확인하려면 save
에 의존해서는 안됩니다. strtok
의 맨 페이지에 따르면
saveptr 인수가 문자 strtok_r에 의해 내부적으로 을 사용 * 변수에 대한 포인터() 같은 문자열을 구문 분석 연속 통화 사이의 맥락을 유지하기 위해.
strtok_r
휴식 추상화 층의 saveptr
외부의 값에 의존, 당신은 strtok
이 saveptr
를 사용하는 방법에 대해 아무것도 가정하지 않아야합니다. 나쁜 습관입니다.
약간 더 나은 방법은 이전 토큰에 대한 포인터를 strtok
이 반환하고 현재 토큰을 가리키는 포인터를 유지하는 것입니다. strtok
이 NULL을 반환하면 더 이상 토큰이 없음을 의미하고 prev
은 마지막 토큰 인 key
을 가리 킵니다. 내가 배열 대신 포인터로 선언 data
을위한 공간을 할당
char *key = NULL, *save=NULL;
char *prev, *curr;
char comando[1024];
char data[1024];
data[0] = '\0';
fgets(comando, 512, stdin);
prev = curr = strtok_r(comando, " ",&save);
while (curr != NULL) {
prev = curr;
curr = strtok_r(NULL, " ", &save);
if (curr != NULL)
strcat(data, prev);
}
key = prev;
참고 : 여기에 몇 가지 코드입니다. 명령
data[0] = '\0';
는 strcat
는 첫 번째 호출에 널 종료 바이트를 발견 있는지가 확인하는 것입니다.
의 사용을 직접 key
으로 바꿀 수 있습니다. 코드를 더 쉽게 읽을 수 있도록 남겨 두었습니다.
조언의 말씀 : 항상 strtok
은 인자를 파괴적으로 변경한다는 점을 기억하십시오. (당신은 구분 바이트의 신원을 잃어 버립니다.) 그리고 상수 문자열로 그것을 호출 할 수 없다는 것을 기억하십시오.
참고 :data
에는 모든 단어가 연결됩니다. 너는 그 공간을 잃는다. 이것이 당신이 원하는 것인지 확실하지 않습니다. 그렇지 않은 경우 strcat
보다 나은 것을 사용하고 싶을 수도 있습니다 (매우 효율적이지는 않습니다. btw).예를 들어 sprintf
을 사용하여 data
에 토큰을 인쇄하고 공백이있는 다음 위치에 대한 포인터를 data
에 유지합니다.
가 디버깅을 시도 해 봤나 : 또한,
strtok_r
는NULL
내가 뭔가 더 좋아 할 것 반환 할 수 있습니다? 'save'가'strtok_r()'을 호출 할 때마다 가리키는 것과 같은 결과를 출력 할 것입니다. – gnobal
'strtok_r '을 사용하는 것이 좋다고 생각합니까? 아니면 잘못된 것이 있습니까? – PhillipD
'data'와'key'를위한 메모리를 할당해야합니다. 지금 널 포인터에 추가 중입니다. –