fputs和printf问题

时间:2011-07-10 12:02:36

标签: c

我得到了以下代码:

char* writeSpace(int i)
{
 fputs("                              " + (30-i), stdout);
}

printf("#%i key: %s%svalue: %s%s value2: %s", id, key, writeSpace(10), value, writeSpace(8), value2);

我的输出应该类似于:

#1 key: foo          value: bar        value2: foobar

但事实并非如此。它看起来像:

                      #1 key: foo(null)value: bar(null)value2: foobar(null)

我的代码出了什么问题?

5 个答案:

答案 0 :(得分:4)

您已宣布writeSpace()返回char*,但您尚未从中返回任何内容。

答案 1 :(得分:4)

嗯,你是fput所有这些空间到控制台,所以你先得到它们。

然后你输出其他所有东西,所以你接下来就得到了。

也许您的意思是writeSpace 返回一个C风格的字符串,而不是将其打印到控制台。

但请务必为此分配空间!由于内存缓冲区的所有权有点隐蔽,因此最好在函数外部分配

void writeSpace(char* buf, int i) {
   fputs("                              " + (30-i), buf);
}

char spaceBuf1[30];
writeSpace(spaceBuf1, 10);

char spaceBuf2[30];
writeSpace(spaceBuf2, 8);

printf("#%i key: %s%svalue: %s%s value2: %s",
   id, key, spaceBuf1, value, spaceBuf2, value2);

并考虑使用实际 C ++功能,如iostreams和std::string。这会容易得多:

std::cout << "#" << id << " "
          << " key: " << std::setw(30) << key
          << " value: " << std::setw(30) << value
          << " value2: " << value2;

我建议these resources学习惯用语C ++。

答案 2 :(得分:0)

你的writeSpace函数没有返回一个新字符串(即使你已经这样声明了)但是直接写入终端。由于您在printf调用中将其称为参数,因此首先调用writeSpace,打印其内容,然后printf打印其内容。你应该这样做:

char* writeSpace(int i)
{
    char *ret = NULL;
    asprintf(ret, "                              " + (30-i));
    return ret;
}

当然,这需要你free内存(否则你会有内存泄漏)。你可以这样做:

char *spaces = writeSpace(10);
printf("%s%i", spaces, 42);
free(spaces);

另一种方法是使用函数本身在下次调用时清理的静态变量:

char* writeSpace(int i)
{
    static char *ret = NULL;
    if (ret != NULL) free(ret);
    asprintf(ret, "                              " + (30-i));
    return ret;
}

但是这样做的缺点是你只能在writeSpace个参数中使用printf的一个调用,因为第二个调用将清除前一个调用的内存。仍然可能是你想要的。

BTW,+ (30-i)部分是邪恶的。你可能想要的是这个:

asprintf(ret, "%*s", i, ""); // Prints i spaces

答案 3 :(得分:0)

如果你想格式化变量ws'并且你必须使用普通的C你可以使用这样的格式字符串(%* c,其中*是ws的数量,c代表要设置的字符(在这种情况下为'')当然)):

sprintf(buffer, "%*cafterspace", 30, ' '); // Will print 30 ws and then "afterspace".
sprintf(buffer, "%*cafterspace", 15, ' '); // Will print 15 ws and then "afterspace".

但是你仍然要像Tomalak解释的那样准备一个缓冲区!

答案 4 :(得分:0)

提供的其他答案有正确的答案。但是,我想尝试添加一些您所看到的症状的解释,以帮助您将来避免它们。

执行printf语句时

 printf("#%i key: %s%svalue: %s%s value2: %s", id, key, writeSpace(10), value, writeSpace(8), value2);

两个writeSpace()方法调用在printf本身执行任何操作之前执行。原因是这些方法的返回值用作printf方法的参数。所以上面一行代码的执行顺序是:

  • writeSpace(10),它将一些空格打印到标准输出并返回空指针。
  • writeSpace(8),它向标准输出打印更多的空格,并返回空指针。
  • 最后使用以下参数调用printf:printf(“#%i key:%s%svalue:%s%s value2:%s”,id,key, null ,value, null ,value2);

这就是为什么你看到开头打印的空格,以及你看到输出中出现“(null)”的原因。

因此,这里学到的教训是,在程序执行期间,方法的参数在调用方法本身之前得到解决。