1.c语言中#的作用,比如char const * pParam##_log = #pParam ,第一个#是编译时将前后两个变量连接,第二个#是把后面的参数变成一个字符串也就是变成“”pparam“”
13. 不正确的赋值或赋13. 不正确的赋值或赋初值的方式是______。
a、char str[]="string";
b、char str[7]={'s', 't', 'r', 'i', 'n', 'g'};
c、char str[10];str="string";
d、char str[7]={'s', 't', 'r', 'i', 'n', 'g', ’\0’};
答案是c,str是该数组的数组名字,而且str还是该数组的首地址,也就是十个元素中的第一个元素的地址,但务必注意str是一个指针常量,它是不能被赋值的也不能进行自增自减的!
2.char a[] = {'a','b','c'};
char b[10] = {'a','b','c'};
strlen(a),strleb(b)分别是多少?
给这两个数组赋初值时,系统自动添加字符串结束符,所以长度都是3.
3.c语言写文件时以"wt"方式写入的是字符文件,转义字符'\n'被看作两个字符来处理。而"wb"方式写入的是二进制文件,转义字符'\n'是一个字符。
4.char*s="china";等价于char*s;s="china";
14. 对于以下结构定义,++p->str中的++加在_____。
struct {
int len;
char *str;
} *p;
a、指针str上 b、指针p上 c、str指的内容上 d、以上均不是
选d
p是一个结构体指针,结构体指针访问成员用"->",结构体变量用"."
正确的应该是p->str++,或者(*p).str++
#include <stdio.h>
#include <alloc.h>
struct link {
char name[10];
int mark;
struct link * next;
};
void insert(char *, int);
struct link * head = null;
main()
{
char name[10];
int mark;
struct link * t;
while ( 1 ) {
scanf("%s %d", name, &mark);
if ( strcmp(name, "#") == 0 ) break;
______(1)_______;
}
for (t=head; ______(2)_______)
printf("<%s>: %d\n", t->name, t->mark);
}
void insert(char * name, int mark)
{
struct link * p;
p = ______(3)_______ ;
strcpy(p->name, name);
p->mark = mark;
______(4)_______;
if ( head != null ) ______(5)_______;
head = p;
}
四、程序填空题
(1) insert(name, mark)
(2) t!=null; t=t->next
(3) (struct link *)malloc(sizeof(struct link))
(4) p->next = null
(5) p->next = head
floatx1,x2; x1=3/2; x2=x1/2; printf("%d%.1f",(int)x1,x2); 输出值是多少
因为 x1=3/2; 3和2都是整型,除下来结果也为整型,是1,然后赋值给float,变成1.0
/-----------------------------------------------------------------------------------------------------------------/
#define a 10
#define b (a<a+2)-2 //+的优先级比<高,所以先+再<
/-----------------------------------------------------------------------------------------------------------------/
6. 写出下列程序段的输出结果:printf(“%d, %d”, null, eof); 0, -1
/-----------------------------------------------------------------------------------------------------------------/
3. 完成字符串拷贝可以使用 sprintf、strcpy 及 memcpy 函数,请问这些函数有什么区别,你喜欢使用哪个,为什么?
答:这些函数的区别在于实现功能以及操作对象不同。
1. strcpy函数操作的对象是字符串,完成从源字符串到目的字符串的拷贝功能。
2. sprintf函数操作的对象不限于字符串:虽然目的对象是字符串,但是源对象可以是任意基本类型的数据。这个函数主要用来实现数据类型向字符串的转换功能。如果源对象是字符串,并且指定 %s 格式符,也可实现字符串拷贝功能。
3. memcpy函数可适用于任意数据类型,只要能给出对象的起始地址和内存长度信息、并且对象具有可操作性即可。鉴于memcpy函数等长拷贝的特点以及数据类型代表的物理意义,memcpy 函数通常限于同种类型数据或对象之间的拷贝,其中当然也包括字符串拷贝以及基本数据类型的拷贝。
对于字符串拷贝来说,其实现的效率和使用的方便程度不同:
• strcpy无疑是最合适的选择:效率高且调用方便。
• sprintf要额外指定格式符并且进行格式转化,麻烦且效率不高。
• memcpy 虽然高效,但是需要额外提供拷贝的内存长度这一参数,易错且使用不便;并且如果长度指定过大的话(最优长度是源字符串长度 + 1),还会带来性能的下降。其实strcpy函数一般是在内部调用memcpy函数或者用汇编直接实现的,以达到高效的目的。因此,使用 memcpy 和 strcpy 拷贝字符串在性能上应该没有什么大的差别。
对于非字符串类型的数据的复制来说,strcpy和snprintf一般就无能为力了,可是对memcpy却没有什么影响。但是,对于基本数据类型来说,尽管可以用memcpy进行拷贝,由于有赋值运算符可以方便且高效地进行同种或兼容类型的数据之间的拷贝,所以这种情况下memcpy几乎不被使用。
/-----------------------------------------------------------------------------------------------------------------/
4. 变量的定义和声明有什么区别?
答:定义包含为变量分配存储空间和指定初始值;而声明仅用于向编译器告知变量的名称和类型类似external变量。
/-----------------------------------------------------------------------------------------------------------------/
8. 定义 int **a[3][4], 则变量占有的内存空间为多少。
答:变量a的大小,那么就是4,因为它就是一个指针。如果是数组的大小,那么是4*3*4=48,它实际上是一个指针的指针的二维数组。
/-----------------------------------------------------------------------------------------------------------------/
12. x=x+1,x+=1,x++,为这三个语句的效率排序。并说明为什么。
答:x=x+1 < x+1 <x++,因为:x=x+1的执行过程如下:1. 读取右x的地址; 2.x+1; 3. 读取左x的地址; 4. 将右值传给左边的x(编译器并不认为左右x的地址相同)。
x+=1的执行过程如下:1. 读取右x的地址; 2.x+1; 3. 将得到的值传给x(因为x的地址已经读出)。
x++的执行如下:1. 读取右x的地址; 2. x自增1。实际上根本没有什么区别,编译器会去优化的。
/-----------------------------------------------------------------------------------------------------------------/
14. static全局变量与普通全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
/----------------------------------------------------------------------------------------------------------------------------/
1. static全局变量和普通的全局变量,在内存中的位置是一样的,区别在于static全局变量只在当前的文件有效,而普通全局变量在所有的文件中都有效。
2. static局部变量和普通局部变量在内存中的存储就不一样了,使得普通全局变量每次都会重新初始化,而static局部变量只会初始化一次,之后就沿用上一次的值。
3. static函数和普通函数的差别是,static函数只在当前文件有效,而普通函数默认是extern的,因此在其它文件也有效。
/----------------------------------------------------------------------------------------------------------------------------/
22. switch中允许的数据类型是?
答:整型常量表达式。重点是整型和常量。C/C++中整型包括:int,char和enum,C++中还包含bool类型
/----------------------------------------------------------------------------------------------------------------------------/
30. 求1000!的未尾有几个0。
答:1-1000中能够整除5的幂比如(5,25,125,625)一共有249个,所以有249个。
/----------------------------------------------------------------------------------------------------------------------------/
2.用typedef定义一个长度为10的整型数组num
typedef int num[10] 使用就是num a;
/----------------------------------------------------------------------------------------------------------------------------/
3.表达式(7<<1>>2^2 ) 的值是_______。 ((7<<1)>>2)^2 )
/----------------------------------------------------------------------------------------------------------------------------/
4.以下选项中不正确的实型常量是_____。
a.0.23e b.2.3e-1 c.1e3.2 d.2.3e0
答案是c e之前随意,后必须是整形,因为e后是幂,哪有带小数点的幂
char*strstr(const char *str1, const char *str2)
{
char *cp = (char*)str1;
char *s1, *s2;
if (!*str2)
return((char *)str1);
while (*cp)
{
s1 = cp;
s2 = (char *)str2;
while (*s1 && *s2 &&!(*s1 - *s2))
s1++, s2++;
if (!*s2)
return(cp);
cp++;
}
return(null);
}
/----------------------------------------------------------------------------------------------------------------------------/
char*strcpy(char* des,const char* source)
{
char* r=des;
assert((des != null) && (source !=null));
while((*r++ =*source++)!='\0');
return des;
}
/----------------------------------------------------------------------------------------------------------------------------/
void*memcpy(void*destaddr, void const*srcaddr, size_tlen)
{
char* dest=destaddr;
char const* src=srcaddr;
while(len>0)
{
*dest++ = *src++;
len--;
}
return destaddr;
}
/----------------------------------------------------------------------------------------------------------------------------/
char *mystrcat(char *dst,const char *src)
{
char *p=dst; //下面的操作会改变目的指针指向,先定义一个指针记录dst
while(*dst!='\0')dst++;
while(*src!='\0')*dst++=*src++;
*dst='\0';
return p; //dst现在指向拼接后的最后一位字符,在这里返回dst,会出现错误
}
/----------------------------------------------------------------------------------------------------------------------------/
根据我们上面的阐述可以知道:新结构建立的过程中遇到了pnext域的声明,类型是pnode,要知道pnode表示的是类型的新名字,那么在类型本身还没有建立完成的时候,这个类型的新名字也还不存在,也就是说这个时候编译器根本不认识pnode。
解决这个问题的方法有多种:
typedef struct tagnode
{
char* pitem;
struct tagnode* pnext;
}*pnode;
/----------------------------------------------------------------------------------------------------------------------------/
下面代码里的i和j各是多少
static int j;
int k=0;
void fun1(void)
{
static inti=0; 由于i是局部static变量,内存静态区,函数运行结束值不销毁,所以只初始化一次
i++;
}
void fun1(void)
{
j=0;j++;
}
int main()
{
for(k=0;k<5;k++)
{
fun2(); fun1();
}
}
答案:5,0
/----------------------------------------------------------------------------------------------------------------------------/
int const *p和const int *p是一样的,可以省去int
/----------------------------------------------------------------------------------------------------------------------------/
#define 表明1年中有多少秒(忽略闰年问题) #define seconds_per_year (60 * 60 * 24 * 365)ul
/----------------------------------------------------------------------------------------------------------------------------/
2. 写一个“标准”宏min,这个宏输入两个参数并返回较小的一个。 #define min(a,b) ((a) <= (b) (a) : (b)) 注意一定要加括号
/----------------------------------------------------------------------------------------------------------------------------/
9. 给定一个整型变量a,写两段代码,第一个设置a的bit 3,第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变。
#define bit3 (0x1<<3)
a |= bit3;
a &= ~bit3;
/----------------------------------------------------------------------------------------------------------------------------/
(2)请写出float x 与“零值”比较的if 语句:
const floatepsinon = 0.00001; 后面是4个零
if ((x >= -epsinon) && (x <= epsinon)
/----------------------------------------------------------------------------------------------------------------------------/
6、请问以下代码有什么问题:
int main()
{
char a;
char *str=&a;
strcpy(str,"hello");
printf(str);
return 0;
}
没有为str分配内存空间,因为越界进行内在读写而导致程序崩溃。应该str = (char*)malloc(10);
/----------------------------------------------------------------------------------------------------------------------------/
7、请问以下代码有什么问题:
char*s="aaa";
printf("%s",s);
s[0]='b';
printf("%s",s);
"aaa" 是字符串常量。s是指针,指向这个字符串常量,所以声明s的时候就有问题。cosnt char* s="aaa";然后又因为是常量,所以对是s[0] 的赋值操作是不合法的。
char*s中的s是指针,而指针是指向一块内存区域,它指向的内存区域的大小可以随时改变,而且当指针指向常量字符串时,它的内容是不可以被修改的,否则在运行时会报错。
char s[]中的s是数组首地址,而数组首地址对应着一块内存区域,其地址和容量在生命期里不会改变,只有数组的内容可以改变。
什么是预编译?何时需要预编译?
预编译又称预处理,是整个编译过程最先做的工作,即程序执行前的一些预处理工作。主要处理#开头的指令。如拷贝#include包含的文件代码、替换#define定义的宏、条件编译#if等。
何时需要预编译:
1、总是使用不经常改动的大型代码体。
2、程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种情况下,可以将所有包含文件预编译为一个预编译头。
#是把宏参数转化为字符串的运算符
#define STR(arg) #arg 则宏STR(hello)展开时为”hello”
sizeof(void)等于1
sizeof(void *)等于4
结构体数组成员的大小为0是GNU C的一个特性。好处是可以在结构体中分配不定长的大小。如
typedef struct st
{
inta;
int b;
char c[0];
}st_t;
sizeof(st_t)等于8,即char c[0]的大小为0.
指出这个函数的错误
void test2()
{
char string[10], str1[10];
int i;
for(i=0; i<10; i++)
{
str1= 'a';
}
strcpy(string, str1);
}
解答:因为str1没有结束符'\0',故而strcpy复制的字符数不确定。
void test3(char* str1)
{
char string[10];
if(strlen(str1) <= 10 )
{
strcpy(string, str1);
}
}
解答:应修改为if (strlen(str1) < 10),因为strlen的结果未统计最后的结束符'\0'。strlen的源码如下:
#include <string.h>
size_t strlen(const char *s)
{
const char *sc;
for (sc = s; *sc != '\0'; ++sc)/*不包含最后的结束符'\0'*/
return (sc - s);
}
void GetMemory(char *p)
{
p = (char *)malloc( 100 );
}
void Test( void )
{
char *str = NULL;
GetMemory(str);
strcpy(str,"hello world");
printf(str);
}
解答:C语言中的函数参数为传值参数,在函数内对形参的修改并不能改变对应实参的值。故而调用GetMemory后,str仍为NULL。
void GetMemory( char **p, int num )
{
*p = (char *)malloc(num);
}
void Test( void )
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
解答:但在GetMemory内,未对*p为NULL情况的判断。当*p不为NULL时,在printf后,也未对malloc的空间进行free,造成内存泄露
char *GetMemory( void )
{
char p[] = "hello world";
return p;
}
void Test( void )
{
char *str = NULL;
str = GetMemory();
printf(str);
}
解答:GetMemory中,p为局部变量,在函数返回后,该局部变量被回收。故而str仍为NULL
void Test( void )
{
char *str = (char *)malloc( 100 );
strcpy(str, "hello" );
free(str);
... //省略的其它语句
}
解答:未对str为NULL的情况的判断,在free(str)后,str未设置为NULL,可能变成一个野指针(后面对str的操作可能会导致踩内存)。
试题8:
swap(int* p1,int* p2)
{
int *p;
*p = *p1;
*p1 = *p2;
*p2 = *p;
}
解答:在swap函数中,p是个野指针,可能指向系统区,导致程序运行的崩溃。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。故而,程序应改为:
swap(int* p1,int* p2)
{
int p;
p = *p1;
*p1 = *p2;
*p2 = p;
}
13、void main()
{
char aa[10];
printf(“%d”,strlen(aa));
} 结果是是多少?
sizeof()和初不初始化,没有关系,
strlen()和初始化有关,打印结果值未知
/----------------------------------------------------------------------------------------------------------------------------/
17、wap( int*p1,int* p2 )找出错误
{
int * p; // p 为野指针,应该null一下
*p = *p1;
*p1 = *p2;
*p2 = *p;
}
/----------------------------------------------------------------------------------------------------------------------------/
20、要对绝对地址0x100000赋值,我们可以用
(unsignedint*)0x100000 = 1234;
那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做?
*((void (*)())0x100000 ) ( );
void (*)()是函数指针,void是返回类型,()是表示参数类型也是void
首先要将0x100000强制转换成函数指针,即:(void (*)())0x100000然后再调用它:
/----------------------------------------------------------------------------------------------------------------------------/
27、关键字volatile有什么含意? 并给出三个不同的例子。
优化器在用到这个变量时必须每次都小心地重新读取这个变量在内存中的值,而不是使用保存在寄存器里的备份。
下面是volatile变量的几个例子:
1). 并行设备的硬件寄存器(如:状态寄存器)
2). 一个中断服务子程序中会访问到的非自动变量(non-automatic variables)
3). 多线程应用中被几个任务共享的变量
/----------------------------------------------------------------------------------------------------------------------------/
40、带参宏与带参函数的区别(至少说出5点)?
1、宏会在编译器在对源代码进行编译的时候进行简单替换,不会进行任何逻辑检测,即简单代码复制而已。
2、宏进行定义时不会考虑参数的类型。
3、参数宏的使用会使具有同一作用的代码块在目标文件中存在多个副本,即会增长目标文件的大小。
4、参数宏的运行速度会比函数快,因为不需要参数压栈/出栈操作。函数的调用会牵扯到参数的传递,压栈/出栈操作,速度相对较慢。
6、函数只在目标文件中存在一处,比较节省程序空间。
8、函数的参数存在传值和传地址(指针)的问题,参数宏不存在。
/----------------------------------------------------------------------------------------------------------/
71、一语句实现x是否为2 的若干次幂的判断。直接a&(a-1)就可以了
比如8&7 = 1000b&111b = 0
20、解释堆和栈的区别
答:堆(heap)和栈(stack)的区别
(1)申请方式
stack:由系统自动分配。例如,声明在函数中一个局部变量int b;系统自动在栈中为b开辟空间
heap:需要程序员自己申请,并指明大小,在c中malloc函数
如p1=(char*)malloc(10);
在C++中用new运算符
如p2=(char*)malloc(10);
但是注意p1、p2本身是在栈中的。
(2)申请后系统的响应
栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。
堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,
会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。
(3)申请大小的限制
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
(4)申请效率的比较:
栈:由系统自动分配,速度较快。但程序员是无法控制的。
堆:是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.
另外,在WINDOWS下,最好的方式是用Virtual Alloc分配内存,他不是在堆,也不是在栈,而是直接在进程的地址空间中保留一块内存,虽然用起来最不方便。但是速度快,也最灵活。
(5)堆和栈中的存储内容
栈:在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。
当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。
堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容由程序员安排。
(6)存取效率的比较
char s1[]="aaaaaaaaaaaaaaa";
char *s2="bbbbbbbbbbbbbbbbb";
aaaaaaaaaaa是在运行时刻赋值的;
而bbbbbbbbbbb是在编译时就确定的;
但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。
这是一个前辈写的,非常详细
//main.cpp
int a=0; //全局初始化区
char *p1; //全局未初始化区
main()
{
intb;栈
char s[]="abc"; //栈
char *p2; //栈
char *p3="123456"; //123456\0在常量区,p3在栈上。
static int c=0; //全局(静态)初始化区
p1 = (char*)malloc(10);
p2 = (char*)malloc(20); //分配得来得10和20字节的区域就在堆区。
strcpy(p1,"123456"); //123456\0放在常量区,编译器可能会将它与p3所向"123456"优化成一个地方。
}
15、全局变量可不可以定义在可被多个.C文件包含的头文件中?为什么?
答 、可以,在不同的C文件中以static形式来声明同名全局变量。
可以在不同的C文件中声明同名的全局变量,前提是其中只能有一个C文件中对此变量赋初值,此时连接不会出错。
11、队列和栈有什么区别?
答:队列先进先出,栈后进先出
8、堆栈溢出一般是由什么原因导致的?
答 :1.没有回收垃圾资源
2.层次太深的递归调用
6、全局变量和局部变量在内存中是否有区别?如果有,是什么区别?
答 :全局变量储存在静态数据区,局部变量在堆栈中。
4、#include<file.h> 与 #include "file.h"的区别?
答:前者是从Standard Library的路径寻找和引用file.h,而后者是从当前工作路径搜寻并引用file.h。
72、下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(isr),请评论一下这段代码的。
__interruptdouble compute_area (double radius)
{
double area = pi* radius * radius;
printf("area = %f", area);
return area;
}
1). isr 不能返回一个值。
2).isr 不能传递参数。
3). 在许多的处理器/编译器中,浮点一般都是不可重入的。
/----------------------------------------------------------------------------------------------------------------------------/
77、写出二分查找的代码。
int b inary_search(int* arr, int k ey, int n)
{
int low = 0;
int h igh = n -1 ;
int m id;
while (low <=high)
{
mid = (high +low) / 2;
if (arr[mid]> k)
high = mid -1 ;
else if(arr[mid] < k)
low = mid + 1;
else
return mid;
}
return -1;
}
/----------------------------------------------------------------------------------------------------------------------------/
78、请编写一个c 函数,该函数给出一个字节中被置1 的位的个数。
unsigned int testasone0(char log)
{
int i;
unsigned intnum=0, val;
for(i=0; i<8;i++)
{
va l = log >> i; // 移位
val & =0x01; // 与1 相与
if(val)
num++;
}
return num;
}
/----------------------------------------------------------------------------------------------------------------------------/
80、请编写一个c 函数,该函数将给定的一个整数转换成字符串。
voidinttocharchange(int num, char* pval)
{
charstrval[100];
int i , j;
int val0 = 0;
int val1 = 0;
val0 = num;
for(i=0;i<100; i++)
{
val1 = val0 %10; //取余
val0 = val0 /10; // 取整
strval[i] = val1+ 48; // ASCII 码48~57为0到9十个阿拉伯数字
if(val0 < 10)
{
i++;
strval[i] = val0+ 48;
break;
}
}
for(j=0; j<=i;j++) // 倒置
pval[j] =strval[i-j];
pval[j] = '\0';
}
/----------------------------------------------------------------------------------------------------------------------------/
82、请编写一个c 函数,该函数将一个字符串逆序。
voidantitonevalue(cha r* father, char* child)
{
int i ;
charsource[100];
int j = 0;
while(father[j])//放入source ,[j] 为长度
{
source[j] =father[j];
j++;
if(j > 99) //判断参数是否大于数组
return;
}
source[j] ='\0';
for(i=0; i<j;i++)
child[i] =source[j-i-1]; // 反序
child[i] = '\0';
}
/----------------------------------------------------------------------------------------------------------------------------/
83、请编写一个c 函数,该函数在给定的内存区域搜
int search(char* source, intn , char ch) // 起始地址,搜索长度,目标字符
{
int i;
for(i=0; i<n&& *(source+i) != ch; ++i);
return i;
}
/----------------------------------------------------------------------------------------------------------------------------/
4、该函数在一个字符串中找到由同一字符组成的可能的最长的子字符串。
int childstring(char*p) // 自己写
{
char *q =p;
int stringlen=0,i=0,j=1,len=0,maxlen=1;
while(*q!=’\0’) //不能用strlen, 求得长度stringlen
{
stringlen++;
q++;
}
while(i< string len )
{
if(*(p+i)==*(p+j)&& j< stringlen )
{
len++; // 统计子串长度
i++;
j++;
}
else
{
if(len>maxlen) // 统计最大子串长度
{
maxlen=len+1;
len=0;
}
else
len=0;
i++;
j++;
}
}
return maxlen;
}
/----------------------------------------------------------------------------------------------------------------------------/
85、怎么判断链表中是否有环?
答:用两个指针来遍历这个单向链表,第一个指针p1,每次走一步;第二个指针p2,每次走两步;当p2 指针追上p1的时候,就表明链表当中有环路了。
inttestlinkring(link *head)
{
link*t1=head,*t2=head;
while(t1->next && t2->next)
{
t1 =t1->next;
if (null == (t2= t2->next->next))
return 0; // 无环
if (t1 == t2)
return 1;
}
return 0;
}
/----------------------------------------------------------------------------------------------------------------------------/
87、实现双向链表删除一个节点p,在节点p 后插入一个节点,写出这两个函数。
statuslistdelete_dul(dulinklist &l,inti,ele mtype &e) // 删除操作
{
if(!(p=g etelemp_dul(l,i))) return error;
e=p->data;
p->prior->next=p->next;
p->next->prior=p->pror;
free(p);
return ok;
}
statuslistinsert_dul(dulinklist &l,inti,elemtype &e) // 插入操作
{
if(!(p=getelemp_dul(l,i)))
return error;
if(!(s=(dulinklist)malloc(sizeof(dulnode))))
return error;
s->data=e;
s->pri or =p;
p-> next-> prior =s;
p->next=s;
s->next=p->next->next;
return ok;
}
/----------------------------------------------------------------------------------------------------------------------------/
88、把一个链表反向。
从第一个元素开始,ps指向他,将他(ps)指向头节点(ps->next= head) ,将ps设为头节点(head = ps; )操作下一个元素(ps= pe->next;)等于是依次将每个元素翻到原头节点前面。
voidreverse(test* head)
{
test* pe = head;
test* ps =head->next;
while(ps)
{
pe->next =ps->next;
ps->next =head;
head = ps;
ps = pe->next;
}
}
/----------------------------------------------------------------------------------------------------------------------------/
89、将二维数组行列元素互换,存到另一个数组中。
#include<stdio.h>
main()
{ int a [2][3]={{1,2,3},{4,5,6}};
int b[3][2],i,j;
printf("arraya :\n");
for(i=0;i<=1;i++)
{ for(j=0;j<=2;j++)
{ printf("%5d",a[i][j]);
b[j][i]=a[i][j];
}
printf("\n");
}
printf("arrayb :\n");
for(i=0;i<=2;i++)
{ for(j=0;j<=1;j++)
printf("%5d",b[i][j]);
printf("\n");
}
}
/----------------------------------------------------------------------------------------------------------------------------/
90、输入一行字符,统计其中有多少个单词。
#include<stdio.h>
main()
{
char str ing[81];
inti,num=0,word=0;
char c;
gets(string);
for(i=0;(c=string[i])!='\0';i++)
if(c==' ')
word=0;
else if(word==0)
{
word=1; num++; }
printf("thereare %d word s in the line\n",num);
}
/----------------------------------------------------------------------------------------------------------------------------/
91、写一个内存拷贝函数,不用任何库函数.就是前些时候本版讨论的那个问题。
void*memcpy(void* pvto, const void* pvfrom, size_t size)
{
assert((pvto !=null) && (pvfrom ! = null));
byte* pbto=pvto;
byte* pbfrom =pbfrom;
while (size--> 0)
{
*pbto++ =*pbfrom++;
}
return pvto;
}
/----------------------------------------------------------------------------------------------------------------------------/
92、有1、2、3 、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?
for(i=1;i<5;i++)/* 以下为三重循环*/
for(j=1;j<5;j++)
for(k=1;k<5;k++)
{
if(i!=k&&i!=j&&j!=k) /* 确保i、j、k三位互不相同*/
printf("%d,%d,%d\n",i,j,k);
}
/----------------------------------------------------------------------------------------------------------------------------/
93、取一个整数a从右端开始的4~7位。
main()
{
unsigneda,b,c,d;
scanf("%o",&a);
b=a>>4;
c=~(~0<<4);
d=b&c;
printf("%o\n%o\n",a,d);
}
/----------------------------------------------------------------------------------------------------------------------------/
94、打印出杨辉三角形(要求打印出10行如下图)。
main()
{
int i,j;
int a [10][10];
printf("\n");
for(i=0;i<10;i++)
{
a[i][0]=1;
a[i][i]=1;
}
for(i=2;i<10;i++)
for(j=1;j<i;j++)
a[i][j]=a[i-1][j-1]+a[i-1][j];
for(i=0;i<10;i++)
{
for(j=0;j<=i;j++)
printf("%5d",a[i][j]);
printf("\n");
}
getch();
}
96、写一个函数,求一个字符串的长度,在main函数中输入字符串,并输出其长度。
char *s tr[20];
int length(char*p)
{
char *p=null; int n =0;
while(*p!='\0')
{
n++; p++;
}
return n;
}
97、809*??=800*??+9*??+1 其中??代表的两位数,8*?? 的结果为两位数,9*??的结果为3位数。求??代表的两位数,及809*??后的结果。
output(longb,long i)
{
printf("\n%ld/%ld=809*%ld+%ld",b,i,i,b%i);
}
main()
{
long int a ,b,i;
a=809;
for(i=10;i<100;i++)
{
b=i*a+1;
if(b>=1000&&b<=10000&&8*i<100&&9*i>=100)
output(b,i);
}
getch();
}
/----------------------------------------------------------------------------------------------------------------------------/
98、某个公司采用公用电话传递数据,数据是四位的整数,在传递过程中是加密的,加密规则如下:每位数字都加上5, 然后用和除以10的余数代替该数字,再将第一位和第四位交换,第二位和第三位交换。
main()
{
int a,i,aa[4],t;
scanf( " %d " ,&a) ;
aa[0]=a %10;
aa[1]=a %100/10;
aa[2]=a%1000/100;
aa[3]=a /1000;
for(i=0 ;i<=3 ;i++)
{
aa [i]+=5;
aa[i] %=10;
}
for(i=0;i<=3/2;i++)
{
t=aa[i];
aa[i]= aa[3- i];
aa[3- i]= t ;
}
for(i=3;i>=0;i--)
prin tf("%d ", a [i]);
getch();
}
/----------------------------------------------------------------------------------------------------------------------------/
99、计算字符串中子串出现的次数。
main()
{
charstr1[20],str2[20],*p1,*p2;
int sum=0;
printf("pleaseinput two strings\n");
scanf("%s%s",str1,str2);
p1=str1;p2=str2;
while(*p1!='\0')
{
if(*p1==*p2)
{
while(*p1==*p2&&*p2!='\0')
{
p1++;
p2++;
}
}
else
p1++;
if(*p2=='\0')
sum++;
p2=str2;
}
printf("%d",sum);
getch();
}
/----------------------------------------------------------------------------------------------------------------------------/
100 、有两个磁盘文件a和b, 各存放一行字母,要求把这两个文件中的信息合并(按字母顺序排列),输出到一个新文件c 中。
main()
{
file *fp;
in t i,j,n,ni;
charc[160],t,ch;
if((fp=fopen("a","r"))==null)
{
printf("filea cannot be opened\n");exit(0);
}
printf("\nacontents are :\n");
for(i=0;(ch=fgetc(fp))!=eof; i++)
{
c[i]=ch;putchar(c[i]);
}
fclose(fp);
ni=i;
if((fp=fopen("b","r"))==null)
{
printf("fileb cannot be opened\n");exit(0);
}
printf("\nbcontents are :\n");
for(i=0;(ch=fgetc(fp))!=eof; i++)
{
c[i]=ch;putchar(c[i]);
}
fclose(fp);
n=i;
for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
if(c[i]>c[j]){t=c[i];c[i]=c[j];c[j]=t;}
printf("\ncfile is:\n");
fp =fopen("c","w");
for(i=0;i<n;i++){putc(c[i],fp);putchar(c[i]);}
fclose(fp);
getch();
}
/----------------------------------------------------------------------------------------------------------------------------/
找出n个数中r个数的组合(递归)
/----------------------------------------------------------------------------------------------------------------------------/
1. main函数执行完毕后,是否可能会再执行一段代码?
答:是。main函数执行完毕后还可以执行代码,它可以通过atexit()函数来注册回调函数,回调函数的形式是void (*function)(void)。atexit()声明在stdlib.h中。具体可以参考:c语言基础函数——exit()和atexit()
/----------------------------------------------------------------------------------------------------------------------------/
4. 变量的定义和声明有什么区别?
答:定义包含为变量分配存储空间和指定初始值;而声明仅用于向编译器告知变量的名称和类型。
/----------------------------------------------------------------------------------------------------------------------------/
10. 写一个函数,判断一个int型的整数是否是2的幂,即是否可以表示成2^X的形式(不可以用循环)。
#defineTRUE 1
#defineFALSE 0
intIsBinrayPower(int num) {
return (num & (num - 1)) ? FALSE :TRUE;
}
/----------------------------------------------------------------------------------------------------------------------------/
11. int (*(*f)(int, int))(int)表示什么含义?
答:f是一个函数指针,它的参数是(int,int),返回值是一个函数指针形式是int *()(int))。虽然看上去很复杂,但是在实际的应用中确实也有类似的,比如在signal.h中就有这样的定义:
void (*signal(int, void (*)(int)))(int);
/----------------------------------------------------------------------------------------------------------------------------/
14. static全局变量与普通全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
答:
1. static全局变量和普通的全局变量,在内存中的位置是一样的,区别在于static全局变量只在当前的文件有效,而普通全局变量在所有的文件中都有效。
2. static局部变量和普通局部变量在内存中的存储就不一样了,使得普通全局变量每次都会重新初始化,而static局部变量只会初始化一次,之后就沿用上一次的值。
3. static函数和普通函数的差别是,static函数只在当前文件有效,而普通函数默认是extern的,因此在其它文件也有效。
/----------------------------------------------------------------------------------------------------------------------------/
15. 下面程序的打印结果是什么?
#include<stdio.h>
main()
{
char *a = "hello";
char *b = "hello";
if (a == b)
printf("YES");
else
printf("NO");
}
答:粗的来看应该是打印NO,但是因为hello是存放在静态存储区的,编译器有可能进行优化,将a和b指向同一个hello,此时a==b。在vs2015上的测试结果也是YES
/------------------------------------------------------------------------------------------------------------------------------/
a+++b实际上是(a++)+b;还有就是后++发生在+=等操作之后.
/------------------------------------------------------------------------------------------------------------------------------/
答:需要记住的是,小端模式下低字节内存放低位数据,即,对于int类型的数据0x12345678,最低地址放的是0x78。这个可以作为编程的依据:
#include<stdio.h>
intmain(void)
{
unsigned int a = 0x12345678;
if (*((unsigned char *)&a) == 0x78){
printf("little end\n");
}
else {
printf("big end");
}
return 0;
}
/------------------------------------------------------------------------------------------------------------------------------/
a += (a++) => a+a;a++
a += (++a) => ++a;a+a
(a++) += a;//错误 a++和++a不能作为左值。
/------------------------------------------------------------------------------------------------------------------------------/
2. 给一个字符串、例如 “ababc”要求返回“ab”,因为“ab”连续重复出现且最长。用C/C++语言写一函数完成该算法,给出复杂度。
char * src ="I am a abc and he is not abc";
charresult[100];
int max =GetSubStr(src, result);
intGetSubStr(char * src, char * sub) {
int length; //原始字符串的长度
int max; //最大子字符串的长度
int tmp_max; //最大子字符串的长度,临时,比较时使用
int index;
char *p, *q; //用来遍历字符串的两个指针
char *k; //指向最终的子字符串的起始位置
length = strlen(src);
max = 0;
p = src;
k = src;
//从第一个字符开始遍历
while (*p != '\0') {
for (q = p + 1; *q != '\0'; q++) { //与前一个字符比较
tmp_max = 0; //如果相等了,表示有可能出现最大连续字符串了,之后就要以p和q为起始,比较两者之后的字符串是否相等
if (*p == *q) {
//起始字符相等后,就开始比较两个字符串
for (index = 0; index < q -p; index++) {
if (*(p + index) == *(q +index)) {
tmp_max++;
} else {
if (tmp_max > max){
max = tmp_max;
k = p;
}
break;
}
}
}
}
p++;
}
strncpy(sub, k, max); //最后需要手动加上一个\0
sub[max] = '\0';
return max;
}
/------------------------------------------------------------------------------------------------------------------------------/
一般将数据结构分为两大类型:线性结构与非线性结构。线性表、栈与队列、线性链表都是线性结构,而二叉树是非线性结构
/------------------------------------------------------------------------------------------------------------------------------/
#include<stdio.h>
#include<string.h>
void GetMemory(char*p)
{
p = (char *)malloc(100);
}
voidTest(void) {
char *str = NULL; GetMemory(str);
strcpy(str, "hello world");
printf(str);
} 答:程序崩溃。 因为GetMemory并不能传递动态内存,Test函数中的 str一直都是 NULL。 strcpy(str, "hello world");将使程序崩溃。
/------------------------------------------------------------------------------------------------------------------------------/
char*GetMemory(void) {
char p[] = "hello world";
return p;
}
void Test(void) {
char *str = NULL;
str =GetMemory();
printf(str);
}
答:可能是乱码。 因为GetMemory返回的是指向“栈内存”的指针,该指针的地址不是 NULL,但其原现的内容已经被清除,新内容不可知。
/------------------------------------------------------------------------------------------------------------------------------/
voidGetMemory2(char **p, int num) {
*p = (char *)malloc(num);
}
void Test(void){
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
(1)能够输出hello (2)内存泄漏
void Test(void){
char *str = (char *) malloc(100);
strcpy(str, “hello”);
free(str);
if(str != NULL) {
strcpy(str, “world”);
printf(str);
}
} 请问运行Test函数会有什么样的结果? 答:篡改动态内存区的内容,后果难以预料,非常危险。 因为free(str);之后,str成为野指针, if(str!= NULL)语句不起作用
/----------------------------------------------------------------------------------------------------------------------------/
strcpy能把strSrc的内容复制到strDest,为什么还要char * 类型的返回值? 答:为了实现链式表达式
/----------------------------------------------------------------------------------------------------------------------------/
第2题: 设有文件a.file, 请写出程序在文件的开头插入字符串
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<math.h>
void main()
{
FILE *fp; /*定义一个文件指针*/
char *p="i love you ";
fp=fopen("1.txt","a+");
fseek(fp, 0, SEEK_SET); //把输入定位在文件开头
fwrite(p, strlen(p), 1, fp);
fclose(fp);
}
strlen()用来计算指定的字符串s 的长度,不包括结束字符"\0"
/----------------------------------------------------------------------------------------------------------------------------/
条件编译命令:
#ifdef 标识符
#else
#endif
/----------------------------------------------------------------------------------------------------------------------------/
由于register变量使用的是硬件CPU中的寄存器,寄存器变量无地址,所以不能使用取地址运算符"&"求寄存器变量的地址。
/----------------------------------------------------------------------------------------------------------------------------/
c语言中变量分为四类,分别是
1.auto 自动变量
2.static 静态存贮分配变量(又分为内部静态和外部静态)
3.extern 全程变量(用于外部变量说明)
4.register 寄存器变量(分配在硬件寄存器中)四大类,所有变量必须先说明(定义),后使用。
变量的定义用于为变量分配存储空间,还可以为变量指定初始值。在一个程序中,变量有且仅有一个定义。
声明用于向程序表明变量的类型和名字,定义包括声明:当定义变量时声明了它的类型和名字。可以通过使用extern关键字声明变量名而不定义它。不定义变量的声明包括对象名、对象类型前的关键字extern。
/----------------------------------------------------------------------------------------------------------------------------/
edp就是栈中间的一个变量,这个变量所在的位置位于全局变量和局部变量之间
将一个字符串中的重复的字母的数量写在该字母的后面
比如
abcdddefgggggjkl
到
abcd3efg5j
代码如下
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
void main()
{
int i;
int j;
int num=2;
int l=0;
char *a="abcdddefgggggjkl";
char b[20];
for(i=0;i<strlen(a);i++)
{
if(a[i]!=a[i+1])
{
b[l]=a[i];
l++;
}else{
b[l]=a[i];
l++;
for(j=i+1;j<strlen(a);j++)
{
if(a[j]==a[j+1])
{
num++;
}else
{
b[l]=num+'0';
num=2;
l++;
i=j;
break;
}
}
}
}
b[l]='\0';
i=0;
while(i<10)
{
printf("%c",b[i]);
i++;
}
}