代码之家  ›  专栏  ›  技术社区  ›  Karajohann

用不同的编程构造替换“goto”

  •  2
  • Karajohann  · 技术社区  · 6 年前

    我正试图用防御编程来做这个小程序,但要处理这个问题就很困难了,因为我知道循环转到是糟糕的编程。我试了一会儿,做了。。。虽然循环,但在一个情况下,我没有问题。当我要做另一件事时,问题开始了。。。而对于第二种情况(“不插入空格或单击enter按钮”)。我试过并嵌套了。。。但这里的结果更复杂。

    #include <ctype.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main()
    {
        int i;
        int length;
        char giventext [25];        
        Loop:
    
        printf("String must have 25 chars lenght:\n");
        gets(giventext);
    
        length = strlen(giventext);
    
        if (length > 25) {
            printf("\nString has over %d chars.\nMust give a shorter string\n", length);
            goto Loop;
        }
        /* Here i trying to not give space or nothing*/
        if (length < 1) {
            printf("You dont give anything as a string.\n");
            goto Loop;
        } else {
            printf("Your string has %d\n",length);
            printf("Letter in lower case are: \n");
    
            for (i = 0; i < length; i++) {
                if (islower(giventext[i])) {                            
                    printf("%c",giventext[i]);
                }
            }
        }
        return 0;
    }
    
    2 回复  |  直到 6 年前
        1
  •  5
  •   Iharob Al Asimi    6 年前

    请注意,您的代码根本不是防御性的。您无法避免缓冲区溢出,因为,

    1. 在将字符串输入到程序后检查字符串的长度,以便在缓冲区溢出发生后
    2. 您使用 gets() 它不检查输入长度,因此很容易发生缓冲区溢出。

    使用 fgets() 而是丢弃额外的字符。

    我想你应该明白 strlen() 不计算输入的字符数,而是计算字符串中的字符数。

    如果要确保 N 然后插入字符

    int
    readinput(char *const buffer, int maxlen)
    {
        int count;
        int next;
    
        fputc('>', stdout);
        fputc(' ', stdout);
    
        count = 0;
        while ((next = fgetc(stdin)) && (next != EOF) && (next != '\n')) {
            // We need space for the terminating '\0';
            if (count == maxlen - 1) {
                // Discard extra characters before returning
                // read until EOF or '\n' is found
                while ((next = fgetc(stdin)) && (next != EOF) && (next != '\n'))
                    ;
                return -1;
            }
            buffer[count++] = next;
        }
        buffer[count] = '\0';
        return count;
    }
    
    int
    main(void)
    {
        char string[8];
        int result;
    
        while ((result = readinput(string, (int) sizeof(string))) == -1) {
            fprintf(stderr, "you cannot input more than `%d' characters\n", 
                                (int) sizeof(string) - 1);
        }
        fprintf(stdout, "accepted `%s' (%d)\n", string, result);
    }
    

    请注意,通过使用函数,此程序的流控制清晰而简单。这就是为什么 goto 感到沮丧,不是因为这是一件坏事,而是因为它可能像你一样被滥用。

        2
  •  2
  •   laker93    6 年前

    尝试使用标记程序需要执行的逻辑步骤的函数:

    char * user_input() -返回用户的输入,作为指向字符的指针(使用 get() ! 例如,看看 scanf )

    bool validate_input(char * str_input) -从上述函数中获取用户输入并执行检查,例如验证长度是否在1到25个字符之间。

    str_to_lower(char * str_input) -如果 validate_input() 返回true,然后可以调用此函数并将用户输入传递给它。然后,此函数的主体可以以小写形式将用户输入打印回控制台。您可以使用标准库函数 tolower() 此处为每个字符的小写字母。

    然后,主函数的主体将更加简单,并执行一系列逻辑步骤来解决您的问题。这是防御性编程的本质——将问题模块化为独立的步骤,这些步骤是自包含的,并且易于测试。

    主要功能的可能结构可以是:

    char * user_input();
    bool validate_input(char *);
    void str_to_lower(char *);
    
    int main()
    {
        char * str_input = user_input();
    
        //continue to get input from the user until it satisfies the requirements of 'validate_input()'
        while(!validate_input(str_input)) { 
            str_input = user_input();
        }
    
        //user input now satisfied 'validate_input' so lower case and print it
        str_to_lower(str_input);
        return 0;
    }