首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

一道面试题目,该如何解决

2012-02-12 
一道面试题目找出下边代码中的错误:void test1(){ char string[10] char* str1 0123456789 strcpy(

一道面试题目
找出下边代码中的错误:
void test1()
{
 char string[10];
 char* str1 = "0123456789";
 strcpy( string, str1 );
}
大家看看有哪些错误?


[解决办法]
越界
[解决办法]
用strcpy()会出现数组越界!


cout < <a[0] < <endl; 
cout < <a[9] < <endl; 
每次只输出单个char的值,是可正常执行的。
[解决办法]
因为这不是JAVA
[解决办法]
拷贝过程是没有问题的。
数组里面就是那十个数。
你可以查看以下memory
退出的时候才会crash的。
[解决办法]
从理论上说

strcpy( string, str1 );

这条语句会报错,因为 

char* str1 = "0123456789"; 

str实际指向的是11个字符的空间地址,字符串的结束符‘\0’也占一个字节。

而执行strcpy函数把一个11个字节长的字符串赋给10字节长的数组是显然越界了的。

但在32位机上安装的VC++6.0上调试该函数,并不会报错,楼主可以自己动手试试!

[解决办法]

C/C++ code
char string[10], str1[10];  int i;  for(i=0; i <10; i++)  {   str1[color=#FF6600][i] [/color]= 'a';  }  strcpy( string, str1 );
[解决办法]
str1是11个字符,最后一个是字符串的结束符‘\0’(为了兼容c语言),而sting[10]只是10,所以会出现数组越界。
[解决办法]
12楼的说的太对了,strcpy函数是用于以结束符\0'字符串的拷贝,对于没有结束符'\0'的字符串,虽然在有的编译器上能编译,但它是不合法的,当然是不是越界我不太清楚,不过我记得好象对于不同的字符串好象也能拷贝,只是有数据的 损失!
[解决办法]
C/C++ code
void test1() {  char string[10];  char* str1 = "0123456789";  strcpy( string, str1 ); }
[解决办法]
这个问题初学者经常会很疑惑。我简单的解释一下~

void test1() 

 char string[10]; 
 char* str1 = "0123456789"; 
 strcpy( string, str1 ); 


上面这个strcpy确实越界了,破坏的是堆栈的数据。但是这个越界造成的影响不一定就会导致程序异常。注意,这里说的是不一定会,不是一定不会。

首先要了解一个事实:调用test1函数的时候,会将调用点的下一条语句的地址记录在堆栈中。然后这个函数执行完了,把开始记录的地址取出来,继续运行。也就是说,只要堆栈里的返回地址不被修改,那么继续正常运行下去是没问题的。

在VC6环境下,DEBUG版本因为要支持Edit and Continue的特性,为每个函数在堆栈中多分配了64个字节的多余数据。也就是说,只要越界的不是足够多的话,或者说没有修改函数返回地址,是不会发生异常的。Release环境下就没有这64个字节了,但是LZ的这个代码仍然不会出错。因为char string[10]要求堆栈分配10个字节。但是堆栈分配的时候是4字节对其,所以实际上分配了12个字节。也就是说这里多写的1个字节还是没影响函数返回地址。

lz不妨把str1定义为一个超过11字节的数据看看是不是出错。。。 不过,不出错的概率不是100%的。

[解决办法]
自己发的文章,自己不能修改吗?


刚才写了个函数看了一下,上面说错一个地方。DEBUG版本多分配的64字节是在函数局部变量的前面,不是导致Debug版没有出错的原因。应该是跟Release版的解释相同。
[解决办法]
越界。

使用strcpy(a, b), 一定要检查a, b是否满足条件:a的长度 > b的长度。这里说的长度是字符串到'\0'结束的长度。
"0123456789"的实际长度为11(包括最后的'\0').
string[10]只有10,使用strcpy越界。

[解决办法]
给楼主看一些东西
试题1:

void test1()
{
 char string[10];
 char* str1 = "0123456789";
 strcpy( string, str1 );
}
  试题2:

void test2()
{
 char string[10], str1[10];
 int i;
 for(i=0; i<10; i++)
 {
  str1 = 'a';
 }
 strcpy( string, str1 );
}
  试题3:

void test3(char* str1)
{
 char string[10];
 if( strlen( str1 ) <= 10 )
 {
  strcpy( string, str1 );
 }
}
  解答:



  试题1字符串str1需要11个字节才能存放下(包括末尾的’\0’),而string只有10个字节的空间,strcpy会导致数组越界;

  对试题2,如果面试者指出字符数组str1不能在数组内结束可以给3分;如果面试者指出strcpy(string, str1)调用使得从str1[url=]内存[/url]起复制到string内存起所复制的字节数具有不确定性可以给7分,在此基础上指出库函数strcpy工作方式的给10分;

  对试题3,if(strlen(str1) <= 10)应改为if(strlen(str1) < 10),因为strlen的结果未统计’\0’所占用的1个字节。

  剖析:

  考查对基本功的掌握:

  (1)字符串以’\0’结尾;

  (2)对数组越界把握的敏感度;

  (3)库函数strcpy的工作方式,如果编写一个标准strcpy函数的总分值为10,下面给出几个不同得分的答案:

  2分

void strcpy( char *strDest, char *strSrc )
{
  while( (*strDest++ = * strSrc++) != ‘\0’ );
}
  4分

void strcpy( char *strDest, const char *strSrc ) 
//将源字符串加const,表明其为输入参数,加2分
{
  while( (*strDest++ = * strSrc++) != ‘\0’ );
}
  7分

void strcpy(char *strDest, const char *strSrc) 
{
 //对源地址和目的地址加非0断言,加3分
 assert( (strDest != NULL) && (strSrc != NULL) );
 while( (*strDest++ = * strSrc++) != ‘\0’ );
}
  10分

//为了实现链式操作,将目的地址返回,加3分!

char * strcpy( char *strDest, const char *strSrc ) 
{
 assert( (strDest != NULL) && (strSrc != NULL) );
 char *address = strDest; 
 while( (*strDest++ = * strSrc++) != ‘\0’ ); 
  return address;
}
  从2分到10分的几个答案我们可以清楚的看到,小小的strcpy竟然暗藏着这么多玄机,真不是盖的!需要多么扎实的基本功才能写一个完美的strcpy啊!

[解决办法]
越界
[解决办法]
好简单,因为'\0'没得放
[解决办法]
1.数组越界问题
2.const char*指向的空间内容不可修改
如:

C/C++ code
char* p="csdn";//或const char* p="csdn";*p='c';//Error! *p为const char型别
[解决办法]
[Quote=引用:]
C/C++ code
试题1: void test1() {  char string[10];  char* str1 = "0123456789";  strcpy( string, str1 ); }   试题2: void test2() {  char string[10], str1[10];  int i;  for(i=0; i <10; i++)  {   str1 = 'a';  }  strcpy( string, str1 ); }   试题3: void test3(char* str1) {  char string[10];  if( strlen( str1 )  <= 10 )  {   strcpy( string, str1 );  } }
[解决办法]
//为了实现链式操作,将目的地址返回,加3分! 

C/C++ code
char * strcpy( char *strDest, const char *strSrc )  { // assert( (strDest != NULL) && (strSrc != NULL) );  assert( (strDest != NULL) && (strSrc != NULL) && (strDest != strSrc) );  char *address = strDest;   while( (*strDest++ = * strSrc++) != ‘\0’ );    return address; }
[解决办法]
貌似数组在声明时还要赋初值吧,也就是直接定义拉
[解决办法]
字符指针本质上是个字符串,所以可以将此字符串赋值进数组。

热点排行