簡體   English   中英

在發現最小和最大問題時STRCPY和STRCMP存在問題

[英]Problems with STRCPY and STRCMP when finding the smallest and largest problems

我正在編寫一個程序,根據KNKing問題中的字典順序找到最小和最大的單詞。 找到一個單詞中最大和最小的單詞,直到用戶輸入一個4個字母的單詞。

首先,我使用strcmp來比較輸入字與最大或最小。 然后使用strcpy將輸入字符串復制到最大或最小。

#include <string.h>
#include <stdio.h>

main()
{
    char inputStr[20] ;
    char max[20];
    char min[20];
    int length =0;
    do
    {
        printf("pls, input your string: ");
        gets(inputStr);
        if(strcmp(inputStr,max) > 0)
            strcpy(max,inputStr);
        if (strcmp(inputStr,min) < 0)
            strcpy(min,inputStr);

        length = strlen(inputStr);  
    }
    while (length != 4);
        printf("largest word is: %s\n",max);
        printf("smallest word is: %s",min); 

}

例如。

Enter Word : Cat
Enter Word : Dog
Enter Word : penguin
Enter Word : bear

the smallest word is bear
the largest word is penguin

但是,在運行程序時,最大的單詞始終是特殊字符,最小的單詞始終是正確的。 我的程序顯示了結果

the largest word is:         
 the smallest word is: bear

我懷疑主要的問題是max或min總是不正確的,因為它們是空的(或充滿垃圾)開始。 您應該將代碼重新格式化為樣式:

min = max = initial-input()
length = len(min)

while (length != 4) 
    do stuff

我還建議使用fgets()getline()來讀取輸入,以防萬一你只留出20個字符而只留出20個字符。與strcpy()相同,它應該被替換為strncpy()案件。 所以結果看起來像:

...
fgets(inputStr, 20, stdin);
strncpy(max, inputStr, 20);
strncpy(min, inputStr, 20);
length = strlen(inputStr);

while(length != 4) {
     ...
}

問題是由於未初始化的char數組。 這(在strcmp使用它)是未定義的行為。 從邏輯上講,您的代碼也無法正常運行。 strcasecmp不是標准的一部分 - 它是POSIX的東西。

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAXLETTER 20
int main(void)
{
    char inputStr[MAXLETTER] ;
    char max[MAXLETTER];
    char min[MAXLETTER];
    size_t length =0;
    bool flag = true;
    do
    {
        printf("pls, input your string: ");
        if( fgets(inputStr,sizeof inputStr,stdin) == NULL){
            fprintf(stderr, "%s\n", "Error in input");
            exit(1);
        }
        inputStr[strcspn(inputStr,"\n")]='\0';
        if(flag){
            strncpy(max,inputStr,MAXLETTER-1);
            strncpy(min,inputStr,MAXLETTER-1);
            max[MAXLETTER-1]=0;
            min[MAXLETTER-1]=0;
            flag = false;
        }
        if(strcasecmp(inputStr,max) > 0){
            strncpy(max,inputStr,MAXLETTER-1);
            max[MAXLETTER-1]=0;
        }            
        if (strcasecmp(inputStr,min) < 0){
            strncpy(min,inputStr,MAXLETTER-1);
            min[MAXLETTER-1]=0;
        }
        length = strlen(inputStr);  
    }
    while (length != 4);
    printf("largest word is: %s\n",max);
    printf("smallest word is: %s",min); 
    return 0;
}

使用gcc -Wall -Wextra -Werror progname.c編譯你的程序,它會告訴你哪里出錯了。

一件事, 不要使用gets()

我錯了,因為我沒有初始化max和min。 但是,該程序仍然運行min ...

它被稱為Undefined behavior 它可能會工作一段時間,也可能不會。 這是關於它的事情。 在比較時沒有初始化,則沒有定義行為。 它可能會出現一些錯誤,可能會令人驚訝地給出正確的結果。

您沒有按比例初始化 maxmin因此在第一次比較它們時它們將被設置為任意值。

無論比較如何 ,您只需將它們設置為第一個單詞即可解決此問題:

int firstTime = 1;
do
{
    printf("Please input your string: ");
    gets(inputStr);
    if (firstTime || (strcmp(inputStr, max) > 0))
        strcpy(max, inputStr);
    if (firstTime || (strcmp(inputStr, min) < 0))
        strcpy(min, inputStr);
    firstTime = 0;
    length = strlen(inputStr);  
}

而且,順便說一句,有一個原因是為什么不推薦使用gets並從標准中刪除,如果你使用這個函數,就沒有辦法防止緩沖區溢出。 這里可以找到更多細節,其中還包括一個非常方便的問題解決方案。

修訂

#include <stdio.h>
#include <string.h>

#define N 20

int main( void )
{

    char max[N];
    char min[N];
    char (*ch)[N];
    char inputStr[N] ;
    int length = 0;


    fgets(inputStr, sizeof(inputStr), stdin);

    // Technique from https://stackoverflow.com/a/28462221/701302
    inputStr[strcspn(inputStr, "\n")] = 0;

    // Set both max and min to initial input  in order to ...
    strcpy(max,inputStr);
    strcpy(min,inputStr);

    do
    {
        fgets(inputStr, sizeof(inputStr), stdin);

        inputStr[strcspn(inputStr, "\n")] = 0;

        // ... now have basis for valid comparison
        if (strcmp(inputStr,max) > 0){ 
            strcpy(max,inputStr);
        }
        else
        if ( strcmp(inputStr,min)  < 0){
            strcpy(min,inputStr);
        }    
        length = strlen(inputStr);  
    } while (length != 4);

     printf("largest word is: %s\n",max);

     ch = &min;
     if (strcmp(ch,"") == 0){
        ch = "[empty string]";
     }
     printf("smallest word is: %s",ch); 

}

查看實時代碼

注意:使用fgets()比使用gets()更安全。 get()危險的原因是本文中潛在緩沖區溢出的b / c。 但是,使用fgets(),輸入可能會以換行符結束,因此您需要刪除它。 盡管你可能會使用strtok(),但它的設計並沒有考慮到這種可能性,因為chux評論說,如果用戶的輸入包含換行符,則不夠。

我再次修改了這個答案,從這里得到了一個提示。 該技術利用strcspn()返回str1中的字符數而不是str2中的字符數。因此,每當輸入包含一個或多個可打印字符或換行符時,換行符都會被替換。 因此,我在ideaone.com上修改了代碼和輸入。 所以,現在輸出反映最大的單詞是企鵝 ,最小的單詞是空字符串。 但是,如果您運行僅使用代碼原始輸入的OP,那么結果將是企鵝分別作為最大和最小字字典順序發言。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM