学习fgets()函数时发现了一个问题,先贴代码

#include<stdio.h>
#include<string.h>
#include<ctype.h>
void convert(char buffer[]) //将字符转换大写
{
int i;
for(i=0;buffer[i]!='\0';i++)
{
buffer[i]=toupper(buffer[i]);
}
}
int findstring() /* Finding occurrence of one string in another */
{
int position=0;
char *find=NULL;
char buffer[20]; //要查找的字符串
char source[20]; //buffer字符串要在此字符串查找
printf("Please input a string you want to find(Less than 20): ");
if(fgets(buffer,sizeof(buffer),stdin)==NULL) //调用fets()输入
{
printf("Error reading input.");
return 1;
}
printf("Please input a string sought(Less than 20): ");
if(fgets(source,sizeof(source),stdin)==NULL)
{
printf("Error reading input.");
return 1;
}
//buffer[strlen(buffer)-1]='\0'; //关键的地方
//source[strlen(source)-1]='\0';
convert(buffer); //将两个字符串都转换为大写
convert(source);
if((find=strstr(source,buffer))!=NULL)
{
position=find-source+1; //计算匹配的字符串第一个字符出现的字符
printf("\nThe fist char %c match: %d\n",*find,position);
}
else
{
printf("\nCan't find the string.\n");
return 1;
}
return 0;
}
int main()
{
findstring();
return 0;
}

运行结果

输入匹配字符串" I love C"

输入要查找的字符串"I love C and C++"

发现程序不匹配,然后将这两行代码注释去掉

buffer[strlen(buffer)-1]='\0';
source[strlen(source)-1]='\0';

再运行程序看看

这次匹配成功,第一个字符匹配,关键地方在那两行.

再看个实验,先贴代码

#include<stdio.h>
#include<string.h>
int main()
{
char buffer[20];
printf("请输入小于长度20的字符串: ");
fgets(buffer,sizeof(buffer),stdin);
printf("输入的字符长度为: %d \n",strlen(buffer));
return 0;
}

 

明明输入长度为5的字符串,但是用strlen()计算时长度为6,这是什么原因呢?

先看fgets()使用说明,摘录于MSDN(01年版的)

 

声明:char *fgets( char *string, int n, FILE *stream );

Return Value

Each of these functions returns string. NULL is returned to indicate an error or an end-of-file condition. Use feof or ferror to determine whether an error occurred.

Remarks

The fgets function reads a string from the input stream argument and stores it in string. fgets reads characters from the current stream position to and including the first newline character, to the end of the stream, or until the number of characters read is equal to n – 1, whichever comes first. The result stored in string is appended with a null character. The newline character, if read, is included in the string.

fgets()从流中获取一定字节的字符储存在字符串string中,关于流我这里是stdin,也就是标准输入流,就是从键盘获取数据,文档说明fgets()从键盘获取n-1字节的字符,参数指定字节为n,但是只能输入n-1字节,原因是最后一个字节要给字符串附加一个'\0'字符,你可以测试一下 ,代码还是刚才那个

 

#include<stdio.h>
#include<string.h>
int main()
{
char buffer[20];
printf("请输入小于长度20的字符串: ");
fgets(buffer,sizeof(buffer),stdin);
printf("输入的字符长度为: %d \n",strlen(buffer));
return 0;
}

输入超过20个字符的字符串,看看结果

这是在你可以输入满n-1个字符的情况下,如果你没能输入满n-1个字符呢?

这个就出了点变化,则fgets()从流中获取字符到换行符(或eof)为止,例如输入:  abcd回车 则string中字符就有五个 a,b,c,d,'\n' 然后才是'\0' ,这就是前面明明输入5个字符,但是strlen()却计算出6个字符的原因。

回到刚开始那个例子,如果按照刚才所说,fgets()在获取少于n-1个字符的情况下

字符数组buffer储存内容 "I love C\n\0"

字符数组source储存内容 "I love C and C++\n\0"

用匹配函数strstr()自然匹配不成功啦,因为buffer多了一个换行符'\n',因此为了匹配成功,应该将buffer中换行符去掉,也就是说的那两行代码

buffer[strlen(buffer)-1]='\0';
source[strlen(source)-1]='\0';

C学习-fgets()篇1的更多相关文章

  1. [Django]模型学习记录篇--基础

    模型学习记录篇,仅仅自己学习时做的记录!!! 实现模型变更的三个步骤: 修改你的模型(在models.py文件中). 运行python manage.py makemigrations ,为这些修改创 ...

  2. JDK源码学习--String篇(二) 关于String采用final修饰的思考

    JDK源码学习String篇中,有一处错误,String类用final[不能被改变的]修饰,而我却写成静态的,感谢CTO-淼淼的指正. 风一样的码农提出的String为何采用final的设计,阅读JD ...

  3. LINQ to XML LINQ学习第一篇

    LINQ to XML LINQ学习第一篇 1.LINQ to XML类 以下的代码演示了如何使用LINQ to XML来快速创建一个xml: public static void CreateDoc ...

  4. Entity Framework 学习中级篇1—EF支持复杂类型的实现

    本节,将介绍如何手动构造复杂类型(ComplexType)以及复杂类型的简单操作. 通常,复杂类型是指那些由几个简单的类型组合而成的类型.比如:一张Customer表,其中有FristName和Las ...

  5. 从.Net到Java学习第二篇——IDEA and start spring boot

    从.Net到Java学习第一篇——开篇 所谓工欲善其事,必先利其器,做java开发也一样,在比较了目前最流行的几个java IDE(eclipse,myeclipse.IDEA)之后,我果断选择IDE ...

  6. 从.Net到Java学习第一篇——开篇

    以前我常说,公司用什么技术我就学什么.可是对于java,我曾经一度以为“学java是不可能的,这辈子不可能学java的.”结果,一遇到公司转java,我就不得不跑路了,于是乎,回头一看N家公司交过社保 ...

  7. Sublime text 入门学习资源篇及其基本使用方法

    Sublime text 学习资源篇 史上最性感的编辑器-sublimetext,插件, 学习资源 官网 http://www.sublimetext.com/ 插件 https://packagec ...

  8. Entity Framework学习初级篇2

    Entity Framework 学习初级篇2--ObjectContext.ObjectQuery.ObjectStateEntry.ObjectStateManager类的介绍 本节,简单的介绍E ...

  9. Docker虚拟化实战学习——基础篇(转)

    Docker虚拟化实战学习——基础篇 2018年05月26日 02:17:24 北纬34度停留 阅读数:773更多 个人分类: Docker   Docker虚拟化实战和企业案例演练 深入剖析虚拟化技 ...

随机推荐

  1. Window Linux下实现指定目录内文件变更的监控方法

    转自:http://qbaok.blog.163.com/blog/static/10129265201112302014782/ 对于监控指定目录内文件变更,window 系统提供了两个未公开API ...

  2. struts2.x中因变量命名错误不被注入到值栈的问题

    //I declare... private String aBC="abc"; Then I Alt+Shift+R and S(Generate Getter/Setter) ...

  3. 有关PHP中点击下载文件的小功能

    最近需要在项目里加一个可以点击导出树状目录的目录结构图, 我在网上查了之后,发现基本千篇一律, 都是使用下面这种header函数, 直接去readfile() 这个文件 header('Content ...

  4. centos7.0 php-fpm 安装ImageMagic php扩展imagick

    Just copy and paste: $ yum install make $ yum install gcc $ yum install php php-fpm php-devel php-pe ...

  5. python bottle 框架开发任务管理系统 V_1.0版

    经过1-2个星期的开发,现在开发了个半成品(UI现在比较烂,因为我的前端本来就很差,将就下吧),大概功能如下:用户功能(添加.删除.修改),添加部门功能,任务管理功能(添加.删除.修改,详细).项目管 ...

  6. 数塔(dp)

    数塔 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submissi ...

  7. 1010 Area

    题目要求面积和判断非相邻边不相交.和数学和几何有关系. #include <stdio.h> #include <math.h> #define MISS 0.0000001 ...

  8. Hits per second 下降的几个原因

    1.首先看看服务器的资源消耗情况,可能是服务器 处理不了那么多请求, 有很多请求都在等待,此时可以监控一下服务器的资源 看看是不是有很多等待队列 是不是有很多的等待的请求,可用vmstat命令,第一个 ...

  9. mysql----innodb统计信息

    对innodb 统计信息的控制可以通过如下几个常用的variables 来实现 1.innodb_stats_persistent: 这个参数控制着innodb的统计信息是否持久化到磁盘,先说明一下持 ...

  10. load average[zhuan]

    load average值的含义 单核处理器 假设我们的系统是单CPU单内核的,把它比喻成是一条单向马路,把CPU任务比作汽车.当车不多的时候,load <1:当车占满整个马路的时候 load= ...