read函数的返回值问题

read函数的返回值问题Read函数读取字符串返回值的问题1.前言在学习socket编程的途中,通过客户端给服务端发送字符串,然后服务端通过read或者recv来读取数据,然后返回读取的字节数.我在想read返回的读取字节数有没有包含’\0’或者’\n’呢,于是通过一些简单的小例子,来看看实际情况到底如何.2.read函数我们来看一下read函数的原型:ssize_tread(intfd,void…

大家好,又见面了,我是你们的朋友全栈君。

Read函数读取字符串返回值的问题

1. 前言

在学习socket编程的途中, 通过客户端给服务端发送字符串,然后服务端通过read或者recv来读取数据,然后返回读取的字节数. 我在想read返回的读取字节数有没有包含'\0'或者'\n'呢,于是通过一些简单的小例子,来看看实际情况到底如何.

2. read函数

我们来看一下read函数的原型:

ssize_t read(int fd, void *buf, size_t count);

然后看看函数的描述:

read() attempts to read up to count bytes from file descriptor fd into the buffer starting at buf.

然后是函数的返回描述:

On success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by this number. It is not an error if this number is smaller than the number of bytes requested; this may happen for example because fewer bytes are actually available right now (maybe because we were close to end-of-file, or because we are reading from a pipe, or from a terminal), or because read() was interrupted by a signal. See also NOTES.

On error, -1 is returned, and errno is set appropriately. In this case, it is left unspecified whether the file position (if any) changes.

大概的意思就是read函数从文件描述符fd中读取字节到count大小的buf中,如果成功读取的话,返回读到的字节数大小,否则返回-1.

接下来我们通过一下小函数来实验一下.

3. read函数从终端读入字符串的返回的大小

看下面的函数:

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

#define BUFSIZE 1024

int main(int argc, char *argv[]){ 
   

    char buf[BUFSIZE] = { 
   0};

    int len = read(STDIN_FILENO, buf, BUFSIZE);

    printf("Read buf: %s", buf);
    printf("The length of buf read: %d\n", len);
    printf("The strlen of buf: %ld\n", strlen(buf));

    return 0;
}

现在我们编译运行这个程序,然后输入:

hello

我们知道hello的字节数为5,然后在终端里我们要敲回车进行确认,也就是换行符'\n',然后我们看看输出:

Read buf: hello
The length of buf read: 6
The strlen of buf: 6

注意在代码中

printf("Read buf: %s", buf);

这一句我是没有加换行符的,但是输出的时候却有了换行的作用,说明buf把换行符'\n'给读取进来了,下面的长度也说明了问题,

  1. 读取到的长度为6,然而hello只有5个字节,说明把换行符读了进来,结束符没有读取进来

  2. strlen测量的buf长度也是6,因为strlen不测量结束符'\0',因此也说明read读取到的字节数不包含结束符,而是包含换行符.

    ps. 最后会有简略的strlensizeof函数的比较.

4. read函数从文件读入字符串的返回的大小

因为终端只能带有换行符,我们试一下从文件中读取不带换行符的试试.创建一个文件名为read_test,里面的内容为:

hello

注意是不带换行的!

然后代码改为如下:

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

#define BUFSIZE 1024

int main(int argc, char *argv[]){ 
   

    char buf[BUFSIZE] = { 
   0};

    int r_fd = open(argv[1], O_RDONLY);

    int len = read(r_fd, buf, BUFSIZE);

    printf("Read buf: %s", buf);
    printf("The length of buf read: %d\n", len);
    printf("The strlen of buf: %ld\n", strlen(buf));

    return 0;
}

编译运行, 输入的命令为:

./read_the_end_of_file read_test

最后输出为:

Read buf: helloThe length of buf read: 5
The strlen of buf: 5

很显而易见,buf只读取了hello,没有了换行符,所以导致第一行和下一行连在一起了.

read函数返回的字节大小和strlen返回的字符串长度都是5,验证了这一点.

5. 总结

通过上面两个简单的测试,最后总结如下:

  1. 在终端中,因为无可避免要回车进行确定,因此read函数会读入换行符,所以read函数从终端读取到的字符串字节数会比输入的大1个字节,多出的一个字节是换行符的大小,不是结束符'\0'的大小. read函数读取不包含'\0', strlen读取的也不包含'\0'
  2. read在文件中读取字符串可以不包含换行符.

6. 番外: strlen和sizeof的区别

先说结论:

  1. strlen 是函数,sizeof 是运算符

  2. strlen 测量的是字符的实际长度,以’\0’ 结束。而sizeof 测量的是字符的分配大小.

    也就是说: strlen是通过找'\0'来确定字符的实际长度的.这一点非常关键.

下面来看看简单的例子:

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

int main(){ 
   

    char str[20] = "hello";
    printf("strlen of str: %ld\n", strlen(str));
    printf("sizeof str: %ld\n", sizeof(str));

    return 0;
}

输出为:

strlen of str: 5
sizeof str: 20

有一点要说明,在char str[20] = "hello";这条语句中, 字符数组会自动在hello后面加上'\0'这个结束符,所以strlen才能找到'\0',得到str的实际字符长度为5.

那如果字符数组不一次赋值的话,就有区别了,看下面程序:

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

int main(){ 
   

    char str1[] = "hello";
    char str2[] = { 
   'h','e','l','l','o', '
#include <stdio.h>
#include <string.h>
int main(){ 

char str1[] = "hello";
char str2[] = { 
'h','e','l','l','o', '\0'};
char str3[] = { 
'h', 'e','l','l', 'o'};
printf("str1:%s\n", str1);
printf("str2:%s\n", str2);
printf("str3:%s\n", str3);
printf("strlen of str1 = %ld\n", strlen(str1));
printf("strlen of str1 = %ld\n", strlen(str2));
printf("strlen of str1 = %ld\n", strlen(str3));
return 0;
}
'
}; char str3[] = { 'h', 'e','l','l', 'o'}; printf("str1:%s\n", str1); printf("str2:%s\n", str2); printf("str3:%s\n", str3); printf("strlen of str1 = %ld\n", strlen(str1)); printf("strlen of str1 = %ld\n", strlen(str2)); printf("strlen of str1 = %ld\n", strlen(str3)); return 0; }

编译运行:

str1:hello
str2:hello
str3:hellohello
strlen of str1 = 5
strlen of str1 = 5
strlen of str1 = 10

我们知道字符串是以 ‘\0’ 为结束标志的,所以char str1[ ] = “hello” 等效于char str2[ ] = {‘h’ , ‘e’ , ‘l’ , ‘l’ , ‘o’ , ‘\0’} 。strlen函数求的是字符串的实际长度,它求得方法是从开始到遇到第一个’\0’,如果你只定义没有给它赋初值,这个结果是不定的,它会从首地址一直找下去,直到遇到’\0’停止。而如果不在字符数组初始化的时候加上\0,那么strlen 得到的值就不是正确的数值,打印出来的结果也不是想要的结果。因此我们要避免这种情况,在初始化的时候要记得加上 \0,或者一次性赋初值。
另外:

  • strlen的结果要在运行的时候才能计算出来,是用来计算字符串的长度,不是类型占内存的大小。而大部分编译程序在编译的时候就把sizeof计算过了是类型或是变量的长度。
  • sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以’’\0’’结尾的
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/152116.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • STM32中断优先级NVIC

    STM32中断优先级NVIC参考正点原子视频为什么STM32需要中断就拿你去饭馆吃饭为例。使用中断就是饭做好了,服务员会为你端上来,然后你开始吃饭。端上来之前你爱干啥就干啥。不使用中断,你需要一次一次去问服务员饭做好了没有,这期间你没办法去做其他事情。CM3(CortexM3)内核支持256个中断,其中包括16个内核中断和240个外部中断,并且具有256级的可编程中断设置STM32并没有使用CM3内核的全部东西,而是只用了它的一部分STM32有84个中断,包括16个内核中断和68个可屏蔽中断,具有16级可编程的中断优

  • python3.9多线程_python创建多线程

    python3.9多线程_python创建多线程什么是线程?线程也叫轻量级进程,是操作系统能够进行运算调度的最小单位,它被包涵在进程之中,是进程中的实际运作单位。线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其

  • matlab输出语句fprintf例子_matlab中compose函数

    matlab输出语句fprintf例子_matlab中compose函数golang需要什么基础?_后端开发golang需要的基础是:首先初学Go语言要弄懂基础语法和概念;然后掌握文件操作、网络编程、锁、协程、对象序列化和反序列化,以及各种数据格式的封装等;最后接触数据库等,就可以模块化开发。matlab中fprintf函数的用法详解:fprintf函数可以将数据按指定格式写入到文本文件中。其调用格式为:数据的格式化输出:fprintf(fid,format,v…

  • wpf wrapPanel居中并从左到右排列

    wpf wrapPanel居中并从左到右排列publicclassAlignableWrapPanel:Panel{///<summary>///注册新的属性HorizontalContentAlignment///</summary>publicHorizontalAlignmentHorizontalContentAlignment{get{return(Horizont.

  • Java 中位数_中位数众数平均数三者关系

    Java 中位数_中位数众数平均数三者关系列举一些中位数和众数的常见问题和解法1.众数一个长度为$N$的列表,出现次数大于$\left\lfloorN/2\right\rfloor$的数为这个列表的众数。1.1摩尔投票算法摩尔投票算法(Boyer-Mooremajorityvotealgorithm)的思路类似一个大乱斗,遇到不相同的数就抵消掉。维护两个变量:major和count,major是众数的可能值,count是…

  • 微信小程序带参数跳转页面(小程序跳转第三方网页)

    //wxml&lt;textwx:for="{{titles}}"wx:key="{{index}}"bindtap=’changeClassify’data-id="{{index}}"&gt;{{item.name}}&lt;/text&gt;//jsfunctionchangeClassify(e){//letid=e.currentTarget.da…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号