龙空技术网

「C与指针心得」1.scanf\strncpy\strcpy\memcpy的使用

IngresGe 326

前言:

现在小伙伴们对“c语言scanf错误”可能比较重视,大家都想要知道一些“c语言scanf错误”的相关资讯。那么小编同时在网摘上收集了一些有关“c语言scanf错误””的相关内容,希望看官们能喜欢,同学们一起来学习一下吧!

感谢您的关注与点赞!

本文默认阅读人员已经有了一点C语言的基础,类似循环操作、分支语句、变量定义等简单的操作不再叙述。

这一章重点讲解如何从键盘进行输入、以及相应的字符串拷贝。这里主要用到四个C的基础API–scanf\strcpy\strncpy\memcpy。

scanf

作用: 是格式输入函数,即按用户的制定格式从键盘上把数据输入到制定变量中

头文件: #include <stdio.h>

调用形式:scanf(“<格式说明字符串>”,<变量地址>);

注意:第二个参数是一个地址,记得加&取地址符号,假如你是一个数组,不需要加入&符号,如果是一个数组带下表,需要加上&取地址符号

int column[8];

int num;

scanf(“%d”,&num);

scanf(“%d”,column); //column是一个数组,scanf使用时,可以直接输入column

scanf(“%d”,&column[1]); //这里只想用column的第一个字段,因此需要带入下标

例如:

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

如果a和b都被成功读入,那么scanf的返回值就是2

如果只有a被成功读入,返回值为1

如果a和b都未被成功读入,返回值为0

如果遇到错误或遇到end of file,返回值为EOF。

且返回值为int型.

&a,&b,&c中的&是地址运算符,&a指a在内存中的地址。scanf的作用是:按照a,b,c的内存地址将输入的数据存到a,b,c中去。变量a,b,c的地址是在编译连续阶段分配的(存储顺序由编译器决定)。

注意部分:

如果scanf中%d是连着写的如“%d%d%d”,在输入数据时,数据之间不可以加逗号,只能是空格或tab键或者回车键——“2 3 4” 或 “2(按tab)3(按tab)4(按tab)”。若是“%d,%d,%d”,则在输入数据时需要加“,”,如“2,3,4”.

相关输入格式

变量 类型

%d int

%ld long

%f float

%lf double

%c char

%s char数组

代码示例:

#include <stdio.h>#include <stdlib.h>int main(void){ int a; float b; char c; scanf("%d,%f,%c",&a,&b,&c); printf("a=%d,b=%f,c=%c\n",a,b,c); scanf("%d%f %c",&a,&b,&c); printf("a1=%d,b1=%f,c1=%c\n",a,b,c); return 0;}

输入输出:

1,2.3,d //输入a=1,b=2.300000,c=d //输出1 2.4 e //输入a1=1,b1=2.400000,c1=e //输出
strcpy

作用: 把从src地址开始且含有NULL结束符的字符串赋值到以dest开始的地址空间,返回dest(地址中存储的为复制后的新值)

头文件: #include <stdio.h>和<string.h>

调用形式:char strcpy(char dest,char *src);

注意:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。

函数原型:

char* strcpy(char* des,const char* source) { char* r=des;  assert((des != NULL) && (source != NULL)); while((*r++ = *source++)!='\0'); return des;}

注意:

该函数的参数是字符指针,也就是可以是字符串变量和字符数组,因为它们的变量名代表首字符地址。字符串默认有一个null结束符,字符数组没有。所以此处需要注意:因为src要求有null结束符,所以字符数组的长度必须大于等于src包含null结束符的总长度。

例如,char* src=”abcd”; char dest[5]; 这里dest的长度就至少为5。

示例代码:

int main(){ char dest[30] = {0}; char src[20]={"Hello world!"}; strcpy(dest, src); printf("%s\n", src); return 0;}

输出:

Hello world!

思考:如果这里dest的长度是2,会不会出现问题。

解答:如果你只是简单的在PC上运行代码,那可能不会出错,但是你放入到真正的程序中运行,就会出现地址异常报错。因为,dest的栈空间只有两个字节,但是需要拷贝过来的“Hello World!”远远超过了两个字节,剩下的内容就会被拷贝到dest栈空间的连续地址,如果这些地址被其他人占用了的话,就会出现地址异常,甚至程序奔溃。

所以在我们一般不适用strcpy,可以使用strncpy来进行拷贝,这个API有长度验证,可以减少类似内存问题

strncpy

作用: 将字符串src中最多n个字符复制到字符数组dest中(它并不像strcpy一样遇到NULL才停止复制,而是等凑够n个字符才开始复制),返回指向dest的指针

头文件: #include <stdio.h>和<string.h>

调用形式:char strncpy(char dest, char src, size_t n);

注意:如果n > dest串长度,dest栈空间溢出产生崩溃异常。该函数注意的地方和strcpy类似,但是n值需特别注意。

1)src串长度<=dest串长度,(这里的串长度包含串尾NULL字符)

如果n=(0, src串长度),src的前n个字符复制到dest中。但是由于没有NULL字符,所以直接访问dest串会发生栈溢出的异常情况。这时,一般建议采取memset将dest的全部元素用null填充,如:memset(dest,0,7)(7为从dest起始地址开始前7个位置填充null,dest可以为字符指针和数组名)。注意:char pc=”abc”; char chs[5]; sizeof(pc)为4(包含null)(有些编译器不行),sizeof(chs)为5。

如果n = src串长度,与strcpy一致。

如果n = dest串长度,[0,src串长度]处存放于desk字串,(src串长度, dest串长度]处存放NULL。

2)src串长度>dest串长度

如果n =dest串长度,则dest串没有NULL字符,会导致输出会有乱码。如果不考虑src串复制完整性,可以将dest最后一字符置为NULL。

所以,一般把n设为dest(含null)的长度(除非将多个src复制到dest中)。当2)中n=dest串长度时,定义dest为字符数组,因为这时没有null字符拷贝。

示例代码:

#include<stdio.h>#include<string.h>int main(){ char name[]={"Hello World!"}; char dest[20]={}; strncpy(dest,name,12); printf("%s\n",dest);}

输出:

Hello World!
memcpy

作用: 函数memcpy从s2指向的对象中复制n个字符到s1指向的对象中。如果复制发生在两个重叠的对象中,则这种行为未定义

头文件: #include <string.h>

调用形式:void memcpy(void s1, const void *s2, size_t n);

返回值:s1的值

注意:memcpy用来在内存中复制数据,由于字符串是以“\0”结尾的,所以对于在数据中包含“\0”的数据只能用memcpy。

Strncpy和memcpy很相似,只不过它在一个终止的空字符处停止。当n>strlen(s1)时,给s2不够数的空间里填充“\0”;当n<=strlen(s1)时,s2是没有结束符“\0”的。

示例代码:

#include <stdio.h>#include <string.h>int main(){ char* s="Hello World!"; char d[20] = {0}; clrscr(); memcpy(d,s,(strlen(s)+1)); //+1 是为了将字符串后面的'\0'字符结尾符放进来,去掉+1可能出现乱码 printf("%s",d); getchar(); return 0;}

输出:

Hello World!

标签: #c语言scanf错误 #strncpy_s头文件 #c语言scanf参数过多