【问题标题】:Need a function like read() that reads integer data into buffer and obtains same buffer value as read()需要一个像 read() 这样的函数,它将整数数据读入缓冲区并获得与 read() 相同的缓冲区值
【发布时间】:2019-11-06 14:29:46
【问题描述】:

当我标准输入相同的整数时,如何将整数转换为与使用 read(0,buff,nbytes) 获得的缓冲区相同的值/编码字符?我正在尝试编写类似 read() 的东西,但使用整数数据代替读入缓冲区的文件描述符参数。

like_read(int data,void *buff,size_t nbytes);

它应该与 read() 类似,因为它应该读入缓冲区的值与 read(0,buff,nbytes) 从标准输入到其缓冲区的值相同。当我直接提供整数地址作为缓冲区而不首先使用 read(0,buff,nbytes) 时,例如

int Integer=25
int nbytes=2;
int rlen,wlen,wlen1;
int fd = open("ttyusb.txt", O_RDWR | O_CREAT,0777);
wlen = write(fd, &Integer, nbytes);
wlen1 = write(1, &Integer, nbytes);//for stdout
close(fd);

预期输出

25

实际输出/文件内容是一些编码字符

,它没有给我想要的结果,因为首先使用 read() 从 stdin 将整数读入缓冲区,然后使用 write() 将该缓冲区写入文件,例如:

int Integer;
int nbytes=2;
int rlen,wlen;
int fd = open("ttyusb.txt", O_RDWR | O_CREAT,0777);
rlen = read(0, &Integer, nbytes);
wlen = write(fd, &Integer, nbytes);
wlen1 = write(1, &Integer, nbytes);//for stdout
close(fd);

标准输入

25

预期输出

25

实际输出/文件内容

25

当我在读取(0,缓冲区,nbytes)之后打印缓冲区值时,它会给出一些编码值:

int Integer, nbytes=2;
int fd = open("ttyusb.txt", O_RDWR | O_CREAT,0777);
rlen = read(0, &Integer, nbytes);
wlen = write(fd, &Integer, nbytes);
wlen1 = write(1, &Integer, nbytes);
printf("\nInteger buffer value %d\n",Integer);
close(fd);

stdin 0 打印“整数缓冲区值 2608”,stdin 1 打印“整数缓冲区值 2609”,stdin 2 打印“整数缓冲区值 2610”,.....stdin 9 打印“整数缓冲区值 2617”...

read() 使用什么编码来转换整数值,我如何在没有 read() 的情况下进行转换?

【问题讨论】:

  • @user3121023 那么两位整数呢?比如 10 给出 12337、11 给出 12593、12 给出 12849...?
  • 字符 '1'、'0' 的 ASCII 值分别为 0x31 和 0x30。如果您将其读取为 little-endian、2 字节整数,则该值将为 0x3031,即 12337。顺便说一下,int 的大小通常为 4 字节,如果变量在堆栈上并且没有已初始化,int 的其他 2 个字节将是不确定的。
  • @IanAbbott 它不会像单个数字 1 0x0A31 ('1',LF) 那样捕获两位数的 LF 吗?为什么 10 不是 0x0A3031 ('1','0',LF)?
  • @Optic_Ray 如果不是 0x0A3031,因为您只读取 2 个字节。

标签: c linux encoding file-io format


【解决方案1】:

我不太确定您想要实现什么,但我的解释是您正在尝试将 int 的字节复制到缓冲区中。可以这样实现:

#include <string.h>

void like_read(int data, void *buff, size_t nbytes)
{
    size_t n;

    /* Limit number of bytes to copy from data variable. */
    n = sizeof(data);
    if (n < nbytes)
        n = nbytes;
    /* Copy bytes from data variable to the buffer. */
    memcpy(buff, &data, n);
    /* If destination buffer is larger than data variable, ... */
    if (n < nbytes) {
        /* ... set the remaining bytes in the destination to all zero. */
        memset((char *)buff + n, 0, nbytes - n);
    }
}

read() 使用什么编码来转换整数值,我如何在没有 read() 的情况下进行转换?

read() 只是从文件描述符中读取原始数据字节,没有任何转换,至少在 Unix 和 Linux 等 POSIX 类型系统上是这样。其他一些操作系统(例如 Microsoft Windows)允许使用特殊标志打开文件,这些标志对原始数据字节进行一些转换,主要用于处理具有不同编码的文本文件。

上述like_read 函数中的memcpy() 调用将原始数据字节从一个内存位置复制到另一个内存位置,而不进行任何转换。


编辑

我仍然不确定您 (OP) 想要实现什么,但根据您下面的 cmets,也许您正在使用一个函数,该函数使用换行符将整数值作为十进制 ASCII 字符“打印”到缓冲区,但是截断到指定的字节数。 snprintf() 几乎可以做到这一点,但该函数总是将一个终止的空字节写入缓冲区(如果缓冲区大小至少为 1),所以这不是我认为你想要的。因此,snprintf() 可用于将整数值打印到足够大小的中间缓冲区,然后memcpy 将结果打印到指定的缓冲区。这是一个实现:

#include <string.h>
#include <stdio.h>

void like_read(int data, void *buff, size_t nbytes)
{
    char tempbuf[24]; /* ought to be large enough... */
    size_t n;

    /* Print data value to temporary buffer. */
    n = snprintf(tempbuf, sizeof(tempbuf), "%d\n", data);
    /* n is number of bytes that would be printed to tempbuf if room. */
    /* Limit number of bytes to copy to size of temporary buffer. */
    if (n > sizeof(tempbuf))
        n = sizeof(tempbuf);
    /* Limit number of bytes to copy to nbytes. */
    if (n > nbytes)
        n = nbytes;
    /* Copy bytes from tempbuf to the buffer. */
    memcpy(buff, tempbuf, n);
    /* If destination buffer is larger than n, ... */
    if (n < nbytes) {
        /* ... set the remaining bytes in the destination to all zero. */
        memset((char *)buff + n, 0, nbytes - n);
    }
}

【讨论】:

  • 使用数据值 10 调用函数后,buff 不是 12337,就像我调用 read(0, &buff, 2) 和 stdin 10 时读取的缓冲区一样。
  • @Optic_Ray 嗯,这取决于sizeof(int)datanbytes 的值,以及您的系统是以小端格式还是大端格式存储整数。它基本上是从data 变量的地址到缓冲区执行memcpy。在sizeof(int) 为4 的小端系统(如PC)上,将data 设置为10 并将nbytes 设置为2 会将buff 指向的前两个字节设置为10, 0。更改@ 987654339@ 到 12337 会将buff 的前两个字节设置为 49、48,它们是字符 '1' 和 '0' 的 ASCII 码。我不太确定你想要达到什么目的。
  • @Optic_Ray 在我编辑的答案中查看该函数的第二个版本。也许这更像您正在寻找的东西?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-12
  • 2017-10-05
  • 1970-01-01
  • 2012-01-28
  • 1970-01-01
  • 2013-06-15
相关资源
最近更新 更多