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を使ってcで入力データを折り返すのを避けるには?

ifブロックは、入力が制限を超えても常に実行されます。ラッピングのためです。ラッピングを見つける方法はありますか?

unsigned int型の上限は4294967295であり、私の入力が4294967296である場合、それは我々が1の33番目のビットにアクセスすることはできない0 の32ビットが続く1なるバイナリ 1の32ビットであるためであります その33ビットにアクセスする可能性はありますか?

+3

32ビットの整数を指定すると、条件は常にtrueになります。以上です。 – Lundin

+0

前述したように、おそらく64ビットの整数が必要になるでしょう。これらの可用性は、使用しているアーキテクチャによって異なる場合があります。どのアーキテクチャを使用していますか?あるいは、少なくともsizeof(long)とsizeof(long long)のgccレポートについて教えてください。それが '4'ならばあなたは不運です(少なくとも問題はもっと困難になっています)。もしそれらのうちの一つが' 4'より大きければ 'unsigned'の代わりにそれを使うことができます。 – skyking

+0

unsigned intではなくlong long変数を使用します。 'scanf'の書式は"%ld "または"% "になります。PRId64 – LPs

答えて

3

上記の条件でelseブロックを実行する入力番号はどれですか?もしそうなら

ほとんどのシステムは、最大値と4294967295

を32ビット符号なし整数を使用して、elseブロックをトリガすることができます入力がありません。

多くの人がコメントしているように、単純な解決策は、可能な場合はより多くのビットを持つ変数を使用することです。しかし、@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 

Aより堅牢なソリューションではなく、このようなものかもしれないscanf

このような機能を使っての入力を解析するために、独自の機能を書くことです

(私の元のコードのよりよい代替案を提案してくれた@chuxに感謝)

+0

'string2unsigned()'は一般的な入力で失敗します。 – chux

+0

'if(v/10!= t)'、 'if(t> UINT_MAX/10)は0を返します。 t * = 10; ' – chux

+1

@chux - 私の元のコードよりもはるかに優れているので、コードを更新しました。ありがとうございます。また、いくつかのチェックを追加し、関数を '\ n'で停止するように変更しました。これは' fgets'からの入力で直接呼び出すので、より論理的です。問題を指摘してくれてありがとう。 – 4386427

2

(より多くのビットを持つ)より大きな整数型を使うのは間違っていて壊れています。あなたが新しい問題を起こすだけです(例:18446744073709551615よりも上の数字を受け入れない場合)。

ユーザーインターフェイスデザインの場合。 1つの「入力された番号が制限内にない」というエラーメッセージは受け入れられません。あなたは本当の問題が何であるかをユーザーに伝える必要がありますまたあなたが期待していることをユーザーに思い出させる必要があります。

最低でも、あなたが処理するエラーの少なくとも4つの異なる種類(し、表示することができる必要があり、したがって、少なくとも4つの異なるエラーメッセージ)がある。

  • なし入力受信(stdinを与えあなたはEOF

  • 入力が有効な文字ではありません何かが含まれて(例えば、バイト0x00で、不正なUTF-8マルチバイトシーケンス、0x7Fを上記のASCII文字、など)

  • 入力に認識されない/受け入れられない文字が含まれています(例:ユーザーが「Bork!」、または「0x1234」、または「12」と入力した。またはユーザーが「12,345」と入力した。あなたのコードでは1000の区切り文字や小数点を扱うことができません)

  • 入力は有効な数値ですが、特定の範囲内にありません。「-1234」などの負の値が含まれている可能性があります。与えられるべき間違ったエラーメッセージの原因と認識されていない/未承認の文字として扱われるべきではない)

も制限が使用する変数の型のサイズに依存しないことに注意してください;変数の型のサイズたとえば、あなたが誰かに年齢を入力して "12345"と入力すると、 "範囲外の番号(年齢は1〜150でなければなりません)"というエラーメッセージが表示されるはずです。 wに関係なくそれはオーバーフローを引き起こすかどうかです。この場合、制限は150になります(INT_MAXのようなものではありません)。制限は150なので、signed charを変数タイプとして使用することはできませんが、uint8_t(またはそれ以上のもの)を使用することができます。

これを念頭において、 scanf()は、 "人間からの文字列"を解析するために決して使用できません。独自のパーサーを書くか、適切なもの( "非標準"ライブラリ)を見つける必要があります。

+0

より多くのビットを使用することについての良い点 - それは解決策ではありません。ナイスキャッチ。 – 4386427

関連する問題