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

Kar*_*ann 2 c defensive-programming repeat

我试图用防御性编程来做这个小程序,但是我很难处理这个避免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;
}
Run Code Online (Sandbox Code Playgroud)

Iha*_*imi 5

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

  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);
}
Run Code Online (Sandbox Code Playgroud)

请注意,通过使用函数,该程序的流程控制清晰简单.这正是为什么goto气馁,不是因为它是一个邪恶的东西,而是因为它可能像你一样被误用.