在研究socket通信时遇到了这个函数:
客户端需要发送信息到服务端,客户端就通过fgets函数从标准输入输入字符,服务端在通过fputs将字符输出到标准输出
(这里我们要经常用到stream)
1. 标准输入 standard input . 标准定义为stdin.
2. 标准输出 standard output. 标准定义为stdout
3. 标准错误 standard error. 标准定义为stderr.
fgets:
#include <stdio.h> char *fgets(char *s, int size, FILE *stream);
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte ('\0') is stored after the last character in the buffer.
大概意思就是:第一个参数是指针s,指向的是从第三个参数文件流中获取的字符串,但是字符串的个数不能大于第二个参数(为s所开辟的空间),fgets遇到文件末尾(EOF)或者一个新行的时候就会停止读取,但是值得主要的是:新行的话,会自动添加一个‘\0’
那么此刻,我们读取到的大小到底是多少,是加上上面的‘\0’吗???我们来测一下吧!!!
#include <stdio.h> #include <string.h> #include <stdlib.h> int main() { char sendbuf[10] = {0}; if(fgets(sendbuf, sizeof(sendbuf), stdin) == NULL) exit(0); printf("%lu :%lu :%s\n", sizeof(sendbuf), strlen(sendbuf), sendbuf); return 0; }
可以看到,strlen计算大小的时候是需要加上后面的‘\0’的。
那么如果,输入字符的个数达到了所指定的大小呢???
如上图:至于三者为什么都是9,实在想的不是很明白??(欢迎大家前来围观!!!)
哈哈,经过仔细思考,最后终于想明白了
对于这个函数而言,最大接受的字符个数是size - 1,最后一个size(存储空间会默认的添加一个'\0')
1,输入12345678外加一个回车键,刚好占9个字节,最后一个添加'\0',strlen计算结果为9,正常
2,输入123456789外加一个回车键,占10个字节,但是第十个必须是‘\0’,所以strlen也为9,正常
3,输入1234567890已经到达10个,将第十个替换成'\0',那么strlen自然也就是9了
那么如果输入的字符很长,超过了所指定的大小,那么会对后面的fgets造成影响吗???
#include <stdio.h> #include <string.h> #include <stdlib.h> int main() { char sendbuf[10] = {0}; if(fgets(sendbuf, sizeof(sendbuf), stdin) == NULL) exit(0); printf("%lu :%lu :%s\n", sizeof(sendbuf), strlen(sendbuf), sendbuf); if(fgets(sendbuf, sizeof(sendbuf), stdin) == NULL) exit(0); printf("%lu :%lu :%s\n", sizeof(sendbuf), strlen(sendbuf), sendbuf); return 0; }如上,如果我们将代码改成了这样呢???
可以发现,如果字符长度超过指定长度,那么接下来再次执行fgets函数,会继续从缓冲区中获取字符
fgets的返回值:
函数成功将返回指针sendbuf,错误返回NULL(函数执行出错,读到文件结尾),所以我们不能简单的通过结果妄断是否正确执行
fputs:
#include <stdio.h>
int fputs(const char *s, *stream);
fputs() writes the string s to stream, without its terminating null byte ('\0').
fputs向指定的文件中写入一个字符串,成功返回一个非负整数,出错返回EOF
缓冲区s中保存的是以'\0'结尾的字符串,fputs将该字符串写入文件stream,但并不写入结尾的'\0'。与fgets不同的是,fputs并不关心的字符串中的'\n'字符,字符串中可以有'\n'也可以没有'\n'。puts将字符串s写到标准输出(不包括结尾的'\0'),然后自动写一个' \n'到标准输出
特别提醒:
关于printf的一点问题(我们都知道,printf是可变参数)
1, size_t strlen(const char *s); 头文件:#include <string.h>
2, sizeof类型的返回值是size_t
size_t在linux,可以查到是:unsigned long(等同于unsinged long int)
假如我们这样写:
printf("%d :%lu :%s\n", sizeof(sendbuf), strlen(sendbuf), sendbuf);然后我们的编译会产生一个警告:
可以看到上面的警告内容是:argument 2 has type ‘long unsigned int’
但是,但是,我想不明白为什么是2,为什么是参数2呢???
继续更改:
printf("%lu :%d :%s\n", sizeof(sendbuf), strlen(sendbuf), sendbuf);
如我们预期,就是3,那么为什么会是3呢???
后来经过查阅
printf()函数的调用格式为:printf(格式控制,输出列表);
格式控制和输出列表都是他的参数
可以表示为:printf(参数1, 参数2, 参数3,,,,,参数n);其中参数1表示“格式控制”,其余参数表示“输出”列表
嗯嗯,对,就是这样!!!