C 编写仅使用循环和条件语句检查升序序列的代码

C 编写仅使用循环和条件语句检查升序序列的代码,c,c89,C,C89,我被要求用c语言编写一个代码,检查输入的字母顺序,并确定有多少合法顺序。顺序是这样的:我收到多个输入,数字从1-9开始,字母从A-Z开始,后跟“@”,这决定了输入的结束。收到数字后,我应检查以下字母,这意味着如果a收到数字3,我应检查接下来的3个字母,依此类推,这些字母应按字母升序排列。例如,ABC3DEF@ABC-不是合法序列。然而,3DEF是一个合法的序列,所以我总共有一个合法的序列 我尝试了一些东西,但不起作用,输出总是0!注意:我只允许使用循环和条件语句,这意味着没有数组、函数、指针。。

我被要求用c语言编写一个代码,检查输入的字母顺序,并确定有多少合法顺序。顺序是这样的:我收到多个输入,数字从1-9开始,字母从A-Z开始,后跟“@”,这决定了输入的结束。收到数字后,我应检查以下字母,这意味着如果a收到数字3,我应检查接下来的3个字母,依此类推,这些字母应按字母升序排列。例如,ABC3DEF@ABC-不是合法序列。然而,3DEF是一个合法的序列,所以我总共有一个合法的序列

我尝试了一些东西,但不起作用,输出总是0!注意:我只允许使用循环和条件语句,这意味着没有数组、函数、指针。。。。有没有我想不起来的想法?还是我的想法错了

int i, x, sum = 0;
char cha, c = 0;
while((cha = getchar()) != '@') {
    scanf("%d %c", &x, &cha);
    cha = c;
    if(x >= 1 && x <= 9) {
        for(i = 0; i < x; i++) {
            if(c == cha - i) {
                sum++;
            }
            c--;
        }
    }
}
每次测试while循环条件时,都会读取一个字符,如果它不是@,则会丢弃它。这些被丢弃的字符是需要解析的数据的一部分

每次调用scanf时,如果下一个字符是十进制数字或a+或a-,则将该字符和以下所有数字解析为十进制数字,然后读取并最终丢弃下一个字符

您根本不会尝试读取以下任何字符,也不会测试它们是否为字母而不是数字

如果输入中没有@字符,并且在某些情况下,即使有@字符,程序也不会终止。为了解决这个问题,除了测试“@”之外,还应该测试EOF。此外,要正确地执行此操作,必须将getchar的返回值存储为int;char不能表示EOF

基本上,所呈现的代码几乎没有任何效果


像您需要编写的解析器,倾向于显式或隐式地作为状态机编写。你从一个初始状态开始。您读取一些输入字符,并根据当前状态和读取的输入执行适当的操作,通常包括将当前状态更改为其他状态。起泡、冲洗、重复,直到达到一个终端状态,该状态至少应在输入结束时达到。

正如评论中指出的,混合使用scanf和getchar充满了陷阱。以代码为例,以解析字符串为目标ABC3DEF@. 您对getchar和scanf的调用说明了这个问题

while((cha = getchar()) != '@') {
    scanf("%d %c", &x, &cha);
    ...
}
当您阅读cha时,测试cha=getchar!='@'对于除“@”之外的每个字符都将为TRUE。因此,对于第一次读取时的序列,cha='A'和BC3DEF@保留在stdin中。然后尝试使用scanf%d%c、&x、&cha;匹配失败是因为“B”不是整数值的有效开始,从stdin中提取字符时,stdin中的“B”将停止未读。x或cha都不是赋值

然后尝试:

    cha = c;
    if(x >= 1 && x <= 9) {
注:,我使用了int c;你在哪里用过茶

然后,您可以在三个主要条件下处理需要完成的所有其他事项,例如:

    while ((c = getchar()) != EOF && c != '\n') {
        if (isdigit (c)) {              /* if c is digit */
            ...
        }
        else if (isalpha(c)) {          /* if c is [A-Za-z] */
            ...
        }
        else if (c == '@') {            /* if c is end character */
            ...
        }
    }
在此基础上,您只需定义几个变量,以帮助跟踪您是否处于有效序列中,序列当前是否为合法lgl,作为序列nchr一部分读取的字符数,以及序列开头转换的整数num,以及跟踪上一个上一个字符,例如

    char buf[MAXC];
    int c, in = 0, lgl = 1, nchr = 0, num = 0, prev = 0;
这样,您就可以一次只读取一个字符,跟踪循环中操作的当前状态

    while ((c = getchar()) != EOF && c != '\n') {
        if (isdigit (c)) {              /* if c is digit */
            if (!in)                    /* if not in seq. set in = 1 */
                in = 1;
            num *= 10;                  /* build number from digits */
            num += c - '0';
        }
        else if (isalpha(c)) {          /* if c is [A-Za-z] */
            if (in) {
                if (prev >= c)          /* previous char greater or equal? */
                    lgl = 0;            /* not a legal sequence */
                prev = c;               /* hold previous char in order */
                if (nchr < MAXC - 1)    /* make sure there is room in buf */
                    buf[nchr++] = c;    /* add char to buf */
            }
        }
        else if (c == '@') {            /* if c is end character */
            /* if in and legal and at least 1 char and no. char == num */
            if (in && lgl && nchr && nchr == num && num < MAXC) {
                buf[num] = 0;           /* nul-terminate buf */
                printf ("legal: %2d - %s\n", num, buf); /* print result */
            }
            lgl = 1;    /* reset all values */
            in = nchr = num = prev = 0;
        }
    }
注意:您可以根据需要调整MAXC以更改字符数

现在,您可以练习代码,并确保它能够满足您的转换需求。您可以调整输出以满足您的需求。虽然在将逻辑整合起来时已经非常小心,但任何可能需要处理的角落案例都留给您处理

示例使用/输出

或者如果没有最后的“@”,即使是其他合法序列也将被丢弃

$ echo "ABC3DEF@11abcdefghijk@3AbC@4AZaz" | ./bin/sequences
legal:  3 - DEF
legal: 11 - abcdefghijk
注意:如果您确实希望接受最终的合法序列,即使在EOF之前没有结束'@',您只需在while循环终止后添加一个附加条件即可,例如

    /* handle final sequence before EOF */
    if (in && lgl && nchr && nchr == num && num < MAXC) {
        buf[num] = 0;   /* nul-terminate */
        printf ("legal: %2d - %s\n", num, buf); /* print result */
    }

有了这个变化,上面的最后一个示例将与其他示例的输出相匹配。

缩进样式中的模式是什么;立即对从scanf获得的值进行过度加载。并且从输出总是0-在哪里?张贴的代码没有输出。@Cacahuetferito我相信它的灵感来自毕加索的立体主义。哈啰!请发布显示问题的。这还应该显示您正在使用的include文件、输入、预期输出以及问题中的文本形式的实际输出。还要注意,问题描述令人困惑。你想要回答的具体C代码问题是什么?@Christiangibons抱歉我破坏了它;非常感谢你的解释
. 你看,我对编码是新手,多亏了你,我现在明白了什么是getchar。但是,有没有其他方法可以从输入中识别数字来替换ifisdigitc?如果我的数字输入是为1-9之间的数字指定的,并且我将识别数字的条件替换为:**ifc-'0'>=1&&c-'0',如果isdigit c&&c>'0'num=c-'0',您会做得更好;。使用isdigit的支票将告诉您它是一个数字,而c>'0'将告诉您它是1-9。
$ echo "ABC3DEF@11abcdefghijk@4AZaz@3AbC@" | ./bin/sequences
legal:  3 - DEF
legal: 11 - abcdefghijk
legal:  4 - AZaz
$ echo "ABC3DEF@11abcdefghijk@3AbC@4AZaz@" | ./bin/sequences
legal:  3 - DEF
legal: 11 - abcdefghijk
legal:  4 - AZaz
$ echo "ABC3DEF@11abcdefghijk@3AbC@4AZaz" | ./bin/sequences
legal:  3 - DEF
legal: 11 - abcdefghijk
    /* handle final sequence before EOF */
    if (in && lgl && nchr && nchr == num && num < MAXC) {
        buf[num] = 0;   /* nul-terminate */
        printf ("legal: %2d - %s\n", num, buf); /* print result */
    }