一項任務要求我限定輸入數字以確保它在我的機器上的無符號整數范圍內。我如何確定該范圍是多少?它說需要在執行時輸入輸入,并且不能對輸入的內容做出任何假設。
我嘗試使用插入不同的范圍(2^7、2^15、2^31),但它們都導致溢位。
uj5u.com熱心網友回復:
測驗字串是否轉換為
unsigned
用于strtoul()轉換為unsigned long. 然而,由于該函式將負文本轉換為正整數,因此strtol()請先使用。
bool valid_unsigned(const char *s, unsigned *uval) {
char *endptr;
errno = 0;
int base = 0; // Use 10 here if only decimal text acceptable.
long lvalue = strtol(s, &endptr, base);
if (s == endptr) {
*uval = 0;
return false; // No conversion
}
if (lvalue < 0) {
errno = ERANGE; // Perhaps calling code would like to test this.
*uval = 0;
return false; // Negative
}
if ((unsigned long) lvalue <= UINT_MAX && errno == 0) {
*uval = (unsigned) lvalue;
return true; // Success
}
#if UINT_MAX > LONG_MAX
// Still could be a value in the LONG_MAX...UINT_MAX range.
errno = 0;
unsigned long uvalue = strtoul(s, &endptr, base);
if (uvalue <= UINT_MAX && errno == 0) {
*uval = (unsigned) uvalue;
return true; // Success
}
#endif
errno = ERANGE;
*uval = UINT_MAX;
return false; // Too big.
}
待辦事項:測驗尾隨文本。
uj5u.com熱心網友回復:
如果您正在使用strtoul將字串輸入轉換為整數的函式,則無需自行確定輸入是否大于ULONG_MAX. 該函式strtoul將通過相應地設定 的值來報告這一點errno。但是,根據平臺的不同,anunsigned long可能比 . 表示更多的數字unsigned int。因此,在函式strtoul報告輸入范圍正常后,您應該額外驗證數字不大于UINT_MAX。
使用該函式的另一個問題strtoul是它將接受負數作為有效值。因此,我們必須檢查自己是否第一個非空白字符是減號。
這是一個示例程式,它使用一個函式,該函式get_unsigned_int_from_user將繼續提示用戶輸入,直到輸入有效并且在 a 范圍內unsigned int:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>
unsigned int get_unsigned_int_from_user( const char *prompt )
{
for (;;) //loop forever until user enters a valid number
{
char buffer[1024], *p, *q;
unsigned long ul;
//prompt user for input
fputs( prompt, stdout );
//get one line of input from input stream
if ( fgets( buffer, sizeof buffer, stdin ) == NULL )
{
fprintf( stderr, "unrecoverable error reading from input\n" );
exit( EXIT_FAILURE );
}
//make sure that entire line was read in (i.e. that
//the buffer was not too small)
if ( strchr( buffer, '\n' ) == NULL && !feof( stdin ) )
{
int c;
printf( "line input was too long!\n" );
//discard remainder of line
do
{
c = getchar();
if ( c == EOF )
{
fprintf( stderr, "unrecoverable error reading from input\n" );
exit( EXIT_FAILURE );
}
} while ( c != '\n' );
continue;
}
//make "p" point to first non-whitespace character
for ( p = buffer; isspace( (unsigned char)*p ); p )
;
//since the function "strtoul" accepts negative
//input as valid input, which we don't want, we must
//first check ourselves whether the input starts
//with a minus sign
if ( *p == '-' )
{
printf( "number must not be negative!\n" );
continue;
}
//attempt to convert string to number
errno = 0;
ul = strtoul( p, &q, 10 );
if ( q == p )
{
printf( "error converting string to number\n" );
continue;
}
//make sure that number is representable as an "unsigned int"
if ( errno == ERANGE || ul > UINT_MAX )
{
printf( "number out of range error\n" );
continue;
}
//make sure that remainder of line contains only whitespace,
//so that input such as "6sdfh4q" gets rejected
for ( ; *q != '\0'; q )
{
if ( !isspace( (unsigned char)*q ) )
{
printf( "unexpected input encountered!\n" );
//cannot use `continue` here, because that would go to
//the next iteration of the innermost loop, but we
//want to go to the next iteration of the outer loop
goto continue_outer_loop;
}
}
return ul;
continue_outer_loop:
continue;
}
}
int main( void )
{
unsigned int num;
num = get_unsigned_int_from_user( "Please enter a number: " );
printf( "Input is valid, you entered: %u\n", num );
}
該程式具有以下行為:
Please enter a number: -1
number must not be negative!
Please enter a number: -5000000000
number must not be negative!
Please enter a number: 5000000000
number out of range error
Please enter a number: 4000000000
Input is valid, you entered: 4000000000
該程式以這種方式運行是因為在大多數常見平臺上UINT_MAX具有價值。4294967295
該函式是我的這個答案的get_unsigned_int_from_user我的函式的修改版本。有關該功能如何作業的更多資訊,請參閱該答案。get_int_from_user
uj5u.com熱心網友回復:
C 標準的每個實作都選擇了基本(這里是整數)型別的大小。所以 an
int保證至少 16 位寬,但也可以是 32 或 64 位寬。請參閱:整數型別和資料模型。為簡單起見,我們假設 an
int為 32 位。那么 的值UINT_MAX將是:4294967295。此令牌長 10 位。因此,如果您的輸入長度超過 10 位,則您的輸入肯定超出范圍(@chux-ReinstateMonica 在下面的評論中提出了一個很好的觀點,例如“ 000000000000000001”的輸入將超過 10 位,但仍在unsigned int)。即使您的輸入有 10 位數字,它仍然可能大于
UINT_MAX. 因此,將字串決議為unsigned long(strtoul) 并測驗該值是否小于或等于UINT_MAX。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/532229.html
標籤:C
