黑马程序员技术交流社区

标题: 【C语言字符串专题---第一部分】面试题解答分享 [打印本页]

作者: Jobs    时间: 2014-9-24 22:26
标题: 【C语言字符串专题---第一部分】面试题解答分享
一,字符串转化
        将字符串转换成整数:atoi
        将整数转换为字符串:itoa
         浮点数与字符串的转换
1)字符串转化为整数
        需要注意的地方:
                                       考虑要缜密,注意是否为数字字符;
                                       判断是否为NULL
                                       开头的‘+’‘-’符号的判断
[html]
#include "stdio.h"
#include "string.h"
#include "assert.h"

int isDigit(char c)
{
    if(c>='0'&&c<='9')
        return 1;
    else
        return 0;  
     
}  
int myatoi(const char *str)
{
    assert(str!=NULL);
    int count=strlen(str);
    int result=0;
     
    int sign=1;
    if(str[0]=='-')
    {
        sign=-1;  
    }  
    else if(str[0]=='+')
    {
        sign=1;  
    }  
    else if(isDigit(str[0]))  
    {
        result=str[0]-'0';
        sign=1;  
    }  
    for(int i=1;i<count;++i)
    {
        assert(isDigit(str[i]));
         
        result=result*10+(str[i]-'0');
    }
     
    return result;
     
     
}
int  main()
{
    printf("%d\n",myatoi("123"));
}

别看一个这么简单的问题,实际要考虑的问题很多。还是看一下glibc的实现吧
[html]
#include "stdio.h"
#include "string.h"
#include "assert.h"

#define LONG_MAX 2147483647L  
#define LONG_MIN (-2147483647L-1L)


long int _strtol_internal (const char *nptr, char **endptr, int base, int group)
{
    //注意要使用unsigned long否则会发生溢出,因为long int最多2147483647L ,无法表示2147483648L
    unsigned long int result = 0;
    long int sign = 1;
    //考虑前导空格
    while (*nptr == ' ' || *nptr == '\t')
        ++nptr;
    //考虑带有正负号
    if (*nptr == '-')
    {
        sign = -1;
        ++nptr;
    }
    else if (*nptr == '+')
        ++nptr;
        //如果出现非法输入
    if (*nptr < '0' || *nptr > '9')
    {
        if (endptr != NULL)
            *endptr = (char *) nptr;
        return 0L;
    }
    //考虑进制
    assert (base == 0);
    base = 10;
    if (*nptr == '0')
    {
        if (nptr[1] == 'x' || nptr[1] == 'X')
        {
            base = 16;
            nptr += 2;
        }
        else
            base = 8;
    }
    //防止非法字符  
    while (*nptr >= '0' && *nptr <= '9')
    {
        unsigned long int digval = *nptr - '0';

        //防止溢出,如果溢出了long的表示范围,则置errno  
        if (result > LONG_MAX / 10 || (sign > 0 ? result == LONG_MAX / 10 && digval > LONG_MAX % 10 :  
                  (result == ((unsigned long int) LONG_MAX + 1) / 10 && digval > ((unsigned long int) LONG_MAX + 1) % 10)))
        {
            errno = ERANGE;
            return sign > 0 ? LONG_MAX : LONG_MIN;
        }
        result *= base;
        result += digval;
        ++nptr;
    }
    return (long int) result * sign;
}

         atoi函数就是这个函数讲第二个参数置为NULL,第三个参数置为10。不知道你注意到了那些空格,越界之类的判断没有。我同学说他写出来的代码最后就被要求加上了这些东西,最后还因此被卡掉了(说是考虑不够慎密,汗)。
2)itoa 函数的实现
      char *itoa( int value, char *string,int radix);
      先看一看使用:
[html]
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
    int number = 12345;
    char string[25];
    itoa(number, string, 10); //按十进制转换
    printf("integer = %d string = %s\n", number, string);
    itoa(number, string, 16); //按16进制转换
    printf("integer = %d string = %s\n", number, string);
    return 0;
}  

整形转化为字符串(这里默认十进制的转换)
[html] view plaincopy
//整形转成字符串函数实现
//题目不难,重点考察面试者对问题考虑的全面程度
#include <iostream>
using namespace std;
void itoa_mf(int num,char str[])
{
    int sign = num;
    int i = 0;
    int j = 0;
    char temp[100];
    if(sign < 0)//如果是负数就去掉符号,将-1234转成1234
    {
        num = -num;
    }
     
    do//转成字符串,1234转成"4321"
    {
        temp[i] = num % 10 + '0';
        num /= 10;
        i++;
    }while(num > 0);
    if(sign < 0)//如果是负数的话,加个符号在末尾,如:"4321-"
    {
        temp[i++] = '-';
    }
    temp[i] = '\0';
    i--;
    //将temp数组中逆序输入到str数组中
    //将"4321-" ====> "-1234"
    while(i >= 0)
    {
        str[j] = temp[i];
        j++;
        i--;
    }
    //字符串结束标识
    str[j] = '\0';
}
int main()
{
    int a = +123;
    char s[100];
    itoa_mf(a,s);
    cout << s << endl;

}

二,找出字符串的最长子串,要求子串的所有字符相同
         例如:str ="sssddddabcdef"  则输出字串为:dddd
[html]
#include <stdlib.h>
#include <stdio.h>
#include <string.h>  
char* GetSubstring(char* strSource)
{
  char* strSubstring; //用于保存得到的子串,大小在找到最大子串后再确定,作为返回值
  int nLen;           //源字符串长度
  int nCurPos;        //当前统计字符串的头指针位置(相对于原字符串第一个字符的位置)
  int nCurCount;      //当前统计字符串的长度(有相同字符组成的子字符串)
  int nPos;          //当前最长的子串的头指针位置
  int nCount;        //当前最长的子串的长度

  nLen = strlen(strSource);

  //初始化变量
  nCount = 1;
  nPos = 0;
  nCurCount = 1;
  nCurPos = 0;

  //遍历整个字符串
  for(int i = 1; i < nLen; i++)
  {
    if(strSource[i] == strSource[nCurPos])//如果当前字符与子串的字符相同,子串长度增1
      nCurCount++;
    else  //如果不相同,开始统计新的子串
    {
      if(nCurCount > nCount)//如果当前子串比原先最长的子串长,把当前子串信息(起始位置 + 长度)保留下来
      {
        nCount = nCurCount;
        nPos = nCurPos;
      }
      //长度复值为1,新串的开始位置为i
      nCurCount = 1;
      nCurPos = i;
    }
  }

  //为返回的子串分配空间(长度为nCount,由于要包括字符串结束符\0,故大小要加1)   
  strSubstring = (char*)malloc(nCount + 1);

  //复制子串(用其他函数也可以)
  for(int i = 0; i < nCount; i++)
    strSubstring[i] = strSource[nPos + i];
  strSubstring[nCount] = '\0';

  return strSubstring;
}  

int main()
{
  //输入一个字符串strSource
  char *strSource="absceeeecd";  
  char* strSubstring = GetSubstring(strSource);

  printf("最长子串为:%s\n长度为:%d",strSubstring,strlen(strSubstring));

  //释放strSubstring
  free(strSubstring);
}



作者: Kevinneo    时间: 2014-9-24 22:41
介个。。。会有删帖的风险吧。。关于面试题的    不过总结的挺好,哈哈哈:lol  我先收啦
作者: fantacyleo    时间: 2014-9-24 22:50
itoa不是标准库函数,未必用得上。mac os貌似就没有
作者: Jobs    时间: 2014-9-25 12:39
我分享的都是纯C的题解,毕竟C是编程的基础,多掌握没坏处。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2