用不同的编程结构替换`goto`

时间:2018-02-09 13:59:29

标签: c repeat defensive-programming

我试图用防御性编程来完成这个小程序但是我很难处理这个避免Loop-Goto,因为我知道这是BAD编程。我曾尝试过,并且做...而循环,但在一个案例中,我没有问题。当我要做另一个时,问题开始......而对于第二种情况(“不插入空格或点击输入按钮”)。我尝试并嵌套做...虽然但这里结果更复杂。

#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 个答案:

答案 0 :(得分:5)

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

  1. 在输入程序后检查字符串的长度,以便在缓冲区溢出后发生
  2. 您使用的multiprocessing.Process没有检查输入长度,因此很容易出现缓冲区溢出。
  3. 改为使用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); } 被劝阻的原因,不是因为它是一个邪恶的东西,而是因为它可能像你一样被滥用。

答案 1 :(得分:2)

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

char * user_input() - 返回来自用户的输入作为指向char的指针(使用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;
}