2013-10-02 9 views
2

我是編程和C的新手,目前正在大學學習。這是一個任務,所以我想避免直接的答案,但更多的技巧或提示/推後正確的方向。使用strtol驗證整數輸入ANSI C

我想使用strtol來驗證我的鍵盤輸入,更具體地說,測試輸入是否是數字。我查看了其他網站和其他網站上的其他問題,並按照其他用戶的說明進行了操作,但這並沒有幫助我。

從我讀/理解strtol將的(長整型與strtol(爲const char *海峽,字符** endptr,INT基地);)如果endptr是不是一個空指針的函數將設置數值後的第一個字符的值爲endptr

因此,如果我要輸入84948ldfk,endptr將指向'l',告訴我在輸入中有數字以外的字符,並且會使其無效。

但在我的情況下,發生了什麼事情,無論我輸入什麼,我的程序都返回一個無效輸入。這裏是我的代碼:

void run_perf_square(int *option_stats) 
{ 
    char input[MAX_NUM_INPUT + EXTRA_SPACES]; /*MAX_NUM_INPUT + EXTRA_SPACES are defined 
               *in header file. MAX_NUM_INPUT = 7 
               *and EXTRA_SPACES 
               *(for '\n' and '\0') = 2. */ 
    char *ptr; 
    unsigned num=0; /*num is unsigned as it was specified in the start up code for the 
        *assignment. I am not allow to change it*/ 

    printf("Perfect Square\n"); 
    printf("--------------\n"); 
    printf("Enter a positive integer (1 - 1000000):\n"); 
    if(fgets(input, sizeof input, stdin) != NULL) 
    { 
     num=strtol(input, &ptr, 10); 
     if(num > 1000001) 
     { 
     printf("Invalid Input! PLease enter a positive integer between 1 
        and 1000000\n"); 
     read_rest_of_line();  /*clears buffer to avoid overflows*/ 
     run_perf_square(option_stats); 
     } 
     else if (num <= 0) 
     { 
     printf("Invalid Input! PLease enter a positive integer between 1 
        and 1000000\n"); 
     run_perf_square(option_stats); 
     } 
     else if(ptr != NULL) 
     { 
     printf("Invalid Input! PLease enter a positive integer between 1 
        and 1000000\n"); 
     run_perf_square(option_stats); 
     } 
     else 
     { 
     perfect_squares(option_stats, num); 
     } 
    } 
} 

任何人都可以幫助我在正確的方向嗎?顯然,錯誤是與我的如果(ptr!= NULL)條件,但據我瞭解,似乎是正確的。正如我所說,我已經看過以前的類似問題,並在答案中提出了建議,但它似乎並不適用於我。因此,我認爲最好能夠根據我自己的情況尋求我的幫助。

在此先感謝!

編輯:好的我得到它的工作,並經過一些測試後,似乎工作正常。我的if語句是個問題。下面的代碼爲我工作至今:

if((input[0] != '\n' && (*ptr == '\0' || *ptr == '\n')) && num < 1000001 && num > 0) 
{ 
    perfect_squares(option_stats, num); 
} 
else 
{ 
    printf("Invalid Input! PLease enter a positive integer between 1 
      and 1000000\n"); 
    if(num > 1000001) 
    { 
     read_rest_of_line(); 
    } 
    run_perf_square(option_stats); 
} 

我可能會清理if語句,使之少一些混亂,但對結果滿意爲止。

+0

'否則如果(NUM <= 0)' – chux

+0

您好chux,我的輸入必須是大於0,不能等於它。 – Lukaaaaaaaay

+1

'else if(num <= 0)'_is_您的錯誤情況。 – chux

回答

3

你檢查strtol順序錯誤的結果,檢查ptr第一,也不會檢查PTR對NULL,derference並檢查它指向的NUL'\0')字符串結束。

if (*ptr == '\0') { 
    // this means all characters were parsed and converted to `long` 
} 
else { 
    // this means either no characters were parsed correctly in which 
    // case the return value is completely invalid 
    // or 
    // there was a partial parsing of a number to `long` which is returned 
    // and ptr points to the remaining string 
} 

num > 1000001也需要num > 1000000

num < 0也需要num < 1

您也可以與一些改組和邏輯的調整瓦解你的序列if語句下降到僅 一個無效的分支和一個好的分支。

+0

感謝您的幫助特洛伊! 我做了你所建議的改變,但代碼是一樣的。我的輸入驗證分支現在是: if(* ptr =='\ 0'&& num <1000001&#num> 0) { perfect_squares(option_stats,num); } 其他 {printf的 (「錯誤消息);如果 (NUM> 1000000) { read_rest_of_line();} run_perf_square(option_stats);} 這裏 – Lukaaaaaaaay

+1

有一個看看:HTTP:// coliru。 stack-crooked.com/a/bb5c10b2cc6860c5 – goji

+0

更好的解決方案可能是完全拋棄'strtol','fgets'並使用'fscanf'。 – goji

0

函數strtol返回long int,它是一個有符號的值。我建議你使用另一個變量(entry_num),你可以測試< 0,從而檢測負數。

我也建議,正則表達式可以測試字符串輸入數字和有效的輸入,或者你可以使用的strtok和任何東西,但數字作爲分隔符;-)或者你可以使用驗證,喜歡的東西掃描輸入字符串:

int validate_input (char* input) 
{ 
    char *p = input; 
    if(!input) return 0; 
    for(p=input; *p && (isdigit(*p) || iswhite(*p)); ++p) 
    { 
    } 
    if(*p) return 0; 
    return 1; 
} 
2

OP想避免直接回答....

驗證整數輸入

  1. 獨立的I/O驗證 - 2種不同的功能。

  2. I/O:假定有敵意的輸入。 (文本,文本太多,文本太少,I/O錯誤。)您是否想將前導空格作爲I/O的一部分使用?你想要消耗領先的0作爲I/O的一部分嗎? (建議不要)

  3. 驗證字符串(NULL,鉛空間OK?數字尾隨空間後,太短,太長,欠範圍,超範圍,是123.0一個確定整數)

  4. strtol()是你的朋友做重型轉換提升。檢查後應如何設置和測試errno。使用endptr。它的價值應該在什麼時候設定。之後如何測試。它消耗領先的空間,是嗎?它將文本轉換爲long,但OP需要模糊的「整數」。

Qapla」