在发现最小和最大问题时STRCPY和STRCMP存在问题

时间:2017-12-16 04:08:32

标签: c

我正在编写一个程序,根据K.N.King问题中的字典顺序找到最小和最大的单词。找到一个单词中最大和最小的单词,直到用户输入一个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

4 个答案:

答案 0 :(得分:1)

我怀疑主要问题是max或min总是不正确的,因为它们是空的(或充满垃圾)开始。您应该将代码重新格式化为样式:

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

while (length != 4) 
    do stuff

我还建议使用fgets()getline()来读取输入,以防万一你只留出空间为20时决定输入100个字符。与strcpy()相同,它应该是取而代之的是strncpy()以防万一。所以结果看起来像是:

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

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

答案 1 :(得分:1)

问题是由未初始化的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。它可能会工作一段时间   不得。这是关于它的事情。没有初始化时你   比较然后没有定义行为。可能会有一些错误   令人惊讶的是给出了正确的结果。

答案 2 :(得分:1)

您不能初始化 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被弃用以及之后从标准中删除之外,还有没有方式来保护如果使用此功能,则缓冲区溢出。进一步的细节可以找到here,其中还包括一个非常方便的解决方案。

答案 3 :(得分:0)

<强>修

#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); 

}

请参阅live code

注意:使用fgets()比使用gets()更安全。 get()危险的原因是每个article潜在缓冲区溢出的b / c。但是,使用fgets(),输入可能会以换行符结束,因此您需要删除它。虽然你可以使用strtok()来实现这一目标。它并没有考虑到这种可能性,因为chux评论说,如果用户的输入包含换行符,则它是不合适的。

我再次修改了这个答案,从here获得了一个提示。该技术利用strcspn()返回str1中的字符数而不是str2中的字符数。因此,每当输入包含一个或多个可打印字符或换行符时,换行符都会被替换。因此,我在ideaone.com上修改了代码和输入。所以,现在输出反映最大的单词是企鹅,最小的单词是空字符串。但是,如果你只使用OP的original input来运行代码,那么结果将分别是企鹅承担分别是按字典顺序排列的最大和最小的单词。