1

使用Arduino 以太网服务器库有什么区别:

server.write(data);, server.print(data);, 和 server.println(data);

我知道printIn添加了一个新行,而print没有。我找不到任何示例server.write();

4

1 回答 1

4

(长答案,跳到TL;如果笨拙,请在底部 DR)

从哪里来print()_ write()_

要找出答案,我们可以查看源代码。 是在(仅选定的行)中定义Server的类的实例EthernetServerarduino/libraries/Ethernet/EthernetServer.h

#include "Server.h"

class EthernetClient;

class EthernetServer : 
public Server {
private:
public:
  virtual size_t write(uint8_t);
  virtual size_t write(const uint8_t *buf, size_t size);
  using Print::write;
};

好的,所以它是一个Server. Server在 中定义/usr/share/arduino/hardware/arduino/cores/arduino/Server.h,并且几乎没有:

class Server : public Print {
public:
  virtual void begin() =0;
};

这意味着 server 是一个子类,Print因此我们可以寻找它们之间的write()差异print()

print()write()参数

我们看到这个类(即Print)定义了许多重载print()方法:

size_t print(const __FlashStringHelper *);
size_t print(const String &);
size_t print(const char[]);
size_t print(char);
size_t print(unsigned char, int = DEC);
size_t print(int, int = DEC);
size_t print(unsigned int, int = DEC);
size_t print(long, int = DEC);
size_t print(unsigned long, int = DEC);
size_t print(double, int = 2);
size_t print(const Printable&);

和三个重载write()方法:

virtual size_t write(uint8_t) = 0;
size_t write(const char *str) { return write((const uint8_t *)str, strlen(str)); }
virtual size_t write(const uint8_t *buffer, size_t size);

如您所见,C-stringwrite使用块write(第三种方法),而在默认实现中,块写入使用字节写入(第一种方法),这是纯虚方法:virtual size_t write(uint8_t) = 0;. 它必须在派生自 的每个类中被覆盖Print。此外,该块write()也可以被覆盖,以便更有效地写入多字节数据。

所以,参数方面:

  • write(): 在字节 ( uint8_t)、字节缓冲区和 char 数组指针上(= 常规 C 字符串)
  • print(): Arduino Strings、ints 和longs(在任何基础上)、floats 和任何从Printable、 除了chars和 C 字符串派生的类。

write()正如你所看到的,形式上,参数和take之间几乎没有重叠print()。比如只write()uint8_t,但只能print()取一个char。唯一重叠的区域是 C 风格的字符串:有print(const char[]);write(const char *str);。然而,即使在像函数这样char的情况下,也print()只是简单地调用write(uint8_t)

size_t Print::print(char c)
{
  return write(c);
}

对于print(char[])

write()在`以太网服务器

该类EthernetServer引入了块写入方法

size_t EthernetServer::write(const uint8_t *buffer, size_t size) 

并在EthernetServer简单write(uint8_t)的块中写入:

size_t EthernetServer::write(uint8_t b) 
{
  return write(&b, 1);
}

由于所有print()调用和非uint8_t write()调用都使用write(uint8_t)or write(uint8_t*, size_t),因此在EthernetServer类中每个print/write调用都是使用块写入进行的。

性能和在和之间进行print()选择write()

thunkingprint()函数(例如print(char c))很可能会被 gcc 编译器内联,但如果您担心这一点,您可以调用write()而不是print().

可能想要调用write()而不是print()保存几个时钟周期的一种情况是您持有byte/uint8_t并且您需要打印它。使用print()您的数据需要转换为 4 字节值 ( int),然后使用更多代码打印。在这种情况下write()会快一点。

另一方面,代码一致性可能也很有价值。从这个角度来看,拨打所有电话可能是有意义的print()

然而,大多数时候,您的类型将决定调用该print()函数:write 只能接受三种类型的输入。


TL; DR:那么你的问题的答案是,print()除了write()

  • write()方法(字节或块)是在任何情况下执行在某处发送字符的实际工作的方法。
  • write()可以将字节 ( uint8_t)、字节缓冲区和 char 数组指针(= 常规 C 字符串)作为参数,而print()将 Arduino Strings、ints 和longs(以任何基数)、 s 以及从、 除了和 C 字符串float派生的任何类. 所以我们可以说它比 低级别,因为它只接受低级别的类型。Printablecharswrite()print()
  • 大多数情况下,您的输出类型将决定使用哪一种。为了使最快的代码write()用于打印byte/uint8_t类型,但print在任​​何地方都使您的代码看起来稍微好一点恕我直言(主要是因为它不会引发print()vswrite()问题)。
于 2013-04-27T05:06:25.453 回答