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 1024int 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 1024int 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', '\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’'结尾的

read函数的返回值问题相关推荐

  1. wpf 窗口的返回值_如何:获取页函数的返回值

    如何:获取页函数的返回值How to: Get the Return Value of a Page Function 03/30/2017 本文内容 本示例显示如何获取页函数的返回值.This ex ...

  2. getchar()函数的返回值赋给char型,用if(ch=getchar() != EOF)测试,输入ctrl+z同样可以结束循环的分析...

    2013-07-18 21:35:58 getchar()函数的返回值赋给char型,用if(ch=getchar() != EOF)测试,输入ctrl+z同样可以结束循环的分析. char是字符型数 ...

  3. ajax回调函数的返回值,使用ajax和回调函数向函数传递/返回值

    我试图读p_info函数返回从函数getproductInfo包含ajax调用,但我得到未定义的值.我使用回调函数来实现这一点,但仍然无法正常工作.我错在哪里?使用ajax和回调函数向函数传递/返回值 ...

  4. Long类型传到前端失去精度(2):Long类型不是实体类的某一个字段,Long类型是一个函数的返回值

    Long类型传到前端失去精度(2):Long类型不是实体类的某一个字段,Long类型是一个函数的返回值 又是转换Mybatis-Plus的一天,又遇到了之前熟悉的问题:Long类型传到前端失去精度.可 ...

  5. C++知识点8——函数的返回值

    函数的返回值不能是数组或函数,但是可以是是数组和函数的指针或引用 函数返回一个值的过程和初始化完全一致,先创建一个临时变量,用返回值初始化该临时变量,然后用该临时变量去初始化另一个变量或者给另一个变量 ...

  6. 函数的初识;函数的返回值;函数的传参

    函数的初识: 避免重复代码,增强可读性. 函数是以功能为导向的. def 函数名(形参): 函数体 函数名() 实参 def 关键字 函数名(与变量命名规则一样) 1.由数字字母下划线组成 2.不能由 ...

  7. Swift2.0语言教程之函数的返回值与函数类型

    Swift2.0语言教程之函数的返回值与函数类型 Swift2.0中函数的返回值 根据是否具有返回值,函数可以分为无返回值函数和有返回值函数.以下将会对这两种函数类型进行讲解. Swift2.0中具有 ...

  8. Python基本语法_函数_返回值

    目录 目录 前言 函数的返回值 在函数中Return和Print的区别 函数中的文档 前言 函数的返回值是函数重要的组成部分.函数的根本在于实现程序的部分功能,所以很多时候我们需要将函数执行后的结果返 ...

  9. java 函数参数 返回值_java中如何用函数返回值作为post提交的参数?

    1.我想实现的功能是在java程序中导入HttpURLConnection类,然后将函数的值作为post方法要提交的参数,最后显示在显示台上. 2.要用到的函数是自己写的可以显示实时计算机cpu.内存 ...

  10. python input与返回值-Python 详解基本语法_函数_返回值

    Python 详解基本语法 概要: 函数的返回值是函数重要的组成部分.函数的根本在于实现程序的部分功能,所以很多时候我们需要将函数执行后的结果返回给程序再由程序作出进一步的操作.可以说是函数的返回值令 ...

最新文章

  1. python3.8.5怎么用-python3.8 五分钟就可以入门
  2. SourceTree 基本介绍
  3. CharNet算法详解
  4. 数据结构与算法--二叉查找树转顺序排列双向链表
  5. Dev C++,一个好玩的猜数字游戏
  6. 2014-01-01
  7. 使用kibana客户端工具操作ElasticSearch(增删改查一)
  8. Android笔记 动画之tween(补间)动画demo
  9. 福建省计算机应用基础一级考试,福建省高等院校学生计算机一级考试大纲
  10. python+appium自动化测试元素定位
  11. 安防与消防融合发展的现状与机遇分析
  12. 有趣的符号图画(颜文字)(I have a AC dream)(神兽护体)(保佑你次次Accepted)
  13. c语言写按键控制蜂鸣器,单片机按键控制蜂鸣器演奏音乐
  14. 3Q之战广东高院上演“熟人新案”
  15. 在js中为什么0.1+0.2不等于0.3
  16. HTML入门学习线路图
  17. blender学习日志
  18. 【2015NOIP模拟】【Ocd】【Mancity】【Captcha】10.31总结
  19. Python MySQL 1054 Unknown column '\xe7\x88\xb1\xe6\x83\x85' in 'where clause'错误分析
  20. 知识图谱和图神经网络

热门文章

  1. 科研课题如何进行查新?
  2. Python获取丁香园疫情数据并解析json数据
  3. 「电子乐之父」的遗作还没完成?由人工智能接手?
  4. 西安交通大学计算机图形学,西安交大计算机图形学实验报告材料.doc
  5. 「镁客·请讲」酷哇机器人刘力源:主打低速自动驾驶场景,AI环卫需求正在急速增长...
  6. pdb连接数_PDB接口说明
  7. 18.QT中的write函数
  8. 【C++】构造-析构详解
  9. JTAG、SWD调试原理简析
  10. input textarea 宽度设置100%不超出父元素