2014-04-25 2 views
0

아래 두 프로그램을 실행 한 결과에 대해 sscanf 동작을 이해하려고합니다.C sscanf 동작

void main() 
{ 
     char *a = "225.311"; 
     int x = 0, y = 0; 
     sscanf(a, "%d.3%d", &x, &y); 
     printf("x is %d, y is %d\n", x, y); 
} 

출력은 프로그램 아래

x is 255, y is 11 

내 기대에 따라 작동하지 않을 것입니다.

void main() 
{ 
     char *a = "225.311"; 
     int x = 0, y = 0; 
     sscanf(a, "%d5.3%d", &x, &y); 
     printf("x is %d, y is %d\n", x, y); 
} 

나는 25,11을 기대하고있다,하지만 난 sscanf 행동이 반대 방식으로 sprintf와 같은 정확한한다 기대하고

x is 255, y is 0 

출력이다. 하지만 내 두 번째 프로그램에서 작동하지 않습니다. 지정된 형식이 %d5.3%d 인 경우 delimeter로 5을 고려해야합니다. 그러나 고려하지 않고 모든 자릿수를 x에 대해 읽은 다음 점이 5.3%d과 일치하지 않아 종료됩니다.

누군가 설명해주세요.

+1

'[s] scanf'의 반환 값을 항상 확인하십시오. 사용한 자리 표시 자의 수와 같지 않은 경우 몇 가지 오류가 발생했음을 알 수 있습니다. – Crozin

+0

'scanf '에 대한 문서 또는 맨 페이지를 읽으십시오. 가정하지 마십시오 ...이 텍스트 패밀리 패밀리는 많은 힘을 가지고 있지만, 그 힘은 기본값보다 말할 가치가있는 것보다 더 많은 책임이 있다고 말하고 싶습니다. 사용자 관점에서 직관적이지 않을 수 있습니다.표준 C'fgets'또는 GNU/POSIX2008'getline'을 사용하여 라인을 읽은 다음'sscanf '로 구문 분석하는 것이 더 좋습니다. – hyde

답변

4

%d 변환 지정자가 sscanf은 버퍼에 숫자가 아닌 문자가 나타날 때까지 a이 가리키는 버퍼에서 계속 읽음을 의미합니다. 즉, %d은 두 번째 예의 문자열 리터럴 "225.311"에서 225까지 소모됩니다.

지정되는 형식이 %d5.3%d 인 경우 delimeter로 5를 고려해야합니다.

아니요, 사실이 아닙니다. 5은 문자열 형식에서 sscanf이 (읽은 후 int) 버퍼에서 정확히 일치합니다. 일치하지 않으면 sscanf이 리턴되고 y의 값은 변경되지 않습니다. sscanf의 결과를 저장하여이를 확인할 수 있습니다. 반환 값은 성공적으로 매칭되고 할당 된 입력 항목의 수와 같습니다.

char *a = "225.311"; 
int x = 0, y = 0; 
int retval = sscanf(a, "%d5.3%d", &x, &y); 
printf("%d\n", retval); // prints 1 

그러나, 버퍼에있는 숫자의 순서가 int에 맞게 너무 긴 경우, 다음 행동 때문에 부호있는 정수 오버 플로우의 정의되지 않은 있습니다.

1

다른 형식을 사용하고 sscanf()의 결과를 확인하는 것이 좋습니다. 또한 "0.001"과 "0.1"과 같은 분수를 구별하려면 위치를 기록하십시오. @ajay는 설명으로

const char *a = "225.0311"; 
int ipart = 0; 
unsigned fractionpart; 
int n1, n2; 
if (sscanf(a, "%d.%n%u%n", &ipart, &n1, &fractionpart, &n2) != 2) { 
    Handle_BadInput(); 
} 

printf("ipart is %d, fractionpart is %0*u\n", ipart, n2 - n1, fractionpart); 
// ipart is 225, fractionpart is 0311 

"%d5.3%d" 그 다음에, int 또 다른 int"5.3" 보인다.