【问题标题】:Implementation of printf() functionprintf()函数的实现
【发布时间】:2019-01-24 17:33:43
【问题描述】:

我正在制作一个爱好者内核,我正在尝试实现一个printf() 函数。

这是我的实现:

void kprint(uint8_t *format, ...) {
  va_list ap;
  va_start(ap, format);

  uint8_t *ptr;

  for (ptr = format; *ptr != '\0'; ptr++) {
    if (*ptr == '%') {
      ptr++;
      switch (*ptr) {
        case 's':
          puts(va_arg(ap, uint8_t *), 0x0F, xPos, yPos);
          break;
      }
    } else {
      puts(ptr, 0x0F, xPos, yPos);
      ptr++;
    }
  }

  va_end(ap);
}

当我想打印“Hello World!”时使用这个函数它返回给我:

"Hello %sllo %so %sWorld"

这里是函数调用:

kprint("Hello %s", "World");

【问题讨论】:

  • 似乎您在没有遇到% 时将ptr 增加了两次。另外,不要忘记将%% 视为%
  • 您是否尝试将其作为简单用户模式程序的一部分进行调试?
  • puts 打印字符串的剩余部分。你需要putc(*ptr)
  • @Jean-FrançoisFabre 我删除了指针递增并在 else 块中用 putc() 替换了 puts(),但现在它只打印给定的参数。
  • puts(va_arg(ap, uint8_t *), 0x0F, xPos, yPos); 这行不通。它使xposypos 的值错误(即未改变)。

标签: c operating-system osdev


【解决方案1】:

主要问题是您使用puts 打印字符串的其余部分,而不是当前字符。

 } else {
   puts(ptr, 0x0F, xPos, yPos);
   ptr++;
}

ptr 已经在循环中完成时,你也在增加它。对使用格式参数很有用,但在这种情况下不是。

在标准系统上工作的工作实现(不使用奇怪的 puts 原型)(在 windows gcc 上测试):

#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>

void zprintf(uint8_t *format, ...)
  {
      va_list ap;
      va_start(ap, format);

      uint8_t *ptr;

      for (ptr = format; *ptr != '\0'; ptr++) {
          if (*ptr == '%') {
              ptr++;
              switch (*ptr) {
                  case 's':
                      fputs(va_arg(ap, uint8_t *),stdout);
                      break;
                 case '%':
                      putchar('%');
                      break;
              }
             } else {
               putchar(*ptr);

            }
           }

           va_end(ap);
}

int main(){

    zprintf("%% Hello %s\n","World");    
    return 0;
}

打印:

% Hello World

(作为奖励,此实现处理转义的 % 字符)

仅使用您对 puts 的特殊实现,您可以更改

 } else {
   puts(ptr, 0x0F, xPos, yPos);
   ptr++;
}

去上班:

 } else {
   char c[2];
   c[0] = *ptr; c[1] = '\0';
   puts(c, 0x0F, xPos, yPos);
 }

蹩脚但会工作:)

【讨论】:

  • 是的,它奏效了。但是当我在 Qemu 中运行它时它不起作用。我知道我的原型很奇怪,因为它的参数还指定了前景色和背景色以及屏幕上应该显示的位置。
  • 在您的平台上检查 putc 原型,或者创建一个只有 1 个字符的 2 大小字符 * (eeek)
  • 现在可以使用了。我还更改了我的 puts 原型,所以现在它只需要 char。在编辑之前,我仍然会尝试按照您的方式进行操作。
  • puts 附加'\n'。建议fputs(va_arg(ap, uint8_t *), stdout);
  • @chux 我自己实现了 puts 函数
【解决方案2】:
void kprint(char *format, ...) 
{
    va_list ap;
    va_start(ap, format);

    char *ptr = format;

  while(*ptr)
  {
    if (*ptr == '%') 
    {
      ptr++;
      switch (*ptr++) 
      {
        case 's':
          printf("%s", va_arg(ap, char *));
          break;
      }
    } 
    else 
    {
      putchar(*ptr++);
    }
  }

  va_end(ap);
}

int main()
{
    kprint("Hello %s World%s", "AAAAA", " BBBBBB");

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-14
    • 1970-01-01
    • 1970-01-01
    • 2018-03-12
    相关资源
    最近更新 更多