programing

strtol의 올바른 사용

javamemo 2023. 6. 9. 21:40
반응형

strtol의 올바른 사용

아래 프로그램은 문자열을 long으로 변환하지만, 제가 이해한 바로는 오류도 반환합니다.저는 만약에strtol한 후 두 를 long으로 변환하였습니다.strtolNULL과 같아야 합니다.아래 앱을 55로 실행하면 다음과 같은 메시지가 나타납니다.

./convertToLong 55
Could not convert 55 to long and leftover string is: 55 as long is 55

오를성공탐방법에서 오류를 하려면 어떻게 ?strtol내 애플리케이션에서 0은 유효한 값입니다.

코드:

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

static long parseLong(const char * str);

int main(int argc, char ** argv)
{
    printf("%s as long is %ld\n", argv[1], parseLong(argv[1]));
    return 0;
 }

static long parseLong(const char * str)
{
    long _val = 0;
    char * temp;

    _val = strtol(str, &temp, 0);

    if(temp != '\0')
            printf("Could not convert %s to long and leftover string is: %s", str, temp);

    return _val;
}

밑줄로 시작하는 이름은 구현을 위해 예약됩니다. 코드에서 이러한 이름을 사용하지 않는 것이 좋습니다.이런 이유로,_val 정해야합이어야 .val.

대오전처사체양에 대한 오류 입니다.strtol()그리고 처음 마주쳤을 때, 그것의 친척들은 복잡하고, 놀랍도록 복잡합니다.당신이 하고 있는 한 가지 일은 기능을 사용하여 호출하는 것입니다.strtol()코드에서 'raw'를 사용하는 것은 아마도 올바르지 않을 것입니다.

질문에 C와 C++이 모두 태그되어 있으므로 C2011 표준을 인용하겠습니다. C++ 표준에서 적절한 표현을 찾을 수 있습니다.

ISO/IEC 9899:2011 § 7.22.1.4strtol,strtoll,strtoul그리고.strtoull

long int strtol(const char * restrict nptr, char ** restrict endptr, int base);

2 [...] 먼저 입력 문자열을 세 부분으로 분해합니다: 초기의 공백 문자 시퀀스(isspace 함수에 의해 지정됨), 기본값에 의해 결정되는 일부 기수에서 표현되는 정수와 유사한 주체 시퀀스, 그리고 하나 이상의 인식되지 않는 문자의 마지막 문자열,입력 문자열의 종료 null 문자를 포함합니다. [...]

형식이 . 7 실 체 시 험 비 예 형 는 되 가 태 있 않 수 습 지 행 니 되 다 이 환 변 않 면 으 지 지 고 를 상 거 퀀 어 있 스 나 가 ▁7 ▁7 ▁of 다 ion ▁is ▁value ▁is 니 ▁sequence ▁if , 습 ▁the 않 ▁no ▁subject ; ▁does ▁or 실 ▁the ▁convers ▁performed 지 값은nptr 객체에 저장됩니다.endptr,endptr포인터가 . " 는 null 포인터입니다.

돌아온다

8 더strtol,strtoll,strtoul,그리고.strtoull함수는 변환된 값이 있으면 반환합니다.변환을 수행할 수 없는 경우 0이 반환됩니다., ) 은 올바값른표벗가면에 됩니다. LONG_MAX, LONG_MAX, LONG_MAX, LONG_MAX ULONG_MAX 또는 ULLONG_MAX가 반환되고 매크로 ERANGE 값이 저장됩니다.errno.

C 함수도 C를 하지 않는다는 것을 기억하세요.errno0. 그러므로, 신뢰할 수 있으려면, 당신은 다음을 설정해야 합니다.errno0을 하기 전에 합니다.strtol().

그래서, 당신의parseLong()기능은 다음과 같습니다.

static long parseLong(const char *str)
{
    errno = 0;
    char *temp;
    long val = strtol(str, &temp, 0);

    if (temp == str || *temp != '\0' ||
        ((val == LONG_MIN || val == LONG_MAX) && errno == ERANGE))
        fprintf(stderr, "Could not convert '%s' to long and leftover string is: '%s'\n",
                str, temp);
        // cerr << "Could not convert '" << str << "' to long and leftover string is '"
        //      << temp << "'\n";
    return val;
}

할 경우 이 은 0 또는 또는 합니다. 이 값은 무엇이 LONG_MIN인지 0인지에 .strtol()반된환 만약 당신의 를 알아야 , 합니다 - 하세요.호출 코드에서 변환이 성공했는지 여부를 알아야 하는 경우 다른 기능 인터페이스가 필요합니다. 아래를 참조하십시오.는 한오류다인야합니다해쇄음로으또로 점에하시기 바랍니다.stderrstdout새 줄로 .\n만약 그렇지 않다면, 그들은 적시에 나타날 것이라고 보장되지 않습니다.

라이브러리 코드에서는 인쇄를 원하지 않을 수 있으며, 호출 코드는 변환이 성공적으로 수행되지 않았는지 여부를 알고 싶어할 수 있으므로 인터페이스도 수정할 수 있습니다.이 경우 함수가 성공/실패 표시를 반환하도록 함수를 수정할 수 있습니다.

bool parseLong(const char *str, long *val)
{
    char *temp;
    bool rc = true;
    errno = 0;
    *val = strtol(str, &temp, 0);

    if (temp == str || *temp != '\0' ||
        ((*val == LONG_MIN || *val == LONG_MAX) && errno == ERANGE))
        rc = false;

    return rc;
}

다음과 같이 사용할 수 있습니다.

if (parseLong(str, &value))
    …conversion successful…
else
    …handle error…

'junk '문자열', big 'small too small'), 'trailing junk', 'value too big', 'value too small'(value too small 'value too small'(value 'no error')을 구분해야 합니다enum부울 리턴 코드 대신.후행 공백만 허용하고 다른 문자는 허용하지 않거나 선행 공백을 허용하지 않으려면 함수에서 더 많은 작업을 수행해야 합니다. 및 하며, 10진수를 8수, 10진 16진니로 . 엄격하게 10진수를 원한다면 통화의 0에서 10으로 변경해야 합니다.strtol().

라이브러리의 이라면, 은 기이표라러일가부경장않설합니다아야정우지를 설정하지 말아야 합니다.errno0errno:

int saved = errno;  // At the start, before errno = 0;

…rest of function…

if (errno == 0)     // Before the return
    errno = saved;

거의 다 왔어요. temp자체는 null이 아니지만 전체 문자열이 변환되면 null 문자를 가리킵니다. 따라서 참조를 취소해야 합니다.

if (*temp != '\0')

sttol에서 오류를 성공적으로 탐지하려면 어떻게 해야 합니까?

static long parseLong(const char * str) {
    int base = 0;
    char *endptr;
    errno = 0;
    long val = strtol(str, &endptr, base);

표준 C 라이브러리에서 지정/지원하는 3가지 테스트:

  1. 변환이 완료되었습니까?

     if (str == endptr) puts("No conversion.");
    
  2. 범위 내?

     // Best to set errno = 0 before the strtol() call.
     else if (errno == ERANGE) puts("Input out of long range.");
    
  3. 미행성 잡동사니?

     else if (*endptr) puts("Extra junk after the numeric text.");
    

성공.

    else printf("Success %ld\n", val);

과 같은 입력str == NULL또는base0이 아님, [2 ~ 36]은(는) 정의되지 않은 동작입니다.다양한 구현(C 라이브러리로의 확장)은 정의된 동작 및 보고서를 제공합니다.errno우리는 4번째 테스트를 추가할 수 있습니다.

    else if (errno) puts("Some implementation error found.");

또는 다음과 결합합니다.errno == ERANGE시험을


일반적인 구현 확장 기능도 활용하는 샘플 용어 코드입니다.

long my_parseLong(const char *str, int base, bool *success) {
    char *endptr = 0;
    errno = 0;
    long val = strtol(str, &endptr, base);
   
    if (success) {
      *success = endptr != str && errno == 0 && endptr && *endptr == '\0';
    }
    return val;
}

당신은 간접적인 수준을 놓치고 있습니다.문자가 종료 문자인지 확인하려고 합니다.NUL가 그고포 가터인리인 에는 그렇지 않습니다.NULL:

if (*temp != '\0')

그나저나, 이것은 오류 확인을 위한 좋은 접근법이 아닙니다.의 오류 strto*함수 패밀리는 출력 포인터를 문자열의 끝과 비교하여 수행되지 않습니다.을 0으로 으로 해야 합니다.errno.

확인해야 합니다.

*temp != '\0'

또한 다음에 따라 스트로톨을 호출한 후 errno 값을 확인할 수 있어야 합니다.

RETURN VALUES
     The strtol(), strtoll(), strtoimax(), and strtoq() functions return the result
     of the conversion, unless the value would underflow or overflow.  If no conver-
     sion could be performed, 0 is returned and the global variable errno is set to
     EINVAL (the last feature is not portable across all platforms).  If an overflow
     or underflow occurs, errno is set to ERANGE and the function return value is
     clamped according to the following table.


       Function       underflow     overflow
       strtol()       LONG_MIN      LONG_MAX
       strtoll()      LLONG_MIN     LLONG_MAX
       strtoimax()    INTMAX_MIN    INTMAX_MAX
       strtoq()       LLONG_MIN     LLONG_MAX

언급URL : https://stackoverflow.com/questions/14176123/correct-usage-of-strtol

반응형