1

下午好!我对以下代码有一些疑问。

[1] for循环中的中间条件是什么意思?; *p;; *sval; - 到达输入字符串的结尾?如果是,如何确定?

[2] 我不明白那个复杂的 for 循环。

假设如果条件不满足*p == %,那么我们立即进入 switch。现在让我们考虑相反的情况,尽管 ,我们输入每个其他字符%,如果满足,那么我们使用 continue 并在switch之后继续。那这两种情况有什么区别呢?我一定是大错特错了,但我现在2个多小时都找不到我的错误……

#include <stdarg.h>
/* minprintf: minimal printf with variable argument list */
void minprintf(char *fmt, ...)
{
    va_list ap; /* points to each unnamed arg in turn */
    char *p, *sval;
    int ival;
    double dval;

    va_start(ap, fmt); /* make ap point to 1st unnamed arg */

    for (p = fmt; *p; p++) {         /* [1] */
        if (*p != '%') {
            putchar(*p);
            continue;                /* [2] */
        }
        switch (*++p) {
        case 'd':
            ival = va_arg(ap, int);
            printf("%d", ival);
            break;
        case 'f':
            dval = va_arg(ap, double);
            printf("%f", dval);
            break;
        case 's':
            for (sval = va_arg(ap, char *); *sval; sval++)
                putchar(*sval);
            break;
        default:
            putchar(*p);
            break;
        }
    }
    va_end(ap); /* clean up when done */
}

非常感谢您的帮助!

4

3 回答 3

1

当我们 时continue,我们只是打印字符,完全跳过开关。循环通过格式行查找 (1) 终止零,或 (2) 百分号。

当到达终止零时,循环结束:

for (p = fmt; *p; p++)
//            ^^^ Here is the condition: *p != 0 is implied

当达到百分号时,将以下符号作为格式字符,并根据它解释下一个可变参数。


这个程序有一个错误 - 当百分号是格式字符串的最后一个字符时,它会在格式字符串的末尾产生读取(未定义的行为)。试试这个:

minprintf("%\0bug!bug!bug!");

\0跳过模拟的行尾标记,并生成bug!bug!bug!输出。其原因是语句p头中的无条件 pre_increment of switch。要解决此问题,请将以下案例添加到switch

 case '\0':
    p--; // reverse the ++p from the header of the switch
    break;
于 2012-08-17T13:02:25.910 回答
1

*p *sval - 指向字符串中字符的解引用指针。在 C 中,字符串以“\0”符号结束。因此,如果我们从 p, sval 点为零的地方获得的值显然已经到达字符串的末尾

2 in loop continue 用于跳过它后面的所有语句并返回到循环头执行 (;;statement)

于 2012-08-17T13:04:27.820 回答
1
  • [1] 是继续循环,直到它没有得到字符串的空终止字符'\0'
  • [2] 如果不是,则打印字符'%'。如果'%'字符串中的下一个字符标识如何打印va_arg列表中的下一个字符。
于 2012-08-17T13:06:09.737 回答