嵌入式C经典笔试题roinxxX

这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用:

答、1)引用必须被初始化,指针不必。

2)引用初始化以后不能被改变,指针可以改变所指的对象。

3)不存在指向空值的引用,但是存在指向空值的指针。

指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。

流操作符<<和>>、赋值操作符=的返回值、拷贝构造函数的参数、赋值操作符=的参数、其它情况都推荐使用引用

答:防止该头文件被重复引用。

答:前者是从StandardLibrary标准库的路径寻找和引用file.h,而后者是从当前工作路径搜寻并引用file.h。

答:全局变量储存在静态数据区,局部变量在堆栈中。

答:左右子树都是平衡二叉树且左右子树的深度差值的绝对值不大于1。

答:1.没有回收垃圾资源

2.层次太深的递归调用

答:O(n^2)

答:constructor构造函数

答:队列先进先出,栈后进先出

答:switch的参数不能为实型(floatdouble之类的)。

答:能,局部会屏蔽全局。要用全局变量,需要使用"::"

局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内

答、和while(1)相同,无限循环。

17、do……while和while……do有什么区别?

答、前一个循环一遍再判断,后一个判断以后再循环。

static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?

答、全局变量(外部变量)的说明之前再冠以static就构成了静态的全局变量。全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。

从以上分析可以看出,把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。

static函数与普通函数作用域不同。仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件

static全局变量与普通的全局变量有什么区别:static全局变量只初使化一次,防止在其他文件单元中被引用;

static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值;

static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝

19、程序的内存分配答:一个由c/C++编译的程序占用的内存分为以下几个部分1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。2、堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表3、全局区(静态区)(static)—全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。4、文字常量区—常量字符串就是放在这里的。程序结束后由系统释放。5、程序代码区—存放函数体的二进制代码

例子程序这是一个前辈写的,非常详细//main.cppinta=0;//全局初始化区char*p1;//全局未初始化区main(){intb;栈chars[]="abc";//栈char*p2;//栈char*p3="123456";//123456\0在常量区,p3在栈上。staticintc=0;//全局(静态)初始化区p1=(char*)malloc(10);p2=(char*)malloc(20);//分配得来得10和20字节的区域就在堆区。strcpy(p1,"123456");//123456\0放在常量区,编译器可能会将它与p3所向"123456"优化成一个地方。}

答:堆(heap)和栈(stack)的区别

(2)申请后系统的响应栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

(3)申请大小的限制栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

(4)申请效率的比较:栈:由系统自动分配,速度较快。但程序员是无法控制的。堆:是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存,他不是在堆,也不是在栈,而是直接在进程的地址空间中保留一块内存,虽然用起来最不方便。但是速度快,也最灵活。

(5)堆和栈中的存储内容栈:在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容由程序员安排。

(6)存取效率的比较

chars1[]="aaaaaaaaaaaaaaa";char*s2="bbbbbbbbbbbbbbbbb";aaaaaaaaaaa是在运行时刻赋值的;而bbbbbbbbbbb是在编译时就确定的;但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。比如:#includevoidmain(){chara=1;charc[]="1234567890";char*p="1234567890";a=c[1];a=p[1];return;}对应的汇编代码10:a=c[1];004010678A4DF1movcl,byteptr[ebp-0Fh]0040106A884DFCmovbyteptr[ebp-4],cl11:a=p[1];0040106D8B55ECmovedx,dwordptr[ebp-14h]004010708A4201moval,byteptr[edx+1]004010738845FCmovbyteptr[ebp-4],al第一种在读取时直接就把字符串中的元素读到寄存器cl中,而第二种则要先把指针值读到edx中,在根据edx读取字符,显然慢了。

答:预编译又称为预处理,是做些代码文本的替换工作。处理#开头的指令,比如拷贝#include包含的文件代码,#define宏定义的替换,条件编译等,就是为编译做的预备工作的阶段,主要处理#开始的预编译指令,预编译指令指示了在程序正式编译前就由编译器进行的操作,可以放在程序中的任何位置。

c编译系统在对程序进行通常的编译之前,先进行预处理。c提供的预处理功能主要有以下三种:1)宏定义2)文件包含3)条件编译

1、总是使用不经常改动的大型代码体。

2、程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种情况下,可以将所有包含文件预编译为一个预编译头。

constinta;

intconsta;

constint*a;

int*consta;

intconst*aconst;

前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。如果应试者能正确回答这些问题,那么他就给我留下了一个好印象。顺带提一句,也许你可能会问,即使不用关键字const,也还是能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢?我也如下的几下理由:

2).通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。

3).合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现

答:一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:

1).并行设备的硬件寄存器(如:状态寄存器)

2).一个中断服务子程序中会访问到的非自动变量(Non-automaticvariables)

3).多线程应用中被几个任务共享的变量

回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。

假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。

1).一个参数既可以是const还可以是volatile吗?解释为什么。

2).一个指针可以是volatile吗?解释为什么。

3).下面的函数有什么错误:

intsquare(volatileint*ptr)

{

return*ptr**ptr;

}

下面是答案:

1).是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。

2).是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。

3).这段代码的有个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:

inta,b;

a=*ptr;

b=*ptr;

returna*b;

由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:

longsquare(volatileint*ptr)

inta;

returna*a;

答:按照数据结构类型的不同,将数据模型划分为层次模型、网状模型和关系模型。

答:(1).结构和联合都是由多个不同的数据类型成员组成,但在任何同一时刻,联合中只存放了一个被选中的成员(所有成员共用一块地址空间),而结构的所有成员都存在(不同成员的存放地址不同)。(2).对于联合的不同成员赋值,将会对其它成员重写,原来成员的值就不存在了,而对于结构的不同成员赋值是互不影响的

答:1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。2)在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集。3)从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由程序员决定,使用非常灵活,但问题也最多

答:Const作用:定义常量、修饰函数参数、修饰函数返回值三个作用。被Const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。

1)const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误。2)有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试。

答:数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。指针可以随时指向任意类型的内存块。(1)修改内容上的差别chara[]=“hello”;a[0]=‘X’;char*p=“world”;//注意p指向常量字符串p[0]=‘X’;//编译器不能发现该错误,运行时错误(2)用运算符sizeof可以计算出数组的容量(字节数)。sizeof(p),p为指针得到的是一个指针变量的字节数,而不是p所指的内存容量。C++/C语言没有办法知道指针所指的内存容量,除非在申请内存时记住它。注意当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。chara[]="helloworld";char*p=a;cout<

答:BOOL:if(!a)orif(a)int:if(a==0)float:constEXPRESSIONEXP=0.000001if(a-EXP)pointer:if(a!=NULL)orif(a==NULL)

答:#ifdef__cpluspluscout<<"c++";#elsecout<<"c";#endif

答:带参宏函数

参数类型没有参数类型问题定义实参、形参类型

处理过程不分配内存分配内存

程序长度变长不变

答、设2个栈为A,B,一开始均为空.

入队:

将新元素push入栈A;

出队:

(1)判断栈B是否为空;

(2)如果不为空,则将栈A中所有元素依次pop出并push到栈B;

(3)将栈B的栈顶元素pop出;

这样实现的队列入队和出队的平摊复杂度都还是O(1),比上面的几种方法要好

答:这个问题用几个解决方案。我首选的方案是:

while(1)

一些程序员更喜欢如下方案:

for(;;)

这个实现方式让我为难,因为这个语法没有确切表达到底怎么回事。如果一个应试者给出这个作为方案,我将用这个作为一个机会去探究他们这样做的

基本原理。如果他们的基本答案是:“我被教着这样做,但从没有想到过为什么。”这会给我留下一个坏印象。

第三个方案是用goto

Loop:

...

gotoLoop;

应试者如给出上面的方案,这说明或者他是一个汇编语言程序员(这也许是好事)或者他是一个想进入新领域的BASIC/FORTRAN程序员。

答:嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit3,第二个清除a的bit3。在以上两个操作中,要保持其它位不变。对这个问题有三种基本的反应1)不知道如何下手。该被面者从没做过任何嵌入式系统的工作。2)用bitfields(字段)。Bitfields是被扔到C语言死角的东西,它保证你的代码在不同编译器之间是不可移植的,同时也保证了的你的代码是不可重用的。我最近不幸看到Infineon为其较复杂的通信芯片写的驱动程序,它用到了bitfields因此完全对我无用,因为我的编译器用其它的方式来实现bitfields的。从道德讲:永远不要让一个非嵌入式的家伙粘实际硬件的边。3)用#defines和bitmasks操作。这是一个有极高可移植性的方法,是应该被用到的方法。最佳的解决方案如下:#defineBIT3(0x1<<3)staticinta;voidset_bit3(void){a|=BIT3;}voidclear_bit3(void){a&=~BIT3;}一些人喜欢为设置和清除值而定义一个掩码同时定义一些说明常数,这也是可以接受的。我希望看到几个要点:说明常数、|=和&=~操作。

答:嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换(typecast)为一指针是合法的。这一问题的实现方式随着个人风格不同而不同。典型的类似代码如下:int*ptr;ptr=(int*)0x67a9;//先取出地址de值付给指针*ptr=0xaa66;//再把指针解引用Amoreobscureapproachis:一个较晦涩的方法是:*(int*const)(0x67a9)=0xaa55;即使你的品味更接近第二种方案,但我建议你在面试时使用第一种方案。

2)ISR不能传递参数。3)在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的。4)与第三点一脉相承,printf()经常有重入和性能上的问题。如果你丢掉了第三和第四点,我不会太为难你的。不用说,如果你能得到后两点,那么你的被雇用前景越来越光明了。

a)一个整型数(Aninteger)

b)一个指向整型数的指针(Apointertoaninteger)

c)一个指向指针的的指针,它指向的指针是指向一个整型数(Apointertoapointertoaninteger)

d)一个有10个整型数的数组(Anarrayof10integers)

e)一个有10个指针的数组,该指针是指向一个整型数的(Anarrayof10pointerstointegers)

f)一个指向有10个整型数数组的指针(Apointertoanarrayof10integers)

g)一个指向函数的指针,该函数有一个整型参数并返回一个整型数(Apointertoafunctionthattakesanintegerasanargumentandreturnsaninteger)

h)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数(Anarrayoftenpointerstofunctionsthattakeaninteger

argumentandreturnaninteger)

答案是:

a)inta;//Aninteger

b)int*a;//Apointertoaninteger

c)int**a;//Apointertoapointertoaninteger

d)inta[10];//Anarrayof10integers

e)int*a[10];//Anarrayof10pointerstointegers

f)int(*a)[10];//Apointertoanarrayof10integers

g)int(*a)(int);//Apointertoafunctionathattakesanintegerargumentandreturnsaninteger

h)int(*a[10])(int);//Anarrayof10pointerstofunctionsthattakeanintegerargumentandreturnaninteger

答:局部变量:在一个函数内部定义的变量是内部变量,它只在本函数范围内有效,也就是说只有在本函数内才能使用它们,在此函数以外时不能使用这些变量的,它们称为局部变量;说明:1.主函数main中定义的变量也只在主函数中有效,而不因为在主函数中定义而在整个文件或程序中有效2.不同函数中可以使用名字相同的变量,它们代表不同的对象,互不干扰3.形式参数也使局部变量4.在一个函数内部,可以在复合语句中定义变量,这些变量只在本符合语句中有效全局变量:在函数外定义的变量是外部变量,外部变量是全局变量,全局变量可以为本文件中其它函数所共用,它的有效范围从定义变量的位置开始到本源文件结束;说明:1.设全局变量的作用:增加了函数间数据联系的渠道2.建议不再必要的时候不要使用全局变量,因为a.全局变量在程序的全部执行过程中都占用存储单元;

b.它使函数的通用性降低了c.使用全局变量过多,会降低程序的清晰性3.如果外部变量在文件开头定义,则在整个文件范围内都可以使用该外部变量,如果不再文件开头定义,按上面规定作用范围只限于定义点到文件终了。如果在定义点之前的函数想引用该外部变量,则应该在该函数中用关键字extern作外部变量说明4.如果在同一个源文件中,外部变量与局部变量同名,则在局部变量的作用范围内,外部变量不起作用;静态变量:在程序运行期间分配固定的存储空间的变量,叫做静态变量

答:交换两个参数值的宏定义为:.#defineSWAP(a,b)\

(a)=(a)+(b);\

(b)=(a)-(b);\

(a)=(a)-(b);

输入两个参数,输出较小的一个:#defineMIN(A,B)((A)<(B))(A):(B))

表明1年中有多少秒(忽略闰年问题):#defineSECONDS_PER_YEAR(60*60*24*365)UL

#defineDOUBLE(x)x+x与#defineDOUBLE(x)((x)+(x))

i=5*DOUBLE(5);i为30i=5*DOUBLE(5);i为50

已知一个数组table,用一个宏定义,求出数据的元素个数

#defineNTBL

#defineNTBL(sizeof(table)/sizeof(table[0]))

42、A.c和B.c两个c文件中使用了两个相同名字的static变量,编译的时候会不会有问题这两个static变量会保存到哪里(栈还是堆或者其他的)

答:static的全局变量,表明这个变量仅在本模块中有意义,不会影响其他模块。

他们都放在数据区,但是编译器对他们的命名是不同的。

如果要使变量在其他模块也有意义的话,需要使用extern关键字。

答:将这个指针指向的next节点值copy到本节点,将next指向next->next,并随后删除原next指向的节点。

%d代表十进制

%o代表八进制

%x代表十六进制

%u无符号十进制数

%e以科学记数法表示

%#o代表带前缀o的八进制

%#x代表待前缀ox的十六进制

\0oo八进制值(o表示一个八进制数字)

\xhh十六进制值(h表示一个十六进制数字)

16进制0x234这样的(如24就是0x018,凡是以0X或0x开头的数字序列)8进制01111这样的(凡是16进制0x234这样的(如24就是0x018,凡是以0X或0x开头的数字序列)8进制01111这样的(凡是以0开头的数字序列)以0开头的数字序列)

八进制数octalnumber二进制数binarynumber

十进制数DecimalNumber

十六进制数hexadecimalnumber

1、下面的代码输出是什么,为什么?voidfoo(void){unsignedinta=6;intb=-20;(a+b>6)puts(">6"):puts("<=6");}这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出是">6"。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。如果你答错了这个问题,你也就到了得不到这份工作的边缘。2、评价下面的代码片断:unsignedintzero=0;unsignedintcompzero=0xFFFF;/*1'scomplementofzero*/对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下:unsignedintcompzero=~0;这一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的经验里,好的嵌入式程序员非常准确地明白硬件的细节和它的局限,然而PC机程序往往把硬件作为一个无法避免的烦恼。

3、C语言同意一些令人震惊的结构,下面的结构是合法的吗,如果是它做些什么?inta=5,b=7,c;c=a+++b;因此,上面的代码被处理成:c=a+++b;因此,这段代码持行后a=6,b=7,c=12。如果你知道答案,或猜出正确答案,做得好。如果你不知道答案,我也不把这个当作问题。我发现这个问题的最大好处是这是一个关于代码编写风格,代码的可读性,代码的可修改性的好的话题。

typedefunion{longi;intk[5];charc;}DATE;

structdata{intcat;DATEcow;doubledog;}too;

DATEmax;

则语句printf("%d",sizeof(structdate)+sizeof(max));的执行结果是?

答、结果是:52。DATE是一个union,变量公用空间.里面最大的变量类型是int[5],占用20个字节.所以它的大小是20

data是一个struct,每个变量分开占用空间.依次为int4+DATE20+double8=32.

所以结果是20+32=52.

当然...在某些16位编辑器下,int可能是2字节,那么结果是int2+DATE10+double8=20

#include

main()

inta,b,c,d;

a=10;

b=a++;

c=++a;

d=10*a++;

printf("b,c,d:%d,%d,%d",b,c,d);

return0;

答:10,12,120

我总结:不管a的自加还是自减在等号的那一边,最终a自身的值也会改变

intinc(inta)

return(++a);

intmulti(int*a,int*b,int*c)

return(*c=*a**b);

typedefint(FUNC1)(intin);

typedefint(FUNC2)(int*,int*,int*);

voidshow(FUNC2fun,intarg1,int*arg2)

INCp=&inc;

inttemp=p(arg1);

fun(&temp,&arg1,arg2);

printf("%d\n",*arg2);

show(multi,10,&a);

答:110

7、请找出下面代码中的所以错误

说明:以下代码是把一个字符串倒序,如“abcd”倒序后变为“dcba”

1、#include"string.h"

2、main()

3、{

4、char*src="hello,world";

5、char*dest=NULL;

6、intlen=strlen(src);

7、dest=(char*)malloc(len);

8、char*d=dest;

9、char*s=src[len];

10、while(len--!=0)

11、d++=s--;

12、printf("%s",dest);

13、return0;

14、}

答:

方法1:

intmain(){

char*src="hello,world";

intlen=strlen(src);

char*dest=(char*)malloc(len+1);//要为\0分配一个空间

char*d=dest;

char*s=&src[len-1];//指向最后一个字符

while(len--!=0)

*d++=*s--;

*d=0;//尾部要加\0

printf("%s\n",dest);

free(dest);//使用完,应当释放空间,以免造成内存汇泄露

方法2:

#include

charstr[]="hello,world";

intlen=strlen(str);

chart;

for(inti=0;i

t=str[i];

str[i]=str[len-i-1];str[len-i-1]=t;

printf("%s",str);

8、请问下面程序有什么错误

inta[60][250][1000],i,j,k;

for(k=0;k<=1000;k++)

for(j=0;j<250;j++)

for(i=0;i<60;i++)

a[i][j][k]=0;

答案:把循环语句内外换一下

//对于多重循环一定是内循环数大于等于外循环数

.#defineMax_CB500

voidLmiQueryCSmd(StructMSgCB*pmsg)

unsignedcharucCmdNum;

......

for(ucCmdNum=0;ucCmdNum

......;

答案:死循环

//字符型应该是到255,再加的话就溢出了,我觉得会出问题,可能就死循环了

10、以下3个有什么区别char*constp;//常量指针,p的值不可以修改

charconst*p;//指向常量的指针,指向的常量值不可以改

constchar*p;//和charconst*p

charstr1[]="abc";

charstr2[]="abc";

constcharstr3[]="abc";

constcharstr4[]="abc";

constchar*str5="abc";

constchar*str6="abc";

char*str7="abc";

char*str8="abc";

cout<<(str1==str2)<

cout<<(str3==str4)<

cout<<(str5==str6)<

cout<<(str7==str8)<

结果是:0011

解答:str1,str2,str3,str4是数组变量,它们有各自的内存空间;

而str5,str6,str7,str8是指针,它们指向相同的常量区域。

voidUpperCase(charstr[])//将str中的小写字母转换成大写字母

for(size_ti=0;i

if('a'<=str[i]&&str[i]<='z')

str[i]-=('a'-'A');

charstr[]="aBcDe";

cout<<"str字符长度为:"<

UpperCase(str);

cout<

inta[5]={1,2,3,4,5};

int*ptr=(int*)(&a+1);

printf("%d,%d",*(a+1),*(ptr-1));

输出:2,5

*(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5

&a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int)

则ptr实际是&(a[5]),也就是a+5

原因如下:

&a是数组指针,其类型为int(*)[5];

而指针加1要根据指针类型加上一定的值,

不同类型的指针+1之后增加的大小不同

a是长度为5的int数组指针,所以要加5*sizeof(int)

所以ptr实际是a[5]

但是prt与(&a+1)类型是不一样的(这点很重要)

所以prt-1只会减去sizeof(int*)

a,&a的地址是一样的,但意思不一样,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5].

intmain()

chara;

char*str=&a;

strcpy(str,"hello");

printf(str);

没有为str分配内存空间,将会发生异常

问题出在将一个字符串复制进一个字符变量指针所指地址。虽然可以正确输出结果,但因为越界进行内在读写而导致程序崩溃。

char*s="AAA";

printf("%s",s);

s[0]='B';

有什么错?

cosntchar*s="AAA";

然后又因为是常量,所以对是s[0]的赋值操作是不合法的。

inta=248;b=4;intconstc=21;constint*d=&a;

int*conste=&b;intconst*fconst=&a;

请问下列表达式哪些会被编译器禁止?为什么?

*c=32;d=&b;*d=43;e=34;e=&a;f=0x321f;

*c这是个什么东东,禁止

*d说了是const,禁止

e=&a说了是const禁止

const*fconst=&a;禁止

即a=3,b=5,交换之后a=5,b=3;

有两种解法,一种用算术算法,一种用^(异或)

a=a+b;

b=a-b;

a=a-b;

or

a=a^b;//只能对int,char..

b=a^b;

a=a^b;

a^=b^=a;

.#include

#include

voidgetmemory(char*p)//修改:(char**p)把地址传过来

p=(char*)malloc(100);

strcpy(p,"helloworld");

char*str=NULL;

getmemory(str);

printf("%s/n",str);

free(str);

程序崩溃,getmemory中的malloc不能返回动态内存,free()对str操作很危险

charszstr[10];

strcpy(szstr,"0123456789");

答案:长度不一样,会造成非法的OS,应该改为charszstr[11];

答:其中ptr为同一个指针

.(void*)ptr和(*(void**))ptr值是相同的

intx=3;

printf("%d",x);

return1;

答:mian中,c标准认为0表示成功,非0表示错误。具体的值是某中具体出错信息

(unsignedint*)0x100000=1234;//经典复制

首先要将0x100000强制转换成函数指针,即:

(void(*)())0x100000

然后再调用它:

*((void(*)())0x100000)();

用typedef可以看得更直观些:

typedefvoid(*)()voidFuncPtr;

*((voidFuncPtr)0x100000)();

unsignedshortA=10;

printf("~A=%u\n",~A);

charc=128;

printf("c=%d\n",c);

第一题,~A=0xfffffff5,int值为-11,但输出的是uint。所以输出4294967285

第二题,c=0x10,输出的是int,最高位为1,是负数,所以它的值就是0x00的补码就是128,所以输出-128。

这两道题都是在考察二进制向int或uint转换时的最高位处理。

补码:例如12模的系统中,加8和减4效果是一样的,因此凡是减4运算,都可以用加8来代替。对“模”而言,8和4互为补数。实际上以12模的系统中,11和1,10和2,9和3,7和5,6和6都有这个特性。共同的特点是两者相加等于模。在以12模的系统中,加8和减4效果是一样的,因此凡是减4运算,都可以用加8来代替。所以对于模为100000000的8位系统来说,减去b和加上100000000-b是一个道理,而(100000000-b)是什么?恰好就是b的补码(负数的补码等于其反码+1)定理:减去一个数就是加上它的补码,结果一样,所以解决了负数的计算。有了补码的概念,所有的加减都可以用加法来计算了。对于计算机而言方便了许多

假设模为8(8位)的操作系统,即它能表示256个数,数的表示范围为-128----+127(共256,注意别忘了0),正负数各占一半-128------+127,但对于-128-----1计算机会以它的补码表示即-128对应+128,-127----+129,-126-----+130,-2----254,-1----+255,当在打印输出是如果你要在8位的操作系统中输出+128-------+255,它会以-128--------1给你输出来

voidGetMemory(char**p,intnum)

*p=(char*)malloc(num);

GetMemory(&str,100);

if(str!=NULL)

strcpy(str,"world");

printf("\nstris%s",str);

getchar();

问输出结果是什么?希望大家能说说原因,先谢谢了

输出strisworld。

free只是释放的str指向的内存空间,它本身的值还是存在的.

所以free之后,有一个好的习惯就是将str=NULL.

此时str指向空间的内存已被回收,如果输出语句之前还存在分配空间的操作的话,这段存储空间是可能被重新分配给其他变量的,

尽管这段程序确实是存在大大的问题(上面各位已经说得很清楚了),但是通常会打印出world来。

这是因为,进程中的内存管理一般不是由操作系统完成的,而是由库函数自己完成的。

当你malloc一块内存的时候,管理库向操作系统申请一块空间(可能会比你申请的大一些),然后在这块空间中记录一些管理信息(一般是在你申请的内存前面一点),并将可用内存的地址返回。但是释放内存的时候,管理库通常都不会将内存还给操作系统,因此你是可以继续访问这块地址的,只不过。。。。。。。。楼上都说过了,最好别这么干。

#include"stdio.h"

#include"string.h"

voidmain()

charaa[10];

printf("%d",strlen(aa));

Printf(“%d”,sizeof(aa));

sizeof()和初不初始化,没有关系;

strlen()和初始化有关。

char(*str)[20];/*str是一个数组指针,即指向数组的指针.*/

char*str[20];/*str是一个指针数组,其元素为指针型数据.*/

答:0x801010用二进制表示为:“100000000001000000010000”,十进制的值为8392720,再加上5就是8392725

chart::4;

chark:4;

unsignedshorti:8;

unsignedlongm;

};问sizeof(A)=

给定结构structA

chart:4;4位

chark:4;4位

unsignedshorti:8;8位

unsignedlongm;//偏移2字节保证4字节对齐

};//共8字节

intadd_n(intn)

staticinti=100;

i+=n;

returni;

当你第二次调用时得不到正确的结果,难道你写个函数就是为了调用一次?问题就出在static上//static会把值保存下来

#include

#include

#include

typedefstructAA

intb1:5;

intb2:2;

}AA;

AAaa;

charcc[100];

strcpy(cc,"0123456789abcdefghijklmnopqrstuvwxyz");

memcpy(&aa,cc,sizeof(AA));

cout<

cout<

答案是-16和1

首先sizeof(AA)的大小为4,b1和b2分别占5bit和2bit.

经过strcpy和memcpy后,aa的4个字节所存放的值是:

0,1,2,3的ASC码,即00110000,00110001,00110010,00110011

所以,最后一步:显示的是这4个字节的前5位,和之后的2位

分别为:10000,和01

因为int是有正负之分所以:答案是-16和1

intfunc(x)

intcountx=0;

while(x)

countx++;

x=x&(x-1);//死记,反正数里面只要有1循环就不会停止,每次最低位一定被清零0---9最低位位是0--1---0----1---0----交叉排列的

returncountx;

结果呢?

知道了这是统计9999的二进制数值中有多少个1的函数,且有

9999=9×1024+512+256+15

9×1024中含有1的个数为2;

512中含有1的个数为1;

256中含有1的个数为1;

15中含有1的个数为4;

故共有1的个数为8,结果为8。

1000-1=0111,正好是原数取反。这就是原理。

用这种方法来求1的个数是很效率很高的。

不必去一个一个地移位。循环次数最少。

structbit

{inta:3;

intb:2;

intc:3;

};

bits;

char*c=(char*)&s;

cout<

*c=0x99;

cout<

inta=-1;

printf("%x",a);

输出为什么是

4

1

-1

-4

ffffffff

因为0x99在内存中表示为10011001,a=001,b=11,c=100

当c为有符合数时,c=100,最高1为表示c为负数,负数在计算机用补码表示,所以c=-4;同理

b=-1;

当c为有符合数时,c=100,即c=4,同理b=3

#defineMAX255

unsignedcharA[MAX],i;//i被定义为unsignedchar

for(i=0;i<=MAX;i++)

A[i]=i;

解答:死循环加数组越界访问(C/C++不进行数组越界检查)

MAX=255

数组A的下标范围为:0..MAX-1,这是其一..

其二.当i循环到255时,循环内执行:

A[255]=255;

这句本身没有问题..但是返回for(i=0;i<=MAX;i++)语句时,

由于unsignedchar的取值范围在(0..255),i++以后i又为0了..无限循环下去.

structname1{

charstr;

shortx;

intnum;

structname2{

sizeof(structname1)=8,sizeof(structname2)=12

在第二个结构中,为保证num按四个字节对齐,char后必须留出3字节的空间;同时为保证整个结构的自然对齐(这里是4字节对齐),在x后还要补齐2个字节,这样就是12字节。

inti:8;

intj:4;

inta:3;

doubleb;

structs2

printf("sizeof(s1)=%d\n",sizeof(s1));

printf("sizeof(s2)=%d\n",sizeof(s2));

result:16,24

第一个structs1

理论上是这样的,首先是i在相对0的位置,占8位一个字节,然后,j就在相对一个字节的位置,由于一个位置的字节数是4位的倍数,因此不用对齐,就放在那里了,然后是a,要在3位的倍数关系的位置上,因此要移一位,在15位的位置上放下,目前总共是18位,折算过来是2字节2位的样子,由于double是8字节的,因此要在相对0要是8个字节的位置上放下,因此从18位开始到8个字节之间的位置被忽略,直接放在8字节的位置了,因此,总共是16字节。特殊注意

第二个最后会对照是不是结构体内最大数据的倍数,不是的话,会补成是最大数据的倍数

structBBB

longnum;

char*name;

shortintdata;

charha;

shortba[5];

}*p;

p=0x1000000;

p+0x200=____;

(Ulong)p+0x200=____;

(char*)p+0x200=____;

希望各位达人给出答案和原因,谢谢拉

解答:假设在32位CPU上,

sizeof(long)=4bytes

sizeof(char*)=4bytes

sizeof(shortint)=sizeof(short)=2bytes

sizeof(char)=1bytes

由于是4字节对齐,

sizeof(structBBB)=sizeof(*p)

=4+4+2+1+1/*补齐*/+2*5+2/*补齐*/=24bytes(经Dev-C++验证)

=0x1000000+0x200*24

=0x1000000+0x200

=0x1000000+0x200*4

Voidtest1()

charstring[10];

char*str1="0123456789";

strcpy(string,str1);//溢出,应该包括一个存放'\0'的字符string[11]

Voidtest2()

charstring[10],str1[10];

for(I=0;I<10;I++)

str1[i]='a';

Voidtest3(char*str1)

if(strlen(str1)<=10)//改成<10,字符溢出,将strlen改为sizeof也可以

strcpy(string,str1);

voidg(int**);

intline[10],i;

int*p=line;//p是地址的地址

for(i=0;i<10;i++)

*p=i;

g(&p);//数组对应的值加1

printf("%d\n",line[i]);

voidg(int**p)

(**p)++;

(*p)++;//无效

输出:

2

3

5

6

7

8

9

10

intsum(inta)

autointc=0;

staticintb=3;

c+=1;

b+=2;

return(a+b+c);

intI;

inta=2;

for(I=0;I<5;I++)

printf("%d,",sum(a));

//static会保存上次结果,记住这一点,剩下的自己写

输出:8,10,12,14,16,

intfunc(inta)

intb;

switch(a)

case1:30;

case2:20;

case3:16;

default:0

returnb;

则func(1)=

//b定义后就没有赋值

inta[3];

a[0]=0;a[1]=1;a[2]=2;

int*p,*q;

p=a;

q=&a[2];

则a[q-p]=a[2]

解释:指针一次移动一个int但计数为1

char*RetMenory(void)

charp[]=“hellowworld”;

returnp;

voidTest(void)

str=RetMemory();

RetMenory执行完毕,p资源被回收,指向未知地址。返回地址,str的内容应是不可预测的,打印的应该是str的地址

typedefstruct

inta:2;

intc:1;

}test;

testt;

t.a=1;

t.b=3;

t.c=1;

printf("%d",t.a);

printf("%d",t.b);

printf("%d",t.c);

t.a为01,输出就是1

t.b为11,输出就是-1

t.c为1,输出也是-1

3个都是有符号数int嘛。

这是位扩展问题//查一下

01

11

编译器进行符号扩展

voidtest2()

inti;

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

str1不能在数组内结束:因为str1的存储为:{a,a,a,a,a,a,a,a,a,a},没有'\0'(字符串结束符),所以不能结束

strcpy(char*s1,char*s2)他的工作原理是,扫描s2指向的内存,逐个字符付到s1所指向的内存,直到碰到'\0',因为str1结尾没有'\0',所以具有不确定性,不知道他后面还会付什么东东。

正确应如下

for(i=0;i<9;i++)

str1[i]='a'+i;//把abcdefghi赋值给字符数组

str[i]='\0';//加上结束符

intarr[]={6,7,8,9,10};

int*ptr=arr;

*(ptr++)+=123;

printf(“%d%d”,*ptr,*(++ptr));

输出:88

过程:对于*(ptr++)+=123;先做加法6+123,然后++,指针指向7;对于printf(“%d%d”,*ptr,*(++ptr));从后往前执行,指针先++,指向8,然后输出8,紧接着再输出8

char*a="hello";

char*b="hello";

if(a==b)

printf("YES");

else

printf("NO");

这个简单的面试题目,我选输出no(对比的应该是指针地址吧),可在VC是YES在C是NO

lz的呢,是一个常量字符串。位于静态存储区,它在程序生命期内恒定不变。如果编译器优化的话,会有可能a和b同时指向同一个hello的。则地址相同。如果编译器没有优化,那么就是两个不同的地址,则不同

voidfoo(intm,intn)

printf("m=%d,n=%d\n",m,n);

intb=3;

foo(b+=3,++b);//遇到函数里自加减的这种题都不定别去管

printf("b=%d\n",b);

输出:m=7,n=4,b=7(VC6.0)

#includestring.h

main(void)

{char*src="hello,world";

char*dest=NULL;

dest=(char*)malloc(strlen(src));

char*s=src[len];

d++=s--;

printf("%s",dest);

找出错误!!实现逆排****************

#include"malloc.h"

dest=(char*)malloc(sizeof(char)*(strlen(src)+1));

char*s=src+len-1;

*d='\0';

12

34

56

输出到file2.txt:

intmain(void)

intMAX=10;

int*a=(int*)malloc(MAX*sizeof(int));

int*b;

FILE*fp1;

FILE*fp2;

fp1=fopen("a.txt","r");

if(fp1==NULL)

{printf("error1");

exit(-1);

fp2=fopen("b.txt","w");

if(fp2==NULL)

{printf("error2");

inti=0;

intj=0;

while(fscanf(fp1,"%d",&a[i])!=EOF)

i++;

j++;

if(i>=MAX)

MAX=2*MAX;

b=(int*)realloc(a,MAX*sizeof(int));

if(b==NULL)

printf("error3");

a=b;

for(;--j>=0;)

fprintf(fp2,"%d\n",a[j]);

fclose(fp1);

fclose(fp2);

例如n=5

5=1+4;5=2+3(相加的数不能重复)

则输出

1,4;2,3。

unsignedlonginti,j,k;

printf("pleaseinputthenumber\n");

scanf("%d",&i);

if(i%2==0)

j=i/2;//思想:一个被加数一定是这个数的1/2的左边,一个在右边

j=i/2+1;

printf("Theresultis\n");

for(k=0;k

printf("%d=%d+%d\n",i,k,i-k);

unsignedlonginta,i=1;

scanf("%d",&a);

if(a%2==0)

for(i=1;i

printf("%d",a,a-i);

for(i=1;i<=a/2;i++)

printf("%d,%d",i,a-i);

voidinverse(char*p)+

if(*p=='\0')

return;

inverse(p+1);//切记:对于字符串的指针加1,就是指向最后一个字符

printf("%c",*p);

intmain(intargc,char*argv[])

inverse("abc\0");

对1的另一种做法:

voidtest(FILE*fread,FILE*fwrite)

charbuf[1024]={0};

if(!fgets(buf,sizeof(buf),fread))

test(fread,fwrite);

fputs(buf,fwrite);

FILE*fr=NULL;

FILE*fw=NULL;

fr=fopen("data","rb");

fw=fopen("dataout","wb");

test(fr,fw);

fclose(fr);

fclose(fw);

4、写一段程序,找出数组中第k大小的数,输出数所在的位置。例如{2,4,3,4,7}中,第一大的数是7,位置在4。第二大、第三大的数都是4,位置在1、3随便输出哪一个均可。函数接口为:intfind_orderk(constint*narry,constintn,constintk)

要求算法复杂度不能是O(n^2)

谢谢!

可以先用快速排序进行排序,其中用另外一个进行地址查找

代码如下,在VC++6.0运行通过。给分吧^-^

//快速排序

#include

usingnamespacestd;

intPartition(int*L,intlow,inthigh)

inttemp=L[low];

intpt=L[low];

while(low

while(low=pt)

--high;

L[low]=L[high];

while(low

++low;

L[low]=temp;

returnlow;

voidQSort(int*L,intlow,inthigh)

if(low

intpl=Partition(L,low,high);

QSort(L,low,pl-1);

QSort(L,pl+1,high);

intnarry[100],addr[100];

intsum=1,t;

cout<<"Inputnumber:"<

cin>>t;

while(t!=-1)

narry[sum]=t;

addr[sum-1]=t;

sum++;

sum-=1;

QSort(narry,1,sum);

for(inti=1;i<=sum;i++)

cout<

cout<

intk;

cout<<"Pleaseinputplaceyouwant:"<

cin>>k;

intaa=1;

intkk=0;

if(aa==k)

break;

if(narry[kk]!=narry[kk+1])

aa+=1;

kk++;

cout<<"TheNO."<

cout<<"Andit'splaceis:";

for(i=0;i

if(addr[i]==narry[sum-kk])

cout<

Linklist*unio(Linklist*p,Linklist*q){

linklist*R,*pa,*qa,*ra;

pa=p;

qa=q;

R=ra=p;

while(pa->next!=NULL&&qa->next!=NULL){

if(pa->data>qa->data){

ra->next=qa;

qa=qa->next;

else{

ra->next=pa;

pa=pa->next;

if(pa->next!=NULL)

if(qa->next!=NULL)

ra->next==qa;

returnR;

递归的方法,记录当前最大的,并且判断当前的是否比这个还大,大则继续,否则返回false结束:

boolfun(inta[],intn)

if(n==1)

returntrue;

if(n==2)

returna[n-1]>=a[n-2];

returnfun(a,n-1)&&(a[n-1]>=a[n-2]);

typedefstructval

{intdate_1;

structval*next;

voidmain(void)

{charc;

for(c=122;c>=97;c--)

{p.date=c;

p=p->next;

p.next=NULL;

node*p=NULL;

node*q=NULL;

node*head=(node*)malloc(sizeof(node));

head->data='';head->next=NULL;

node*first=(node*)malloc(sizeof(node));

first->data='a';first->next=NULL;head->next=first;

p=first;

intlongth='z'-'b';

while(i<=longth)

node*temp=(node*)malloc(sizeof(node));

temp->data='b'+i;temp->next=NULL;q=temp;

head->next=temp;temp->next=p;p=q;

print(head);

voidswap(inta,intb)

intc;c=a;a=b;b=a;

--->空优

a=a+b;b=a-b;a=a-b;

intcontinumax(char*outputstr,char*inputstr)

char*in=inputstr,*out=outputstr,*temp,*final;

intcount=0,maxlen=0;

while(*in!='\0')

if(*in>47&&*in<58)

for(temp=in;*in>47&&*in<58;in++)

count++;

in++;

if(maxlen

maxlen=count;

count=0;

final=temp;

for(inti=0;i

*out=*final;

out++;

final++;

*out='\0';

returnmaxlen;

intgetlen(char*s){

intn;

for(n=0;*s!='\0';s++)

n++;

returnn;

voidreverse(chars[])

intc,i,j;

for(i=0,j=getlen(s)-1;i

c=s[i];

s[i]=s[j];

s[j]=c;

voiditoa(intn,chars[])

inti,sign;

if((sign=n)<0)

n=-n;

i=0;

do{/*以反序生成数字*/

s[i++]=n%10+'0';/*getnextnumber*/

}while((n/=10)>0);/*deletethenumber*/

if(sign<0)

s[i++]='-';

s[i]='\0';

reverse(s);

方法2:

voiditochar(intnum);

voiditochar(intnum)

intj;

charstra[10];

charstrb[10];

while(num)

stra[i++]=num%10+48;//+48和+‘0’一样

num=num/10;

stra[i]='\0';

for(j=0;j

strb[j]=stra[i-j-1];

strb[j]='\0';

cout<

cin>>num;

itochar(num);

如:combination(5,3)

要求输出:543,542,541,532,531,521,432,431,421,321,

intpop(int*);

intpush(int);

voidcombination(int,int);

intstack[3]={0};

top=-1;

intn,m;

printf("Inputtwonumbers:\n");

while((2!=scanf("%d%*c%d",&n,&m)))

fflush(stdin);

printf("Inputerror!Again:\n");

combination(n,m);

printf("\n");

voidcombination(intm,intn)

inttemp=m;

push(temp);

if(1==temp)

if(pop(&temp)&&stack[0]==n)//当栈底元素弹出&&为可能取的最小值,循环退出

elseif(push(--temp))

printf("%d%d%d",stack[0],stack[1],stack[2]);//§¨ì¤@

pop(&temp);

intpush(inti)

stack[++top]=i;

if(top<2)

intpop(int*i)

*i=stack[top--];

if(top>=0)

#include

charstr[]="ABCD1234efgh";

intlength=strlen(str);

char*p1=str;

char*p2=str+length-1;

while(p1

charc=*p1;

*p1=*p2;

*p2=c;

++p1;

--p2;

printf("strnowis%s\n",str);

system("pause");

doublegetValue()

doubleresult=0;

inti=2;

while(i<42)

result+=1.0/i;//一定要使用1.0做除数,不能用1,否则结果将自动转化成整数,即0.000000

i+=2;

returnresult;

printf("resultis%f\n",getValue());

以7个数为例:

{0,1,2,3,4,5,6,7}0-->1-->2(删除)-->3-->4-->5(删除)-->6-->7-->0(删除),如此循环直到最后一个数被删除。

方法1:数组

#definenull1000

intarr[1000];

for(inti=0;i<1000;++i)

arr[i]=i;

intcount=0;

while(count<999)

while(arr[j%1000]==null)

j=(++j)%1000;

arr[j]=null;

++count;

while(arr[j]==null)

cout<

}方法2:链表

#definenull0

structnode

intdata;

node*next;

node*head=newnode;

head->data=0;

head->next=null;

node*p=head;

for(inti=1;i<1000;i++)

node*tmp=newnode;

tmp->data=i;

tmp->next=null;

head->next=tmp;

head=head->next;

head->next=p;

while(p!=p->next)

p->next->next=p->next->next->next;

p=p->next->next;

cout<data;

方法3:通用算法

#defineMAXLINE1000//元素个数

/*

MAXLINE元素个数

a[]元素数组

R[]指针场

suffix下标

index返回最后的下标序号

values返回最后的下标对应的值

start从第几个开始

K间隔

*/

intfind_n(inta[],intR[],intK,int&index,int&values,ints=0){

intsuffix;

intfront_node,current_node;

suffix=0;

if(s==0){

current_node=0;

front_node=MAXLINE-1;

current_node=s;

front_node=s-1;

while(R[front_node]!=front_node){

printf("%d\n",a[current_node]);

R[front_node]=R[current_node];

if(K==1){

current_node=R[front_node];

continue;

for(inti=0;i

front_node=R[front_node];

index=front_node;

values=a[front_node];

intmain(void){

inta[MAXLINE],R[MAXLINE],suffix,index,values,start,i,K;

suffix=index=values=start=0;

K=2;

for(i=0;i

a[i]=i;

R[i]=i+1;

R[i-1]=0;

find_n(a,R,K,index,values,2);

printf("thevalueis%d,%d\n",index,values);

intStrCmp(constchar*str1,constchar*str2)

做是做对了,没有抄搞,比较乱

assert(str1&&srt2);

while(*str1&&*str2&&*str1==*str2){

str1++,str2++;

if(*str1&&*str2)

return(*str1-*str2);

elseif(*str1&&*str2==0)

elseif(*str1==0&&*str2)

return-1;

//省略判断空指针(自己保证)

while(*str1&&*str1++==*str2++);

return*str1-*str2;

intFindSubStr(constchar*MainStr,constchar*SubStr)

intMyStrstr(constchar*MainStr,constchar*SubStr)

constchar*p;

constchar*q;

constchar*u=MainStr;

//assert((MainStr!=NULL)&&(SubStr!=NULL));//用断言对输入进行判断

while(*MainStr)//内部进行递增

p=MainStr;

q=SubStr;

while(*q&&*p&&*p++==*q++);

if(!*q)

returnMainStr-u+1;//MainStr指向当前起始位,u指向

MainStr++;

slnodetype*Delete(slnodetype*Head,intkey){}中if(Head->number==key)

Head=Pointer->next;

free(Pointer);

Back=Pointer;

Pointer=Pointer->next;

if(Pointer->number==key)

Back->next=Pointer->next;

voiddelete(Node*p)

if(Head=Node)

while(p)

inta[]={10,6,9,5,2,8,4,7,1,3};

intlen=sizeof(a)/sizeof(int);

inttemp;

for(inti=0;i

temp=a[a[i]-1];

a[a[i]-1]=a[i];

a[i]=temp;

if(a[i]==i+1)

for(intj=0;j

cout<

typedefstructlinknode

structlinknode*next;

}node;

//将一个链表逆置

node*reverse(node*head)

node*p,*q,*r;

p=head;

q=p->next;

while(q!=NULL)

r=q->next;

q->next=p;

p=q;

q=r;

head->next=NULL;

head=p;

returnhead;

voiddel_all(node*head)

node*p;

while(head!=NULL)

p=head->next;

free(head);

cout<<"释放空间成功!"<

voidinsert(char*s,char*t,inti)

char*q=t;

char*p=s;

if(q==NULL)return;

while(*p!='\0')

p++;

while(*q!=0)

*p=*q;

q++;

*p='\0';

memcpysourcecode:

270void*memcpy(void*dst,constvoid*src,unsignedintlen)

271{

272registerchar*d;

273registerchar*s;

27

275if(len==0)

276returndst;

277

278if(is_overlap(dst,src,len,len))

279complain3("memcpy",dst,src,len);

280

281if(dst>src){

282d=(char*)dst+len-1;

283s=(char*)src+len-1;

284while(len>=4){

285*d--=*s--;

286*d--=*s--;

287*d--=*s--;

288*d--=*s--;

289len-=4;

290}

291while(len--){

292*d--=*s--;

293}

294}elseif(dst

295d=(char*)dst;

296s=(char*)src;

297while(len>=4){

298*d++=*s++;

299*d++=*s++;

300*d++=*s++;

301*d++=*s++;

302len-=4;

303}

304while(len--){

305*d++=*s++;

306}

307}

308returndst;

309}

各种情况包括:

1、参数是指针,检查指针是否有效

2、检查复制的源目标和目的地是否为同一个,若为同一个,则直接跳出

3、读写权限检查

4、安全检查,是否会溢出

memcpy拷贝一块内存,内存的大小你告诉它

strcpy是字符串拷贝,遇到'\0'结束

/*memcpy───拷贝不重叠的内存块*/

voidmemcpy(void*pvTo,void*pvFrom,size_tsize)

void*pbTo=(byte*)pvTo;

void*pbFrom=(byte*)pvFrom;

ASSERT(pvTo!=NULL&&pvFrom!=NULL);//检查输入指针的有效性

ASSERT(pbTo>=pbFrom+size||pbFrom>=pbTo+size);//检查两个指针指向的内存是否重叠

while(size-->0)

*pbTo++==*pbFrom++;

return(pvTo);

memcpy(&s[strlen(t)+i],&s[i],strlen(s)-i);

memcpy(&s[i],t,strlen(t));

s[strlen(s)+strlen(t)]='\0';

char*search(char*cpSource,charch)

char*cpTemp=NULL,*cpDest=NULL;

intiTemp,iCount=0;

while(*cpSource)

if(*cpSource==ch)

iTemp=0;

cpTemp=cpSource;

while(*cpSource==ch)

++iTemp,++cpSource;

if(iTemp>iCount)

iCount=iTemp,cpDest=cpTemp;

if(!*cpSource)

++cpSource;

returncpDest;

intsearch(char*cpSource,intn,charch)

for(i=0;i

比如A="aocdfe"B="pmcdfa"则输出"cdf"

//Author:azhen

char*commanstring(charshortstring[],charlongstring[])

inti,j;

char*substring=malloc(256);

if(strstr(longstring,shortstring)!=NULL)//如果……,那么返回shortstring

returnshortstring;

for(i=strlen(shortstring)-1;i>0;i--)//否则,开始循环计算

for(j=0;j<=strlen(shortstring)-i;j++){

memcpy(substring,&shortstring[j],i);

substring[i]='\0';

if(strstr(longstring,substring)!=NULL)

returnsubstring;

returnNULL;

char*str1=malloc(256);

char*str2=malloc(256);

char*comman=NULL;

gets(str1);

gets(str2);

if(strlen(str1)>strlen(str2))//将短的字符串放前面

comman=commanstring(str2,str1);

comman=commanstring(str1,str2);

printf("thelongestcommanstringis:%s\n",comman);

str2返回1,若str1小于str2返回-1

intstrcmp(constchar*src,constchar*dst)

intret=0;

while(!(ret=*(unsignedchar*)src-*(unsignedchar*)dst)&&*dst)

++src;

++dst;

if(ret<0)

ret=-1;

elseif(ret>0)

ret=1;

return(ret);

求出1->1000里,能被5整除的数的个数n1,能被25整除的数的个数n2,能被125整除的数的个数n3,

能被625整除的数的个数n4.

1000!末尾的零的个数=n1+n2+n3+n4;

#defineNUM1000

intfind5(intnum){

while(num%5==0){

num/=5;

ret++;

returnret;

intresult=0;

for(i=5;i<=NUM;i+=5)

result+=find5(i);

printf("thetotalzeronumberis%d\n",result);

{intdata;

structnode*front,*next;

有两个双向循环链表A,B,知道其头指针为:pHeadA,pHeadB,请写一函数将两链表中data值相同的结点删除

BOOLDeteleNode(Node*pHeader,DataTypeValue)

if(pHeader==NULL)return;

BOOLbRet=FALSE;

Node*pNode=pHead;

while(pNode!=NULL)

if(pNode->data==Value)

if(pNode->front==NULL)

pHeader=pNode->next;

pHeader->front=NULL;

if(pNode->next!=NULL)

pNode->next->front=pNode->front;

pNode->front->next=pNode->next;

Node*pNextNode=pNode->next;

deletepNode;

pNode=pNextNode;

bRet=TRUE;

//不要break或return,删除所有

pNode=pNode->next;

returnbRet;

voidDE(Node*pHeadA,Node*pHeadB)

if(pHeadA==NULL||pHeadB==NULL)

Node*pNode=pHeadA;

if(DeteleNode(pHeadB,pNode->data))

pHeadA=pNode->next;

pHeadA->front=NULL;

intGetCommon(char*s1,char*s2,char**r1,char**r2)

intlen1=strlen(s1);

intlen2=strlen(s2);

intmaxlen=0;

for(inti=0;i

for(intj=0;j

if(s1[i]==s2[j])

intas=i,bs=j,count=1;

while(as+1

if(count>maxlen)

*r1=s1+i;

*r2=s2+j;

char*test3(longnum){

char*buffer=(char*)malloc(11);

buffer[0]='0';

buffer[1]='x';

buffer[10]='\0';

char*temp=buffer+2;

for(inti=0;i<8;i++){

temp[i]=(char)(num<<4*i>>28);

temp[i]=temp[i]>=0temp[i]:temp[i]+16;

temp[i]=temp[i]<10temp[i]+48:temp[i]+55;

returnbuffer;

比如N=3,打印:

123

894

765

N=4,打印:

1234

1213145

1116156

10987

解答:

1#defineN15

ints[N][N];

intk=0,i=0,j=0;

inta=1;

for(;k<(N+1)/2;k++)

while(j

while(i

while(j>k-1)s[i][j--]=a++;i--;j++;

while(i>k)s[i--][j]=a++;i++;j++;

for(i=0;i

for(j=0;j

cout<

2defineMAX_N100

intmatrix[MAX_N][MAX_N];

*(x,y):第一个元素的坐标

*start:第一个元素的值

*n:矩阵的大小

voidSetMatrix(intx,inty,intstart,intn){

if(n<=0)//递归结束条件

if(n==1){//矩阵大小为1时

matrix[x][y]=start;

for(i=x;i

matrix[y][i]=start++;

for(j=y;j

matrix[j][x+n-1]=start++;

for(i=x+n-1;i>x;i--)//底部

matrix[y+n-1][i]=start++;

for(j=y+n-1;j>y;j--)//左部

matrix[j][x]=start++;

SetMatrix(x+1,y+1,start,n-2);//递归

voidmain(){

scanf("%d",&n);

SetMatrix(0,0,1,n);

//打印螺旋矩阵

for(i=0;i

for(j=0;j

printf("%4d",matrix[i][j]);

intFunct(intn)

if(n==0)return1;

if(n==1)return1;

retrurnFunct(n-1)+Funct(n-2);

请问,如何不使用递归,来实现上述函数?

请教各位高手!

解答:intFunct(intn)//n为非负整数

inta=0;

intb=1;

intc;

if(n==0)c=1;

elseif(n==1)c=1;

elsefor(inti=2;i<=n;i++)//应该n从2开始算起

c=a+b;

b=c;

returnc;

100的二进制是001100100

低位在前高位在后

001----s3

100----s2

100----s1

所以结果应该是1

如果先申明的在低位则:

001----s1

100----s3

结果是4

1、原题跟little-endian,big-endian没有关系

2、原题跟位域的存储空间分配有关,到底是从低字节分配还是从高字节分配,从DevC++和VC7.1上看,都是从低字节开始分配,并且连续分配,中间不空,不像谭的书那样会留空位

3、原题跟编译器有关,编译器在未用堆栈空间的默认值分配上有所不同,DevC++未用空间分配为

01110111b,VC7.1下为11001100b,所以在DevC++下的结果为5,在VC7.1下为1。

注:PC一般采用little-endian,即高高低低,但在网络传输上,一般采用big-endian,即高低低高,华为是做网络的,所以可能考虑big-endian模式,这样输出结果可能为4

intIsReverseStr(char*aStr)

intfound=1;

if(aStr==NULL)

j=strlen(aStr);

for(i=0;i

if(*(aStr+i)!=*(aStr+j-i-1))

found=0;

returnfound;

36、Josephu问题为:设编号为1,2,…n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。

数组实现:

intJosephu(intn,intm)

intflag,i,j=0;

int*arr=(int*)malloc(n*sizeof(int));

for(i=0;i

arr[i]=1;

for(i=1;i

flag=0;

while(flag

if(j==n)

j=0;

if(arr[j])

++flag;

++j;

arr[j-1]=0;

printf("第%4d个出局的人是:%4d号\n",i,j);

free(arr);

returnj;

scanf("%d%d",&n,&m);

printf("最后胜利的是%d号!\n",Josephu(n,m));

链表实现:

typedefstructNode

intindex;

structNode*next;

}JosephuNode;

JosephuNode*head,*tail;

head=tail=(JosephuNode*)malloc(sizeof(JosephuNode));

tail->index=i;

tail->next=(JosephuNode*)malloc(sizeof(JosephuNode));

tail=tail->next;

tail->next=head;

for(i=1;tail!=head;++i)

for(j=1;j

tail=head;

tail->next=head->next;

printf("第%4d个出局的人是:%4d号\n",i,head->index);

head=tail->next;

i=head->index;

char*strcpy(char*strDest,constchar*strSrc);

1.不调用库函数,实现strcpy函数。

2.解释为什么要返回char*。

解说:

1.strcpy的实现代码

char*strcpy(char*strDest,constchar*strSrc)

if((strDest==NULL)||(strSrc==NULL))file://[/1]

throw"Invalidargument(s)";//[2]

char*strDestCopy=strDest;file://[/3]

while((*strDest++=*strSrc++)!='\0');file://[/4]

returnstrDestCopy;

错误的做法:

[1]

(A)不检查指针的有效性,说明答题者不注重代码的健壮性。

(B)检查指针的有效性时使用((!strDest)||(!strSrc))或(!(strDest&&strSrc)),说明答题者对C语言中类型的隐式转换没有深刻认识。在本例中char*转换为bool即是类型隐式转换,这种功能虽然灵活,但更多的是导致出错概率增大和维护成本升高。所以C++专门增加了bool、true、false三个关键字以提供更安全的条件表达式。

(C)检查指针的有效性时使用((strDest==0)||(strSrc==0)),说明答题者不知道使用常量的好处。直接使用字面常量(如本例中的0)会减少程序的可维护性。0虽然简单,但程序中可能出现很多处对指针的检查,万一出现笔误,编译器不能发现,生成的程序内含逻辑错误,很难排除。而使用NULL代替0,如果出现拼写错误,编译器就会检查出来。

[2]

(A)returnnewstring("Invalidargument(s)");,说明答题者根本不知道返回值的用途,并且他对内存泄漏也没有警惕心。从函数中返回函数体内分配的内存是十分危险的做法,他把释放内存的义务抛给不知情的调用者,绝大多数情况下,调用者不会释放内存,这导致内存泄漏。

(B)return0;,说明答题者没有掌握异常机制。调用者有可能忘记检查返回值,调用者还可能无法检查返回值(见后面的链式表达式)。妄想让返回值肩负返回正确值和异常值的双重功能,其结果往往是两种功能都失效。应该以抛出异常来代替返回值,这样可以减轻调用者的负担、使错误不会被忽略、增强程序的可维护性。

[3]

(A)忘记保存原始的strDest值,说明答题者逻辑思维不严密。

[4]

(A)循环写成while(*strDest++=*strSrc++);,同[1](B)。

(B)循环写成while(*strSrc!='\0')*strDest++=*strSrc++;,说明答题者对边界条件的检查不力。循环体结束后,strDest字符串的末尾没有正确地加上'\0'。

有些信息在存储时,并不需要占用一个完整的字节,而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1两种状态,用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示。一、位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为:

struct位域结构名

{位域列表};

其中位域列表的形式为:类型说明符位域名:位域长度

例如:

structbs

inta:8;

intc:6;

位域变量的说明与结构变量说明的方式相同。可采用先定义后说明,同时定义说明或者直接说明这三种方式。例如:

}data;

说明data为bs变量,共占两个字节。其中位域a占8位,位域b占2位,位域c占6位。对于位域的定义尚有以下几点说明:

1.一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如:

unsigneda:4

unsigned:0/*空域*/

unsignedb:4/*从下一单元开始存放*/

unsignedc:4

在这个位域定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。

2.由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说不能超过8位二进位。

3.位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如:

structk

inta:1

int:2/*该2位不能使用*/

intb:3

intc:2

从以上分析可以看出,位域在本质上就是一种结构类型,不过其成员是按二进位分配的。

二、位域的使用位域的使用和结构成员的使用相同,其一般形式为:位域变量名位域名位域允许用各种格式输出。

THE END
1.如何正确使用和了解各类工具及应用?这些工具的使用嘲有哪些?以下是一个简单的表格,对部分工具及应用的使用场景进行比较: 要正确使用这些工具及应用,首先需要明确自己的需求和目标。在选择工具时,充分了解其功能特点,是否与自己的工作或任务相匹配。然后,通过在线教程、官方文档、培训课程等途径学习其基本操作和高级技巧。 https://stock.hexun.com/2024-12-14/216182960.html
2.会计基础知识中的用途与功能是一个意思吗?高顿为您提供一对一解答服务,关于会计基础知识中的用途与功能是一个意思吗?我的回答如下:同学你好~功https://www.gaodun.com/ask/404935.html
3.功能与作用的区别,,,功能与作用意思一样吗(职能和功能有什么区别?)在我们的生活中,有许多意思相近的词语,人们把他们称之为近义词,有时候,人们用错词的话,可能就会闹出一个大笑话,今天就给大家介绍一下功能与作用的区别,功能是食物内部固有的一种效能,就像一个人或者一个东西本身具有的一种能力,它是由事物内部要素结构所决定的,是一种内在于事物内部相对稳定独立的机制。 https://www.dadaojiayuan.com/jiankang/63005.html
4.实施运维企业面试题5原理:当网络中的数据包每经过一个路由器 TTL 值减 1,当 TTL 值为 0 时,数据包丢弃。 11 请描述 SMTP 及 POP3 分别是什么协议、作用及端口号 参考答案 SMTP:简单邮件传输协议,用于发送和接收邮件,端口号 25。 POP3:邮局协议版本 3,用于客户端接收邮件,端口号 110。 https://blog.csdn.net/zd19900712/article/details/122303308
5.Alibaba最新1000多道Java面试题汇总详解,收藏起来慢慢刷!4、Spring Framework 有哪些不同的功能? 5、怎么比较两个字符串的值一样,怎么比较两个字符串是否同一对象? 6、什么是 Spring 配置文件? 7、Spring 应用程序有哪些不同组件? 8、使用 Spring 有哪些方式? 9、tring str = new String(“abc”);创建了几个对象,为什么? https://maimai.cn/article/detail?fid=1728969401&efid=esjJLvGGL4fAr1LArgq_cQ
6.蚂蚁庄园形堂今日答案蚂蚁庄园最新今日答案8.24:猜一猜:以下哪种水果口感很甜,热量却偏低? 答案:蜜瓜 8.23:以下哪件国宝级文物出土于金沙遗址? 答案:太阳神鸟金饰 8.23:冷知识:以下哪一个是古人对铜镜的称谓? 答案:鉴 8.22:节气小知识:“处暑”一词是什么意思 答案:炎热离开 8.22:小鸡宝宝考考你:处暑等于出伏吗 答案:不是哦 8.21:夏季炎热,以下哪种https://m.duotegame.com/mgl/35822.html
7.常见问题解答如果您不想截取音频,直接点击“确认”按钮关闭对话框即可,因为默认的截取时间段是整个音频,就是不截取的意思。 我怎样将同一个视频分成几段呢? 您只需使用主界面最下方的“超级剪刀手”功能(就是那个剪刀图标)即可。方法是:先在预览窗口中定位好想要分割的时间点,点击剪刀图标按钮即可切割视频。用这个方法您可以快http://www.ijianji.com/faq.htm
8.小羊楼百问百答!再随便说一个小困难:出《建规证》的前一天,某职能部门突然发现图纸上多出一条道路,再一看,原来这是“现行控规”和“在编控规”矛盾了,职能部门要着眼未来按在编控规规划,画图纸的设计部门坚持按现行控规画图,因为在编控规还没公布……就为了沟通这一个问题,为了第二天顺利出证,一天之内我们在设计部门和职能部https://news.ycwb.com/2022-07/16/content_40920940.htm
9.小学英语语法大全语法有两个 含义,一指语法结构规律本身,即语法事实;一指 语法学,是探索并描写语法结构的科学,是语法学者对客观存在的语法体系的认识和说明。以下是小编整理的关于小学英语语法大全,希望大家认真阅读! 一. 名词复数的规则变化 一般情况 加-s 1.清辅音后读/s/; https://www.oh100.com/peixun/basic/348277.html
10.精神文明建设征信体系是指与征信活动有关的法律规章、组织机构、市场管理、文化建设、宣传教育等共同构成的一个体系。征信体系的主要功能是为信贷市场服务,但同时具有较强的外延性,还向商品交易市场和劳动力市场提供服务。在实践中,征信体系的主要参与者有征信机构、金融机构、企业、个人以及政府。 https://zwfwb.tj.gov.cn/ztzl1/ZTZL3/djyd/jswmjs/202007/t20200722_3088885.html
11.不可不知的风水摆件,各种开运化煞风水摆件!六帝铜钱,又称善六铜钱,指清朝顺治、康熙、雍正、乾隆、嘉庆、道光六个皇帝的铜钱,专化五黄煞、二黑煞之用。六为六白乾,性质属金,五黄、二黑煞都属土,以土生金泄气化煞(风水宜泄不宜斗)。因此,六帝钱化解五黄煞,太岁的效果要比五帝钱好。 六铜钱的风水用途: http://www.360doc.com/content/22/0818/21/655052_1044413391.shtml
12.初中网络安全教育主题班会(精选10篇)5、请说出计算机的十个用途? (这两组问题的对比,使学生从心理上认识到自己对电脑的了解片面,对于电脑网络的娱乐功能,了如指掌,但一些关于电脑的产生、发展历史以及在其他领域的实用功能,他们却知之甚少甚至一无所知,对于电脑网络,并不像自己认为的那样了解。) https://yjbys.com/cehuashu/zhutibanhui/1343626.html
13.pos机是干什么用的pos机的作用及用途→MAIGOO知识摘要:pos机是干什么用的?相信很多人也许还并不了解。其实pos机是一个收款的中间工具,跟手机银行转账一样,不过pos机除了用来商家收款外,我们还可以用pos机还信用卡,就是刷卡以后你到账了,那么就可以直接在机器上面还任何一张信用卡。下面就来了解下pos机的作用及用途吧。 https://www.maigoo.com/goomai/254552.html
14.礼仪的基本知识2、为避免几年选同样的礼物给同一个人的尴尬情况发生,最好每年送礼时做一下记录为好。 3、千万不要把以前接收的礼物转送出去,或丢掉它,不要以为人家不知道,送礼物给你的人会留意你有没有用他所送的物品。 4、切勿直接去问对方喜欢什么礼物,一方面可能他要求的会导致你超出预算,另一方面你即使照着他的意思去https://www.ruiwen.com/liyichangshi/6517797.html
15.《实用现代汉语语法》3) 你把身上的雪扫一下吧。 4) 我们班有十个同学。 5) 他们中间的多数会觉悟出来。 (2) 描述性定语:从性质、状态、特点、用途、材料、职业、人的穿着打扮等方面加以描述 1)她穿了一件紫红色的大衣 2)她是一个雷厉风行的人 3)这个是装工具的箱子 https://m.douban.com/note/687231006/