2016-07-01 3 views
-3
#include<stdio.h> 
void main() 
{ 
    unsigned int a; 
    printf("Enter a number:"); 
    scanf("%u",&a); 
    if (a <= 4294967295) { 
     printf("Entered no is within limit\n"); 
    } 
    else { 
     printf("Entered no is not in the limit"); 
    } 
} 

위의 조건으로 else 블록을 실행할 입력 번호는 무엇입니까?gcc를 사용하여 입력 데이터의 래핑을 피하는 방법?

if 블록은 입력이 제한보다 크지 만 항상 실행됩니다. 포장하기 때문입니다. 배치 방법을 찾을 수있는 방법이 있습니까?

부호 INT의 최대 한계는 4294967295이고 내 입력이 0 32 개 비트 1이어서된다 우리는 하나의 33 비트를 액세스 할 수 4294967296 경우는 이진 1의 32 비트이기 때문이다 33 번째 비트에 액세스 할 수 있습니까?

+3

32 비트 정수를 사용하면 조건은 항상 true입니다. 그리고 그게 다야. – Lundin

+0

앞서 언급했듯이 64 비트 정수가 필요할 것입니다. 이러한 아키텍처는 사용중인 아키텍처에 따라 달라질 수 있습니다. 어떤 아키텍처를 사용하고 있습니까? 또는 적어도 sizeof (long)와 sizeof (long long) gcc가 어떤 것인지 알려주십시오. 만약''4 ''라면 운이 나옵니다 (또는 적어도 문제는 훨씬 더 어려워지고 있습니다). 만약 그들 중 하나가 '4'보다 크다면 당신은'서명되지 않은 '대신 그것을 사용할 수 있습니다. – skyking

+0

unsigned int 대신 long long 변수를 사용하십시오. 'scanf '에 대한 포맷은 "% ld"또는 "%"가 될 것입니다. PRId64 – LPs

답변

3

위의 조건으로 else 블록을 실행할 입력 번호는 무엇입니까?

는 대부분의 경우 시스템은 else 블록을 실행할 수있는 입력이 없을 최대치 4294967295

그렇다면 32 비트 부호 INT를 이용한다.

많은 사람들이 언급했듯이 간단한 해결책은 가능한 경우 더 많은 비트가있는 변수를 사용하는 것입니다. 그러나 @Brendan이 지적한 바와 같이 그것은 단지 당신에게 다른 문제를줍니다.

#include <stdio.h> 
#include <limits.h> 

// Returns 1 if the string can by converted to unsigned int without overflow 
// else return 0 
int string2unsigned(const char* s, unsigned int* u) 
{ 
    unsigned int t = 0; 
    if (*s > '9' || *s < '0') return 0;  // Check for unexpected char 
    while(*s) 
    { 
     if (*s == '\n') break;     // Stop if '\n' is found 
     if (*s > '9' || *s < '0') return 0;  // Check for unexpected char 
     if (t > UINT_MAX/10) return 0;   // Check for overflow 
     t = 10 * t; 
     if (t > UINT_MAX - (*s - '0')) return 0; // Check for overflow 
     t = t + (*s - '0'); 
     s++; 
    } 
    *u = t; 
    return 1; 
} 

int main(void) { 
    unsigned int u; 
    char s[100]; 
    if (!fgets(s, 100, stdin)) // Use fgets to read a line 
    { 
     printf("Failed to read input\n"); 
    } 
    else 
    { 
     if (string2unsigned(s, &u)) 
     { 
      printf("OK %u\n", u); 
     } 
     else 
     { 
      printf("Illegal %s", s); 
     } 
    } 
    return 0; 
} 

예 :

input: 4294967295 
output: OK 4294967295 

input: 4294967296 
output: Illegal 4294967296 

보다 강력한 솔루션 대신에 이런 일이 될 수 scanf

이러한 기능을 사용하는 입력을 구문 분석하는 자신의 함수를 작성하는 것입니다

(내 원본 코드에 대한 더 나은 대안을 제시 한 @chux에 감사)

+0

'string2unsigned()'는 일반적인 입력에 실패합니다. – chux

+0

'if (v/10! = t)','if (t> UINT_MAX/10)가 0을 반환한다; t * = 10;' – chux

+1

@chux - 당신의 대안이 제 원래 코드보다 훨씬 뛰어나므로 코드를 업데이트했습니다 - 고마워요. 나는 또한''fgets''의 입력으로 직접 호출했을 때 좀 더 논리적으로 보인'\ n'에서 멈추도록 함수를 변경했습니다. 문제를 지적 해 주셔서 감사합니다. – 4386427

2

더 많은 정수 유형 (더 많은 비트 포함)을 사용하는 것은 잘못되어 손상되었습니다. 모든 일은 새로운 문제를 제기하는 것입니다 (예 : 18446744073709551615 이상의 숫자를 허용하지 않는 경우).

사용자 인터페이스 디자인 용; 단일 "입력 된 숫자가 제한 내에 없습니다"라는 오류 메시지는 받아 들일 수 없습니다. 실제 문제가 무엇인지 사용자에게 알려야하며 사용자에게 예상되는 것을 상기시켜야합니다. 받은 없음 입력 (stdin은 포기하지

  • : 최소한

    , 당신이 처리해야 (따라서 적어도 4 가지 오류 메시지는 표시 할 수 있어야한다) 오류의 적어도 4 가지 종류가있다 당신은 EOF)

  • 입력 유효한 문자가 아닌 뭔가를 포함 (예를 들면 바이트 × 00, 잘못된 UTF-8 멀티 바이트 시퀀스, 0x7F의 위의 ASCII 문자 등)

  • 입력에 인식 할 수없는/허용되지 않는 문자가 포함되어 있습니다 (예 : 사용자가 "Bork!"또는 "0x1234"또는 "twelve"를 입력했습니다. 또는 사용자가 "12,345"를 입력했습니다.00 "이고 코드에서 1000의 구분 기호 또는 분수를 처리 할 수 ​​없음)

  • 입력이 유효한 숫자이지만 특정 범위 내에 있지 않습니다."-1234 "와 같은 음수 값을 포함 할 수 있습니다 (이 경우 빼기 부호 잘못된 오류 메시지의 원인이 인식/용인되지 문자로 처리해서는 안)을 제공 할

이 또한 한계가 사용하는 변수 유형의 크기에 의존하지 않습니다;. 변수 유형의 크기 예를 들어, 누군가에게 나이를 입력하라는 메시지를 표시하고 "12345"를 입력하면 "범위를 벗어났습니다 (나이는 1에서 150 사이 여야 함)"라는 오류 메시지가 나타납니다. w에 상관없이 그렇지 않으면 오버 플로우가 발생하는지 여부. 이 경우 제한은 150이됩니다 (아무도 그 나이가 될 가능성이 없으므로 INT_MAX과 같은 것이 아닙니다). 제한은 150이므로 변수 유형으로 signed char을 사용할 수 없지만 uint8_t (또는 그 이상)을 사용할 수 있습니다.

이 모든 것을 염두에두고; scanf()은 "인간의 문자열"을 구문 분석하는 데 사용할 수 없습니다. 자신 만의 파서를 작성하거나 적절한 ("비표준"라이브러리) 것을 찾아야합니다.

+0

더 많은 비트를 사용하는 것이 좋은 점입니다. 해결책이 아닙니다. 멋지다. – 4386427