문제

문자열에 큰 숫자가 저장되어 있고 한 자리 숫자를 추출하려고 합니다.그런데 그 호출들 사이의 차이점은 무엇입니까?

#include <iostream>
#include <string>

int main(){
    std::string bigNumber = "93485720394857230";
    char tmp = bigNumber.at(5);
    int digit = atoi(&tmp);
    int digit2 = atoi(&bigNumber.at(5))
    int digit3 = atoi(&bigNumber.at(12));
    std::cout << "digit: " << digit << std::endl;
    std::cout << "digit2: " << digit2 << std::endl;
    std::cout << "digit3: " << digit3 << std::endl;
}

그러면 다음과 같은 출력이 생성됩니다.

숫자:7

숫자2:2147483647

숫자3:57230

첫 번째는 원하는 결과입니다.두 번째는 문자열에서 찾을 수 없는 임의의 숫자인 것 같습니다.세 번째는 문자열의 끝인데 예상했던 것처럼 한자리 숫자가 아니라 12번째 인덱스부터 문자열의 끝까지 올라갑니다.누군가 나에게 다른 출력을 설명해 줄 수 있습니까?

편집하다:이것이 수용 가능한 해결책일까요?

char tmp[2] = {bigNumber.at(5), '\0'};
int digit = atoi(tmp);
std::cout << "digit: " << digit << std::endl;
도움이 되었습니까?

해결책

그것은 모두 어느 정도 설명 가능합니다.

int main(){
    std::string bigNumber = "93485720394857230";

이 줄은 단일 문자 '5'를 문자 변수에 복사합니다. atoi 이것을 올바르게 변환합니다. atoi 문자열 매개변수는 유효한 0으로 끝나는 문자열일 것으로 예상합니다. &tmp 문자 변수에 대한 포인터일 뿐입니다. 메모리의 문자 바로 뒤에 오는 메모리를 알 수 없으므로 이 호출의 동작은 정의되지 않습니다.정확하게 말하면 null로 끝나는 문자열을 생성하여 전달해야 합니다.*

    char tmp = bigNumber.at(5);
    int digit = atoi(&tmp);

이 줄은 문자열의 위치 5에 있는 문자에 대한 포인터를 가져옵니다.이는 위의 원래 큰 숫자 문자열에 대한 포인터입니다. 따라서 문자열 매개변수는 atoi 문자열 "5720394857230"처럼 보입니다. atoi 32비트 정수가 이것을 보유하지 않기 때문에 이것을 정수로 바꾸려고 하면 분명히 오버플로됩니다.

    int digit2 = atoi(&bigNumber.at(5))

이 줄은 위치 12의 문자열에 대한 포인터를 가져옵니다.매개변수는 atoi 문자열 "57230"입니다.이는 정수 57230으로 올바르게 변환됩니다.

    int digit3 = atoi(&bigNumber.at(12));

... }

C++를 사용하고 있으므로 문자열을 정수로 변환하는 더 좋은 방법이 있습니다.내가 좋아하는 것 중 하나는 Boost lexical_cast 라이브러리입니다.다음과 같이 사용할 수 있습니다.

char tmp = bigNumber.at(5);
// convert the character to a string then to an integer
int digit = boost::lexical_cast<int>(std::string(tmp));

// this copies the whole target string at position 5 and then attempts conversion
// if the conversion fails, then a bad_lexical_cast is thrown
int digit2=boost::lexical_cast<int>(std::string(bigNumber.at(5)));

* 엄밀히 말하면, atoi 숫자가 아닌 문자를 찾을 때까지 숫자를 검색합니다.언제 찾을 것인지, 유효하지 않은 메모리 위치를 읽을 때 무엇을 할 것인지는 명확하게 정의되어 있지 않습니다.

다른 팁

두 번째 숫자가 표시되는 이유를 알고 있습니다.

ATOI 참조에서.

올바른 값이 표현 가능한 값 범위를 벗어난 경우 INT_MAX 또는 int_min이 반환됩니다.

2147483647은 int_max입니다

bigNumber.at() 단일 문자로 새 문자열을 반환하지는 않지만 문자열의 문자 주소를 반환합니다. 두 번째 호출은 실제로 다음과 같습니다.

atoi("720394857230")

내부 알고리즘이 오버플로 발생합니다.

또한 첫 번째 호출은 메모리의 (임의) 값에 따라 매우 위험합니다. (&tmp)+1.

두 문자로 문자열을 할당하고 단일 문자를 할당해야합니다. bigNumber.at() 첫 번째와 \0 두 번째로 전화하십시오 atoi() 임시 문자열의 주소로.

논쟁 atoi 제로 종료 문자열이어야합니다.

기능 at 문자열에서 Char에 대한 포인터를 제공합니다. 기능 atoi 문자열을 하나의 숯뿐만 아니라 int로 변환합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top