%hd在c语言中什么意思(%hd在c语言中是什么意思)

语法:

scanf(“格式化字符串”,输入列表);

“格式化字符串”的格式是:“普通字符+%[<修饰符>]<格式字符>+转义字符”,与printf函数一样。

普通字符、%[<修饰符>]<格式字符>、转义字符这三者的概念,与前面讲printf函数的时候一样,并且,它们同样可以自由组合、任意顺序、重复使用。只不过,需要注意的是,此时的“%[<修饰符>]<格式字符>”表示的是对所要输入的数据的格式的控制。

输入列表就是指所要输入的数据所存放的位置(即内存地址)。当需要同时输入多个数据时,用逗号作为两个存储地址之间的间隔符。注意:输入列表中的每一项,只能是变量的地址(即数据的存储地址),不能是变量名;一般情况下,使用&运算符来取变量的地址(如&a、&b等等),或者,也可以使用指针来表示变量的地址;除此之外,一般情况下,输入列表中项的个数要与“%[<修饰符>]<格式字符>”的个数一致,并且输入的数据类型也要一致(不能说,格式字符是%s,而输入的数据却是整型,也就是输入列表中的对应项是一个整型变量的地址),总而言之,就是输入项要与格式字符的顺序、个数、类型一致。

还有,当我们输入多个数据时,可以用空格符(空格键)、制表符(Tab键)或换行符(Enter键)作为两个输入数据间的间隔符,表示前一个数据输入完毕了;当我们输入完最后一个数据时,用换行符作为数据输入结束的标志,表示所有的数据都输入完了;程序在等待所有的数据都输入完之后,就会继续往下执行。

下面,我们来具体举一些例子:

int a,b,c; int *p=&c; short d; char e,ch; float f; double g; char s[20]; long lo;

1、scanf(“%3d”,&a); //这条语句表示对所要输入的数据的宽度有限制,即输入的字符个数不能超过3个。因为,我们输入数据都是通过键盘按下数字或字符键来进行输入,而当我们按下的时候,系统至少会做两件事(这里,我们只讲输入整型数据);一个是将我们按下的数字以字符的形式显示到屏幕上,以便让我们看到,另一个则是将我们按下的数字以整型数值的形式存储到变量a所在的内存地址位置;而在这里,我们在格式字符前面加了修饰符数字3,就是为了限制我们所按下的数字的个数,而且,即使我们所按下的数字的个数超出了限制范围(注意:虽然超出了限制范围,但超出的那部分数字,当我们按下时系统还是会在屏幕上显示的),系统也只会截取前面3个字符来作为输入数据。因此,在这里,我们只能输入-99~999这之间的数据,因为这之间的数据的字符个数都不超过3个(算上正负号);如果我们输入的数据不在这个范围内,那么只会得到错误的结果。


2、int b; short d; float f; double g; long lo;

scanf(“%ld%hd%f%lf%o%x”,&lo,&d,&f,&g,&b,&c);

//“%ld%hd%f%lf%o%x”分别依次表示以长整型、短整型、单精度浮点型、双精度浮点型、八进制、十六进制的格式输入数据,也就是说,所输入的数据都会以对应的数据类型来存储。比如,第一个数,我们输入10,虽然这个10,我们用int类型变量也能存储,但是它这里会用long类型变量来存储;再比如,我们最后一个数,也输入10,这时,这个10就不能念作“十”了,而应该念作“一零”,因为,虽然我们输入的是“十”,但这条语句会把它认作是一个十六进制的数,即0x10,也就是十进制的16,所以,当它被存储到变量c中时,它会以十进制数16的形式来存储,而非是以十进制数10的形式来存储,也就是,实际存储的是十进制的数据16、而非十进制的数据10。


3、int a,b,c;

scanf(“%d%*d%d”,&a,&b,&c);

//在修饰符中,“*”星号是一个比较特殊的修饰符,它的作用就是跳过对应输入项的输入,意思就是,使“对对应输入项的数据输入”无效,并且将“对下一个输入项所要输入”的数据存储到该输入项所表示的地址中。以当前这个例子为例,如果我们在键盘上依次输入1、2、3,想要把1、2、3分别存储到变量a、b、c中,那么,最终结果是,a=1,b=3,而变量c则没有被赋值;因为,当我们输入2时,由于“*”星号的作用,所输入的数据2会被scanf函数给忽略掉,就好像我们没有输入过2一样,而实际是,我们确实输入了2,但是scanf函数并没有把2赋值给变量b,而是在接收了数据2之后就把它给丢弃了,因此,当我们输入2时,变量b并没有被赋值。而当我们输入3时,由于变量b还未被赋值过,scanf函数会先给前面未输入的输入项赋值,而并不会跳过变量b、直接给变量c赋值,所以,数据3会被赋值给变量b。至于变量c,由于我们前面只输入了1、2、3这三个数,并没有第四个数可以用来赋值给变量c,而且,我们在scanf的格式化字符串中只写了三个格式字符,这表示我们在这个scanf语句中只能输入三个数据,所以,即使我们前面在输入数据的时候输入了四个数据,第四个数据也不会被赋值给变量c,因此,变量c最终是没有被赋值的;但如果将上面的例子写成如下形式,那么所输入的第四个数据就可以被赋值给变量c:

scanf(“%d%*d%d%d”,&a,&b,&c);

这时,我们输入1、2、3、4,那么,得到的最终结果就a=1,b=3,c=4。


4、int a,b,c; char e,ch;

scanf(“%d%c”,&a,&e);

//对于字符或字符串的输入,我们需要格外注意,因为,当我们输入字符时,作为输入项间隔符的空格、制表符、换行符也会被scanf函数看作是一个单独的字符,被存储到输入项中。

//以上面这个例子为例,如果我们输入“数字1+空格+字符A,最后按回车”,那么得到的结果是a=1,e=空格,字符A并没有被赋值给变量e。这是因为,空格也被scanf函数看作是一个字符,被存储到变量e中了,因此就没有多余的变量用来存储字符A了。在这里,空格字符不仅仅是作为一个分隔符,用来分界多个输入项,它还会被看作是一个字符,可以被存储到输入项当中。但如果给上面的例子多增加一个输入项,即改成如下样子,那么字符A就会被存储到第三个输入项当中了。修改后,如下:

scanf(“%d%c%c”,&a,&e,&ch);

这时,我们再输入“数字1+空格+字符A,最后按回车”,那么得到的结果就是a=1,e=空格,ch=A。

利用这个原理,我们可以配合“*”星号的功能来跳过空格字符的输入,即,空格字符虽然被scanf函数接收了,但没有被赋值给任何变量,而空格之后的字符就会被赋值给“原本空格字符所要赋值”的变量。所以,根据以上原理,我们就可以把上面的例子改成如下样子:

int a,b,c; char e,ch;

scanf(“%d%*c%c”,&a,&e);

这样,我们就可以少写一个输入项,并且字符A还能按我们预期的样子被存储到变量e中。

除了可以用这种方法来处理字符输入的问题外,我们还可以通过调换格式字符的顺序来保证空格、制表符、换行符不被存储到输入项中。以上面的例子为例,我们可以将上面的例子改成如下样子:

int a,b,c; char e,ch;

scanf(“%c%d”,&e,&a);

这时,我们输入的时候就要改变一下顺序了,即“字符A +空格+数字1,最后按回车”,这样,空格字符就不会被存储到变量e中了,也不会被存储到变量a中。这是因为字符A是最先被输入的,所以在它前面并没有其他字符会被先存储,因此字符A就会被存储到变量e中;其次,由于“%d”表示的意思是要输入一个整型的数据,而空格是一个字符、无法被看作是一个整型的数据(虽然它的ASCII的十进制值是32,但scanf函数并不会把转换成32),所以,空格对于“%d”是无效的,会被跳过,就好像加了*星号一样,所以空格并不会被赋值给变量a,所以数字1就会还有地方可以存储,即变量a。最终得到的结果就是e=A,a=1。

我们再来看个例子:

int a,b,c; char e,ch;

scanf(“%c”,&e); //这里我们输入数字1,即按下键盘上的数字1

scanf(“%d”,&a); //这里我们也输入数字1

这里,我们会发现,数字1,既被看作是一个字符,又被看作是一个整型的数据。所以,同样的按键,不同的数据类型,scanf函数对按键的处理方式是不一样的。这一点,我们要注意。


还有一点,需要注意,那就是字符串的输入。以如下例子为例:

char s[20];

scanf(“%s”,s);

//如果我们输入“hello world!”这样一个带空格的字符串,那么scanf函数只会把空格前面的字符串保存到字符数组s中,而不会把整个“hello world!”保存到字符数组s中。所以,在使用这种方式输入字符串时,要注意,不要带空格。如果就想要带空格,那么可以用专门的字符串输入函数。

//除此之外,要注意,所输入的字符个数不要超过数组的元素个数。


5、int a,b,c;

scanf(“%d,%d,%d”,&a,&b,&c);

//在scanf函数的格式化字符串中也是可以把普通字符放进去的,但是要注意,在我们输入数据的时候,这些普通字符是并不会显示在屏幕上的,而且,我们需要按照scanf函数的格式化字符串中普通字符和格式字符的顺序,原样地把普通字符和数据输入进去(注意:普通字符和数据的位置关系要与格式化字符串中普通字符和格式字符之间的位置关系保持一致)。

//如果两个格式字符之间有普通字符,那么输入数据的时候,就不能用空格、制表符、换行符作为两个输入项的间隔了,而是必须以该普通字符作为两个输入项之间的间隔;若两个格式字符之间没有普通字符,那么输入数据时依旧用空格、制表符、换行符作为两个输入项的间隔,而不能普通字符作为间隔。

//以上面的例子为例,我们输入完一个输入项之后,需要以逗号作为分隔符,而不能以空格、制表符、换行符作为分隔符,否则得到的结果就是错误的。比如,我们输入“1,2,3”,得到的结果就是a=1,b=2,c=3;但如果我们输入“1空格2空格3”,那么得到的结果就是a=1,b和c的值是未知的、不确定的。

我们再举个例子:

int a,b,c;

scanf(",,%d,%d%d",&a,&b,&c);

//这时,我们输入数据时就得这么输入:“,,1,2空格3”。只有这样,才能得到正确的结果。如果我们顺序错了或者少了一个字符,或者该空格的没空格、该普通字符的没输普通字符,那么得到的必定会是错误、不可预期的结果。

下面,我们再看个例子:

int a,b,c;

scanf(“%d\t%d\n%d”,&a,&b,&c);

//在scanf函数的格式化字符串中,我们也可以把转义字符添加进去,但是要注意,只有\n、\t、\v、\r、\f这几个转义字符不会对输入造成影响,我们按照正常的输入方式(以空格、制表符、换行符为间隔)进行数据输入即可;而其他的转义字符,则都需要按照与普通字符一样的方式输入,即上面所讲的方式。

但对于字符的输入,\n、\t、\v、\r、\f这几个转义字符却又有特殊的作用:在前面,我们说过,字符输入时,空格、制表符、换行符也会被scanf函数看作是一个字符、被存储到输入项中,但是如果在两个“%c”之间插入这几个转义字符,那么我们就可以按照正常的方式输入字符了,它的作用就相当于前面提到过的“%*c”。例如,下面这个例子:

char a,b,c;

scanf("%c\f%c\t%c",&a,&b,&c);

//这时,我们输入字符时就可以按照“a空格b空格c回车”的方式进行输入了,而不用担心空格会被scanf函数保存到输入项中。

但是,建议最好不要把普通字符或者转义字符放到scanf函数的格式化字符串中,因为很容易会发生意想不到的错误。比如如下这个例子:

int a,b,c;

scanf(“\v\r\f%d\t%d\n%d\f\r\v”,&a,&b,&c);

//当程序执行到上面这条语句,我们进行输入时,我们会发现,我们按回车无法结束输入,这其实就跟“%d”后面的转义字符有关了,至于为什么请自行查资料。


7、int c; int *p=&c;

scanf(“%d”,&c);

scanf(“%d”,p);

//我们前面说过,输入列表中的每一个输入项只能是变量的地址,不能是变量名。既然输入项只能是地址,那么它也可以用指针表示,即指向变量的指针,因为指针与变量的地址指向的都是相同的存储位置。

//在上面的例子中,两种写法的作用是相同的,都是在给变量c赋初值;只不过,前者是用&运算符取变量c的地址,而后者则是直接用指向变量c的指针。