c string 面试题

1.将一个链表逆序

第一种方法:
1、将第一个结点的next置为NULL
2、用指针保存第二,第三结点
3、将第二个结点的next指向第一个结点
4、依次循环,直到最后一个结点指向前一个结点
5、将头结点的next指向最后一个结点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void Reseave(Lnode *head)
{
   Lnode *pFirst,*pCurrent,*pNext;
   pFirst = head->next; //第一个结点
   pCurrent = pFirst->next; //第二个结点
 
   pFirst->next = NULL; //将第一个结点的next置为NULL;
   pNext = pCurrent; //初始化pNext
 
   while (pCurrent != NULL)
   {
      pNext = pCurrent->next; //保存后续的结点
      pCurrent->next = pFirst; //将当前结点指向前一个结点
 
      pFirst = pCurrent;  //pFirst、pCurrent指针往后移动
      pCurrent = pNext;
   }
   head ->next = pFirst;
}

第二种方法:
与第一种方法的主要区别是,head的next域始终指向当前处理的结点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void Reseave(Lnode *head)
{
   Lnode *p,q;
   p=head->next;
   head->next=NULL;
 
   while (p)
  {
    q=p->next; //保存p的后续结点
    p->next=head->next;
    head->next=p;
    p=q; //p向后移动
   }
}


2、计算一个字节里(byte)里面有多少bit被置1
算法一

int count_ones(unsigned a)
{
    int count = 0;

    for (; a; a >>= 1) {
        if (a & 1) count ++;
    }

    return count;
}
算法二

int count_ones(unsigned a)
{
    int count = 0;

    for (; a; count ++) {
        a &= a - 1;
    }

    return count;
}



3.在一个字符串中找到可能的最长的子字符串
1。编写一个 C 函数,该函数在一个字符串中找到可能的最长的子字符串,且该字符串是由同一字符组成的。
char * search(char *cpSource, char ch)
{
         char *cpTemp=NULL, *cpDest=NULL;
         int iTemp, 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)
break;
                 }
                 ++cpSource;
}
return cpDest;
}     
2。请编写一个 C 函数,该函数在给定的内存区域搜索给定的字符,并返回该字符所在位置索引值。
int search(char *cpSource, int n, char ch)
{
         int i;
         for(i=0; i<n && *(cpSource+i) != ch; ++i);
         return i;
}
一个单向链表,不知道头节点,一个指针指向其中的一个节点,问如何删除这个指针指向的节点?
将这个指针指向的next节点值copy到本节点,将next指向next->next,并随后删除原next指向的节点。
 
 
 
#include <stdio.h>
void foo(int m, int n)
{
    printf("m=%d, n=%d\\n", m, n);
}
 

int main()
{
    int b = 3;
    foo(b+=3, ++b);
    printf("b=%d\\n", b);
return 0;
}
输出:m=7,n=4,b=7(VC6.0)
这种方式和编译器中得函数调用关系相关即先后入栈顺序。不过不同
编译器得处理不同。也是因为C标准中对这种方式说明为未定义,所以
各个编译器厂商都有自己得理解,所以最后产生得结果完全不同。
因为这样,所以遇见这种函数,我们首先要考虑我们得编译器会如何处理
这样得函数,其次看函数得调用方式,不同得调用方式,可能产生不同得
结果。最后是看编译器优化。
 
 
 
2.写一函数,实现删除字符串str1中含有的字符串str2.
第二个就是利用一个KMP匹配算法找到str2然后删除(用链表实现的话,便捷于数组)
 
 
 
/*雅虎笔试题(字符串操作)
给定字符串A和B,输出A和B中的最大公共子串。
比如A="aocdfe" B="pmcdfa" 则输出"cdf"
*/
//Author: azhen
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
 

char *commanstring(char shortstring[], char longstring[])
{
int i, j;
 

char *substring=malloc(256);
 

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

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)
return substring;
}
}
return NULL;
}
 
 
 
main()
{
char *str1=malloc(256);
char *str2=malloc(256);
char *comman=NULL;
 

gets(str1);
gets(str2);
 

if(strlen(str1)>strlen(str2))                         //将短的字符串放前面
comman=commanstring(str2, str1);
else
comman=commanstring(str1, str2);
 

printf("the longest comman string is: %s\\n", comman);
}
 
 
 
11.写一个函数比较两个字符串str1和str2的大小,若相等返回0,若str1大于
str2返回1,若str1小于str2返回-1
int strcmp ( const char * src,const char * dst)
{
        int ret = 0 ;
        while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
{
                ++src;
++dst;
}
        if ( ret < 0 )
                ret = -1 ;
        else if ( ret > 0 )
                ret = 1 ;
        return( ret );
}
 

3,求1000!的未尾有几个0(用素数相乘的方法来做,如72=2*2*2*3*3);
求出1->1000里,能被5整除的数的个数n1,能被25整除的数的个数n2,能被125整除的数的个数n3,
能被625整除的数的个数n4.
1000!末尾的零的个数=n1+n2+n3+n4;
#include<stdio.h>
#define NUM 1000
 

int find5(int num){
int ret=0;
while(num%5==0){
num/=5;
ret++;
}
return ret;
}
int main(){
int result=0;
int i;
for(i=5;i<=NUM;i+=5)
{
result+=find5(i);
}
printf(" the total zero number is %d\\n",result);
return 0;
}
 
 
 
 
 
 
1. 有双向循环链表结点定义为:
struct node
{ int data;
struct node *front,*next;
};
有两个双向循环链表A,B,知道其头指针为:pHeadA,pHeadB,请写一函数将两链表中data值相同的结点删除
BOOL DeteleNode(Node *pHeader, DataType Value)
{
if (pHeader == NULL) return;
 

BOOL bRet = FALSE;
Node *pNode = pHead;
while (pNode != NULL)
{
if (pNode->data == Value)
{
if (pNode->front == NULL)
{
pHeader = pNode->next;
pHeader->front = NULL;
}
else
{
if (pNode->next != NULL)
{
pNode->next->front = pNode->front;
}
pNode->front->next = pNode->next;
}
 

Node *pNextNode = pNode->next;
delete pNode;
pNode = pNextNode;
 

bRet = TRUE;
//不要break或return, 删除所有
}
else
{
pNode = pNode->next;
}
}
 

return bRet;
}
 

void DE(Node *pHeadA, Node *pHeadB)
{
if (pHeadA == NULL || pHeadB == NULL)
{
return;
}
 

Node *pNode = pHeadA;
while (pNode != NULL)
{
if (DeteleNode(pHeadB, pNode->data))
{
if (pNode->front == NULL)
{
pHeadA = pNode->next;
pHeadA->front = NULL;
}
else
{
pNode->front->next = pNode->next;
if (pNode->next != NULL)
{
pNode->next->front = pNode->front;
}
}
Node *pNextNode = pNode->next;
delete pNode;
pNode = pNextNode;
}
else
{
pNode = pNode->next;
}
}
}
2. 编程实现:找出两个字符串中最大公共子字符串,如"abccade","dgcadde"的最大子串为"cad"
int GetCommon(char *s1, char *s2, char **r1, char **r2)
{
int len1 = strlen(s1);
int len2 = strlen(s2);
int maxlen = 0;
 

for(int i = 0; i < len1; i++)
{
for(int j = 0; j < len2; j++)
{
if(s1[i] == s2[j])
{
int as = i, bs = j, count = 1;
while(as + 1 < len1 && bs + 1 < len2 && s1[++as] == s2[++bs])
count++;
 

if(count > maxlen)
{
maxlen = count;
*r1 = s1 + i;
*r2 = s2 + j;
}
}
}
}
3. 编程实现:把十进制数(long型)分别以二进制和十六进制形式输出,不能使用printf系列库函数
char* test3(long num) {
char* buffer = (char*)malloc(11);
buffer[0] = \'0\';
buffer[1] = \'x\';
buffer[10] = \'\\0\';
 

char* temp = buffer + 2;
for (int i=0; i < 8; i++) {
temp[i] = (char)(num<<4*i>>28);
temp[i] = temp[i] >= 0 ? temp[i] : temp[i] + 16;
temp[i] = temp[i] < 10 ? temp[i] + 48 : temp[i] + 55;
}
return buffer;
}
 
 
 
 
 
 
输入N, 打印 N*N 矩阵
比如 N = 3,打印:
 

1  2  3
8  9  4
7  6  5
 

N = 4,打印:
 

1   2   3   4
12  13  14  5
11  16  15  6
10  9   8   7
解答:
1 #define N 15
int s[N][N];
void main()
{
int k = 0, i = 0, j = 0;
int a = 1;
for( ; k < (N+1)/2; k++ )
{
while( j < N-k ) s[i][j++] = a++; i++; j--;
while( i < N-k ) s[i++][j] = a++; i--; j--;
while( j > k-1 ) s[i][j--] = a++; i--; j++;
while( i > k )   s[i--][j] = a++; i++; j++;
}
for( i = 0; i < N; i++ )
{
for( j = 0; j < N; j++ )
cout << s[i][j] << \'\\t\';
cout << endl;
}
}
2 define MAX_N  100
int matrix[MAX_N][MAX_N];
 

/*
*(x,y):第一个元素的坐标
* start:第一个元素的值
* n:矩阵的大小
*/
void SetMatrix(int x, int y, int start, int n) {
    int i, j;
 

    if (n <= 0)    //递归结束条件
        return;
    if (n == 1) {  //矩阵大小为1时
        matrix[x][y] = start;
        return;
    }
    for (i = x; i < x + n-1; i++)   //矩阵上部
        matrix[y][i] = start++;
 

    for (j = y; j < y + n-1; 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);   //递归
}
 

void main() {
   int i, j;
   int n;
 

   scanf("%d", &n);
   SetMatrix(0, 0, 1, n);
  
   //打印螺旋矩阵
   for(i = 0; i < n; i++) {
      for (j = 0; j < n; j++)
printf("%4d", matrix[i][j]);
      printf("\\n");
   }
}
 
 
 
斐波拉契数列递归实现的方法如下:
int  Funct( int n )
{
   if(n==0) return 1;
   if(n==1) return 1;
   retrurn  Funct(n-1) + Funct(n-2);
}
请问,如何不使用递归,来实现上述函数?
请教各位高手!
解答:int  Funct( int n )  //  n 为非负整数
{
   int a=0;
   int b=1;
   int c;
   if(n==0) c=1;
   else if(n==1) c=1;
   else for(int i=2;i<=n;i++)  //应该n从2开始算起
   {
     c=a+b;
     a=b;
     b=c;
   }
   return c;
}
解答:
现在大多数系统都是将低字位放在前面,而结构体中位域的申明一般是先声明高位。
100  的二进制是 001 100 100
低位在前   高位在后 
001----s3
100----s2
100----s1
所以结果应该是 1
如果先申明的在低位则:
001----s1
100----s2
100----s3
结果是 4
1、原题跟little-endian,big-endian没有关系
2、原题跟位域的存储空间分配有关,到底是从低字节分配还是从高字节分配,从Dev C++和VC7.1上看,都是从低字节开始分配,并且连续分配,中间不空,不像谭的书那样会留空位
3、原题跟编译器有关,编译器在未用堆栈空间的默认值分配上有所不同,Dev C++未用空间分配为
01110111b,VC7.1下为11001100b,所以在Dev C++下的结果为5,在VC7.1下为1。
 

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



4.字符串转换为整数
要这样
int i;
String s1="134";
i=Integer.parseInt(s1);
这样才行要是翻过来要用
Integer.toString()

String转换为int型
//convert str(String) to i(int)
String str;
int i = Integer.parseInt(str);



int型转换为String
//conver i(int) to str(String)
int i;
String str = i.toString();




//convert i(int) to j(Integer)
int i;
Integer j = Integer.valueOf(i);

//convert t(Integer) to n (int)
Integer t;
int n = t.intValue();



itoa() 将整型值转换为字符串
itoa() 将长整型值转换为字符串
ultoa() 将无符号长整型值转换为字符串
一、atoi()——把字符串转换成整型数

示例例程序:
#include <ctype.h>
#include <stdio.h>
int atoi (char s[]);
int main(void )
{ 
char s[100];
gets(s);
printf("integer=%d\n",atoi(s));
return 0;
}
int atoi (char s[])
{
int i,n,sign;
for(i=0;isspace(s[i]);i++)//跳过空白符;
sign=(s[i]=='-')?-1:1;
if(s[i]=='+'||s[i]==' -')//跳过符号
 i++;
for(n=0;isdigit(s[i]);i++)
      n=10*n+(s[i]-'0');//将数字字符转换成整形数字
return sign *n;
}
二、itoa()——把一整数转换为字符串

例程序:
#include <ctype.h>
#include <stdio.h>
void      itoa (int n,char s[]);
//atoi 函数:将s转换为整形数
int main(void )
{ 
int n;
char s[100];
printf("Input n:\n");
scanf("%d",&n);
printf("the string : \n");
itoa (n,s);
return 0;
}
void itoa (int n,char s[])
{
int i,j,sign;
if((sign=n)<0)//记录符号
n=-n;//使n成为正数
i=0;
do{
      s[i++]=n%10+'0';//取下一个数字
}
while ((n/=10)>0);//删除该数字
if(sign<0)
s[i++]='-';
s[i]='\0';
for(j=i;j>=0;j--)//生成的数字是逆序的,所以要逆序输出
      printf("%c",s[j]);
} 
是int 转string类型的一个函数




5.整数转换为字符串


  1. /** 
  2.  * 将数字字符串转换为整数 
  3.  */ 
  4. #include <stdio.h> 
  5. #include <ctype.h> 
  6.  
  7. int ascii_to_integer( char * string ); 
  8.  
  9. int main() 
  10.     char str[] = "123456"
  11.     int result ; 
  12.  
  13.     result = ascii_to_integer(str); 
  14.     printf("%d\n",result); 
  15.     return 1; 
  16.  
  17. int ascii_to_integer( char * string ) 
  18. {    
  19.     int number = 0 ; 
  20.  
  21.     while( *string >= '0' && *string <= '9' ){ 
  22.         number *= 10; 
  23.         number += *string - '0';  
  24.         string++; 
  25.     } 
  26.     if( *string != '\0'){ 
  27.         number = 0; 
  28.     } 
  29.     return number; 




 

6、将一个字符串逆序


d)请编写一个 C 函数,该函数将一个字符串逆序。 
    
   #include <string.h>; 
#include <stdio.h>; 

exchange(char *str) 
{ 
   char tmp; 
   int len, i, j; 

   len = strlen(str); 
   for(i = 0, j = len-1; i != len/2; i++, j--) { 
      tmp = str[i]; 
      str[i] = str[j]; 
      str[j] = tmp; 
   } 

return; 
} 

main() 
{ 
   char str[100]; 
   scanf("%s", str); 
   exchange(str); 
   printf("%s\n", str); 
   return; 
}


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值