fputs和printf问题

我得到了以下代码:

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) 

我的代码出了什么问题?

好吧,你将所有这些空间输入到控制台,所以你先得到它们。

然后你输出其他所有东西,所以接下来就是这样。

也许你的意思是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 ++function,如iostreams和std::string 。 这会容易得多:

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

我推荐这些资源来学习惯用的C ++。

你已经声明writeSpace()返回一个char* ,但是你没有从中返回任何东西。

你的writeSpace函数没有返回一个新字符串(即使你已经这样声明了)但是直接写入终端。 因为你在printf调用writeSpace它称为参数, writeSpace首先调用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; } 

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

顺便说一句, + (30-i)部分是邪恶的。 您可能想要的是这样:

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

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

当你的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)”的原因。

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

如果你想格式化变量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解释的那样!