链表的基本概念:
- 表头结点:链表中的第一个结点,包含指向第一个数据元素的指针以及链表自身的一些信息
- 数据结点:链表中代表数据元素的节点,包含下一个数据元素的指针和数据元素
- 尾节点:链表中的最后一个数据结点,其下一个元素指针为空,表示无后继
已知链表的头结点head,写一个函数把这个链表逆序
Node* ReverseList(Node* head)
{
if(head == NULL || head->next == NULL)
return NULL;
Node* p1 = head;
Node* p2 = p1->next;
Node* p3 - p2->next;
p1->next = NULL;
while(p3 != NULL)
{
p2->next = p1;
p1 = p2;
p2 = p3;
p3 = p3->next;
}
p2->next = p1;
head = p2;
return head;
}
已知两个链表head1和head2各自有序升序排列,请把它们合并成一个链表并依然有序,并要求保留所有节点
Node* Merge(Node* head1,Node* head2)
{
Node* head = NULL;
if(head1 == NULL)
return head2;
if(head2 == NULL)
return head1;
if(head1->data < head2->data)
{
head = head1;
head1 = head1->next;
}
else
{
head = head2;
head2 = head2->next;
}
while(head1 != NULL && head2 != NULL)
{
if(head1->data < head2->data)
{
head->next = head1;
head = head1;
head1 = head1->next;
}
else
{
head->next = head2;
head = head2;
head2= head2->next;
}
}
if(head1 == NULL)
{
head->next = head2;
}
else
{
head->next = head1;
}
return temp;
}
用递归方法:已知两个链表head1和head2各自升序排列,请把它们合并成一个链表依然有序
Node* MergeRecursive(Node* head1,Node* haed2)
{
if(head1 == NULL)
{
return head2;
}
else
{
return head1;
}
Node* head = NULL;
if(head1->data < head2->data)
{
head = head1;
head->next = MergeRecursive(head1->next,head2);
}
else
{
head = head2;
head->next = MergeRecursive(head1,head2->next);
}
设变量名为var,分别给出bool、int、float和指针变量与“零值”比较的if语句
- if(!var)
- if(var ==0)
- const float EPSINON = 0.00001;if( x>= -EPSINON && x <= EPSINON)
- if(var == NULL)
编写一个函数,把一个char组成的字符串循环右移n位,例如,原来是“abcdefghi”,如果n=2,移位后是“hiabcdefg”
strcpy, memcpy和memset
- char* strcpy(char* dest, const char *src);
- void *memcpy(void *dest, const void *src, size_t n);
- void *memset(void *s, int ch, size_t n);
(1) void LoopMove(char* pStr,int steps)
{
int length = strlen(pStr);
int temp = steps % length;
strcpy(temp, pStr+n);
strcpy(temp+n, pStr);
*(temp + length) = '\0';
strcpy(pStr, temp);
}
(2) void LoopMove(char* pStr, int steps)
{
int length = strlen(pStr);
int n = steps % length;
char temp[256];
memcpy(temp, pStr+n, (length - n));
memcpy(temp + (length-n), pStr, n);
memcpy(pStr, temp, length);
}
编写类String的构造函数,析构函数和赋值函数
已知类String的原型如下,*编写类String的构造函数,析构函数和赋值函数
class String
{
public:
String(const char* str = NULL);
String(const String& other);
~String(void);
String& operator = (const String& other);
private:
char* m_data;
};
String::String(const char* str = NUlL)
{
if(str == NULL)
{
m_data = new char[1];
m_data[0] = '\0';
}
else
{
int length = strlen(str);
m_data = new char[length+1];
strcpy(m_data,str);
}
}
String::~String(void)
{
delete[] m_data;
}
String::String(const String& other)
{
int length = strlen(other.m_data);
m_data = new char[length+1];
strcpy(m_data, other.m_data);
}
String& String::operator = (const String& other)
{
if(this == &other)
return *this;
delete [] m_data;
int length = strlen(other.m_data);
m_data = new char[length+1];
strcpy(m_data,other.m_data);
return *this;
}
写一个C函数,判断不同模式处理器的返回值
int checkCPU()
{
union
{
int a;
char b;
}u;
u.a = 1;
return (u.b == 1);
}
写一个函数返回1+2+3…+n的值
long Sum(int n)
{
long sum = 0;
for(int i=1;i<=n;i++)
{
sum += i;
}
return sum;
}
long Sum(int n)
{
return (long)(n+1)*n / 2;
}
找出两个数中最大的一个
int max = ((a+b)+abs(a-b)) / 2;
打印出当前源文件的文件名及当前行号
printf("File:%s,Line:%ld\n",__FILE__,__LINE__);
main函数执行完毕后,是否可能会再执行一段代码
- 会执行另一些代码,进行处理工作;
- 可以使用atexit()函数(注册结束函数),注册一个函数
- atexit()注册的函数类型为不接受任意参数的void函数,exit调用atexit()函数的顺序与它们登记时候的顺序相反
一个关于指针的问题
int c[3][3] = {1,2,3,4,5,6,7,8,9};
- c是数组名,是一个二维指针,它的值就是数组的首地址,也即第一行元素的首地址
- *c:第一行元素的首地址,是一个一维地址
- **c:二维数组的第一个元素的值,即:c[0][0]
- (c+1):c是行指针,(c+1)是在c的基础上加上二维数组一行的地址长度,即从&c[0][0]变到&c[1][0]
- (*c+1):*c是列指针,(*c+1)是在 *c 的基础上加上二维数组一个元素的长度,即从&&c[0][0]变到&&c[0][1];
已知strcpy()的函数原型为char* strcpy(char* strDest, const char* strSrc),要求不调用C++/C的字符串库函数,编写函数strcpy
char* strcpy(char* strDest,const char* strSrc)
{
if((strDest == NULL) || (strSrc == NULL))
return NULL;
if(strDest == strSrc)
return strDest;
char* tempptr = strDest;
while((*strDest++ = *strSrc++) != '\0')
return tempptr;
}
数组和指针的区别
- 用运算符sizeof可以计算出数组的容量(字节数),而sizeof(p),p为指针得到的是指针变量的字节数,而不是p所指的内存容量。
- 数组作为函数的参数进行传递时,该数组自动退化为同类型的指针
- 修改内容上的差别;char* p = “world”;p[0] = ‘X’;p指向常量字符串,编译器不能发生错误,运行时错误
关于C/C++编译器的问题
如何判断一段程序是由C编译器编译的还是由C++编译器编译的?
#ifdef __cplusplus
cout << "C++";
#else
cout << "C";
#endif
文件中有一组整数,要求排序输出到另外一个文件
#include <iostream>
#incldue <fstream>
#include <vector>
int main()
{
vector<int> data;
iftream in("C:\\data.txt");
if(!in)
{
cout << "file error!":
exit(1);
}
int temp;
while(!in.eof())
{
in >> temp;
data.push_back(temp);
}
in.close();
Sort(data);//冒泡排序
ofstream out("C:\\result.txt");
if(!out)
{
cout << "file error!";
exit(1);
}
for(int i=0;i<data.size();i++)
out << data[i] << " ";
out.close();
}
找出一个整数数组中的第二大数
int类型(8位)的取值范围:(-2的15次方)(2的15次方-1)
int find_Sec_Max(int data[],int count)
{
int maxNum = data[0];
int secMax = -32768;
for(int i=1;i<count;i++)
{
if(data[i] > maxNum)
secNum = maxNum;
maxNum = data[i];
else
{
if(data[i] > secNum)
secNum = data[i];
}
}
return secNum;
}
判断一个单链表有环
已知:struct node{char var; node* next};
bool check(const node* head){}
bool check(const node* head)
{
if(node == NULL)
return false;
node* slow = head;
node* fast = head->next;
while((fast != NULL)&&(fast->next != NULL))
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
return true;
}
return false;
}
一个关于如何处理溢出的问题
定义了int a,b,c,请写函数实现c=a+b。要求不能改变数据类型,如c改为long int。关键是如何处理溢出
bool add(int a,int b, int* c)
{
*c = a + b;
return ((a > 0)&&(b > 0)&&(*c < a || *c <b)) || ((a < 0)&&(b < 0)&&(*c > a || *c > b));
}
如何用C语言将一个字符转换成整形
long atol(const char* nptr)
{
if(nptr == NULL)
{
return -1;
}
int length = strlen(nptr);
long array[256];
int ret = 0;
for(int i=0;i<length;i++)
{
long temp = nptr[i] - 48;
array[i] = temp;
ret = ret + array[i] * pow(10,length-i-i)
}
}
volatile含义,并给出三个不同的例子
- 定义为volatile的变量就是说变量可能会被意想不到地改变,每次用到这个变量编译器不会去优化,使用保存在寄存器里的备份,而是每次小心地去内存重新读取这个变量的值
- 并行设备的硬件寄存器(状态寄存器)
- 一个中断服务子程序中访问到的非自动变量
- 多线程间共享的变量
一个参数既可以是const还可以是volatile吗
- 可以,比如状态寄存器,它是volatile因为它可能被意想不到地改变;它是const因为程序不应该视图去修改它
一个指针可以是volatile吗
可以,比如一个中断服务子程序修改一个指向一个buffer的指针时
int square(volatile int* ptr) { return *ptr * *ptr;//int a,b; a = *ptr; b = *ptr; return a * b; }
由于*ptr的值可能被意想不到地改变,所以a和b的值可能是不同的