2014-05-23 10 views
0

다음과 같은 문제가 있습니다. sscanf은 내가 원하는 방식으로 반환하지 않습니다.Sscanf가 원하는 것을 반환하지 않습니다.

sscanf(naru, 
     "%s[^;]%s[^;]%s[^;]%s[^;]%f[^';']%f[^';']%[^;]%[^;]%[^;]%[^;]" 
     "%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]" 
     "%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]", 
     &jokeri, &paiva1, &keskilampo1, &minlampo1, &maxlampo1, 
     &paiva2, &keskilampo2, &minlampo2, &maxlampo2, &paiva3, 
     &keskilampo3, &minlampo3, &maxlampo3, &paiva4, &keskilampo4, 
     &minlampo4, &maxlampo4, &paiva5, &keskilampo5, &minlampo5, 
     &maxlampo5, &paiva6, &keskilampo6, &minlampo6, &maxlampo6, 
     &paiva7, &keskilampo7, &minlampo7, &maxlampo7); 

이 검사의 문자열 : 이것은 sscanf입니다

모든 변수가 char paiva1[22] 등으로 저장됩니다
const char *str = "city;" 
        "2014-04-14;7.61;4.76;7.61;" 
        "2014-04-15;5.7;5.26;6.63;" 
        "2014-04-16;4.84;2.49;5.26;" 
        "2014-04-17;2.13;1.22;3.45;" 
        "2014-04-18;3;2.15;3.01;" 
        "2014-04-19;7.28;3.82;7.28;" 
        "2014-04-20;10.62;5.5;10.62;"; 

; 그러나 sscanf은 도시를 제외한 모든 것을 정확하게 저장하지 않습니다. 각 변수를 ;에 멈추려 고했습니다. 날짜 등을 올바르게 저장하는 방법에 대한 도움을 주시면 감사하겠습니다.

또는 더 스마트 한 방법이 있다면 제안을 할 수 있습니다.

+4

sscanf (naru, "% s [^;] % s [^;] ...'->'sscanf (naru,"% [^;]; – BLUEPIXY

+0

항상 scanf 함수의 반환 값을 확인해야하며, 그와 같이 긴 형식의 문자열은 변경해야하는 경우 관리상의 악몽이 될 수 있습니다. – hyde

+1

Yeesh,'; 그것. –

답변

2

여러 가지 문제가 있지만 이 첫 번째 것을 나타냅니다. — 스캔 세트 표기법이 %s을 따르지 않습니다. 그 의미로는 [ 뒤에 공간 분리 된 단어하는 ^하는 ;를 찾지

"%s[^;]%s[^;]%s[^;]%s[^;]%f[^';']%f[^';']%[^;]%[^;]%[^;]%[^;]" 

, A는 ] (이는 자기이다

형식의 첫 번째 행은 상반되는 문자, 문자열 뒤의 문자는 공백 또는 문자열의 끝임).

첫 번째 픽스가 제대로 스캔 세트를 사용하는 것입니다 : 이제

"%[^;]%[^;]%[^;]%[^;]%f[^';']%f[^';']%[^;]%[^;]%[^;]%[^;]" 

당신이 처음 %[^;] 두 번째 %[;]을 위해 아무것도 남기지 않고, 문자열 또는 첫 번째 세미콜론 년 말까지 모든 것을 스캔 문제 일치시킵니다.

"%[^;]; %[^;]; %[^;]; %[^;]; %f[^';']%f[^';']%[^;]%[^;]%[^;]%[^;]" 

이 세미콜론까지 문자열을 찾습니다 후 세미콜론를 들어, 다음 옵션 공백은 다음 세 가지 항목에 대해 반복. 문자열의 크기를 제한하기 위해 길이를 추가하는 것 외에 오버플로를 방지하는 것이 좋습니다. %f은 정상입니다. 다음 자료는 이상한 문자 시퀀스를 다시 찾습니다.

그러나 데이터를 살펴보면 도시와 7 세트의 '날짜와 3 개의 숫자'로 구성되는 것으로 보입니다.

당신은 (아직 그와 함께 작업 한 경우) 구조의 배열을 더 잘 할, 또는 4 개 병렬 배열의 세트 및 루프 것 :

char jokeri[30]; 
char paiva[7][30]; 
float keskilampo[7]; 
float minlampo[7]; 
float maxlampo[7]; 

int eoc; // End of conversion 
int offset = 0; 
char sep; 
if (fscanf(str + offset, "%29[^;]%c%n", jokeri, &sep, &eoc) != 2 || sep != ';') 
    ...report error... 
offset += eoc; 

for (int i = 0; i < 7; i++) 
{ 
    if (fscanf(str + offset, "%29[^;];%f;%f;%f%c%n", paiva[i], 
       &keskilampo[i], &minlampo[i], &maxlampo[i], &sep, &eoc) != 5 || 
     sep != ';') 
     ...report error... 
    offset += eoc; 
} 

How to use sscanf() in loops 참조하십시오.

이제 관리 할 수있는 데이터가 있습니다. 별도로 명명 된 29 개의 변수 집합은 무시 무시한 생각입니다. 그것들을 사용하는 코드는 무시 무시할 것이다.

스캔 세트 변환 사양은 문자열을 jokeripaiva 배열 요소의 크기보다 짧은 최대 길이로 제한합니다.


당신은 합법적으로 코드가 &eoc 전에 %c%n&sep을 사용하는 이유에 대해 궁금 할 것이다. 이유가 있지만 미묘합니다. 또한,

"%29[^;];%f;%f;%f;%n" 

을 세 번째 숫자 뒤에 세미콜론이 누락 된 데이터에 문제가있다 생각하십시오 sscanf() 형식 문자열이 있다고 가정하자. sscanf()에 대한 호출은 성공적으로 4 회 전환했음을보고하지만 할당으로 %n을 계산하지 않으므로 sscanf()이 세미콜론을 찾지 못해서 &eoc을 설정하지 않았다는 것을 알 수 없습니다. 값은 sscanf()에 대한 이전 호출에서 남겨 지거나 간단히 초기화되지 않습니다. %c을 사용하여 sep에 값을 스캔하면 성공하면 5가 반환되고 %n도 성공했는지 확인할 수 있습니다. 이 코드는 sep의 값이 실제로는 세미콜론인지 아닌지 확인합니다.

세미콜론 앞에는 %c 앞에 공백을 넣을 수 있습니다. 그렇지 않으면 다른 데이터 문자열이 변환되지 않고 다른 방식으로는 변환되지 않습니다. 형식 문자열 (스캔 세트 외부)의 공백은 선택적 공백이 나타날 수있는 위치를 나타냅니다.

+0

정말 고맙습니다! 배열 정말입니다. 엄청난 양의 변수를 처리하는 가장 현명한 방법 인 것 같습니다. – pellerusty

1

나는 ;을 구분 기호로 사용하여 문자열을 조각으로 나누는 strtok 함수를 사용합니다. 이러한 긴 형식의 문자열은 앞으로 문제가 될 수 있습니다.

관련 문제