1. 程式人生 > >《劍指Offer》面試題:將字串轉換為整數

《劍指Offer》面試題:將字串轉換為整數

題目

題目:把字串轉化為整數 ,若輸入無效,則返回0且將標誌位設為true

自己以前在一些書上面看到過關於 字串轉化為整數的例子,心中有點印象,知道要考慮一些特殊情況。今天決定寫下這段程式碼,發現程式碼寫的稀爛,重複度太大,需要改善。

剛實現的程式碼如下:

/*
題目:把字串轉化為整數 ,若輸入無效,則返回0且將標誌位設為true; 

需要考慮的測試用例如下:
1)"123"
2)"+123"  //帶符號的正數輸入 
3)"-123"
4) "  abd123 " //非法輸入
5)  NULL 
*/

#include<stdio.h>
#include<string.h>


/*功能:檢查str中的字元是否全部是由數字構成 ,若是,則返回true,否則返回false 
@param str:字串
@param begin:字串的起始下標 
@parameter  end:字串的 終止下標 
*/
bool checkStr(char *str,int begin,int end){ if(begin<end){ for(int i=begin;i<end;i++){ if(!(str[i]>='0'&&str[i]<='9')){ return false; } } return true; } else{ return false; } } /* 開始轉換 */ int beginStringToNum(char
*str,int begin,int end){ int num=0; for(int i=begin;i<end;i++){ num=num*10+str[i]-'0'; } return num; } void strToNum(char *str){ bool str_illege=false; int num=0; //先檢查str是否有效 if(str==NULL||str==""){ str_illege=true; printf("%d %d\n",str_illege,num); return
; } int len=strlen(str); bool flag=false; if(str[0]=='+'){//若第一個字元為"+"時 flag=checkStr(str,1,len); if(flag){ num=beginStringToNum(str,1,len); } else{ str_illege=true; } } else if(str[0]=='-'){//若第一個字元是"-"時 flag=checkStr(str,1,len); if(flag){ num=beginStringToNum(str,1,len)*(-1); } else{ str_illege=true; printf("%d %d\n",str_illege,num); return; } } else{//第一個字元不是“=”和“-”的情況 flag=checkStr(str,0,len); if(flag){ num=beginStringToNum(str,0,len); } else{ num=0; str_illege=true; printf("%d %d\n",str_illege,num); return; } } printf("%d %d\n",str_illege,num); }

測試用例如下:

int main(void){
    char *str;
    //gets(str);
    //直接用測試用例來測試
    //正常情況下的3中不同的輸入 
    char str1[]="123";
    char str2[]="-123";
    char str3[]="+123";
    //只輸入一個"+"  或者是  "-"
    char str4[]="+" ;
    char str5[]="-";
    //不可以轉換的輸入
    char str6[]="abc123";
    char str7[]="";
    char *str8=NULL;
    strToNum(str1);
    strToNum(str2);
    strToNum(str3);
    strToNum(str4);
    strToNum(str5);
    strToNum(str6);
    strToNum(str7);
    strToNum(str8);
    return 0;
}

題目:輸入一個表示整數的字串,把該字串轉換成整數並輸出。例如輸入字串”345”,則輸出整數345。 分析:這道題儘管不是很難,學過C/C++語言一般都能實現基本功能,但不同程式設計師就這道題寫出的程式碼有很大區別,可以說這道題能夠很好地反應出程式設計師的思維和程式設計習慣,因此已經被包括微軟在內的多家公司用作面試題。

轉換的思路:每掃描到一個字元,我們把在之前得到的數字乘以10再加上當前字元表示的數字。這個思路用迴圈不難實現。
由於整數可能不僅僅只含有數字,還有可能以’+’或者’-‘開頭,表示整數的正負。因此我們需要把這個字串的第一個字元做特殊處理。如果第一個字元是’+’號,則不需要做任何操作;如果第一個字元是’-‘號,則表明這個整數是個負數,在最後的時候我們要把得到的數值變成負數。
接著我們試著處理非法輸入。由於輸入的是指標,在使用指標之前,我們要做的第一件是判斷這個指標是不是為空。如果試著去訪問空指標,將不可避免地導致程式崩潰。另外,輸入的字串中可能含有不是數字的字元。每當碰到這些非法的字元,我們就沒有必要再繼續轉換。最後一個需要考慮的問題是溢位問題。由於輸入的數字是以字串的形式輸入,因此有可能輸入一個很大的數字轉換之後會超過能夠表示的最大的整數而溢位。

enum Status {kValid = 0, kInvalid};
int g_nStatus = kValid;
///////////////////////////////////////////////////////////////////////
// Convert a string into an integer
///////////////////////////////////////////////////////////////////////
int StrToInt(const char* str)
{
       g_nStatus = kInvalid;
      long long num = 0;
      if(str != NULL)//至少保證字串不為空
       {
            const char* digit = str;//用了一下中間變數,儲存原始字串,防止被破壞
            // the first char in the string maybe '+' or '-'
            bool minus = false;
            if(*digit == '+')//通過第一個字元判斷是正是負
                   digit ++;
            else if(*digit == '-')
             {
                   digit ++;
                   minus = true;
             }
            // the remaining chars in the string
            while(*digit != '\0')//字串結束標誌
             {
                  if(*digit >= '0' && *digit <= '9')
                   {
                         num = num * 10 + (*digit - '0');
                        // overflow  
                        if(num > std::numeric_limits::max())//整數溢位的情況
                         {
                               num = 0;
                               break;
                         }
                         digit ++;
                   }
                  // if the char is not a digit, invalid input
                  else
                   {
                         num = 0;
                        break;
                   }
             }
            if(*digit == '\0')
             {
                   g_nStatus = kValid;
                  if(minus)
                         num = 0 - num;//轉化為負數的方式
             }
       }
       return static_cast(num);
}

相關推薦

Offer試題字串轉換整數

題目 題目:把字串轉化為整數 ,若輸入無效,則返回0且將標誌位設為true 自己以前在一些書上面看到過關於 字串轉化為整數的例子,心中有點印象,知道要考慮一些特殊情況。今天決定寫下這段程式碼,發現程式碼寫的稀爛,重複度太大,需要改善。 剛實現的程

Offer試題35.字串轉換數字

一、題目:將字串轉換為數字 題目:寫一個函式StrToInt,實現把字串轉換成整數這個功能。當然,不能使用atoi或者其他類似的庫函式。 二、程式碼實現   (1)考慮輸入的字串是否是NULL、空字串   (2)考慮輸入的字串是否包含正負號或者是否是隻包含正負號   (3)考慮輸入的字串是否

Offer試題34.翻轉單詞順序VS左旋轉字串

一、題目一:翻轉單詞順序 1.1 題目說明 題目一:輸入一個英文句子,翻轉句子中單詞的順序,但單詞內字元的順序不變。為簡單起見,標點符號和普通字母一樣處理。例如輸入字串"I am a student.",則輸出"student. a am I"。 1.2 解題思路   第一步翻轉句子中所有的字

offer 試題重建二叉樹

題目:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。 思路:二叉樹先序是根左右,中序 是左根右。所以先找到

offer 試題從尾到頭列印連結串列

題目:輸入一個連結串列,按連結串列值從尾到頭的順序返回一個ArrayList。 思路:有多種放法。(1)先反轉連結串列,再列印連結串列。(2)使用棧。 /** * struct ListNode { * int val; * struct ListNode *n

Offer試題17.樹的子結構

一、題目:樹的子結構 題目:輸入兩棵二叉樹A和B,判斷B是不是A的子結構。例如下圖中的兩棵二叉樹,由於A中有一部分子樹的結構和B是一樣的,因此B是A的子結構。   該二叉樹的節點定義如下,這裡使用C#語言描述: public class BinaryTreeNode {

Offer試題31.兩個連結串列的第一個公共節點

一、題目:兩個連結串列的第一個公共節點 題目:輸入兩個連結串列,找出它們的第一個公共結點。   連結串列結點定義如下,這裡使用C#語言描述: public class Node { public int key; public Node

Offer試題2.二維陣列中的查詢

一、題目:二維陣列中的查詢 題目:在一個二維陣列中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。     例如下面的二維陣列就是每行、每列都遞增排序。如果在這個陣列中查詢數字7,則返回true;

Offer試題22.二叉搜尋樹的後序遍歷序列

一、題目:二叉搜尋樹的後序遍歷序列 題目:輸入一個整數陣列,判斷該陣列是不是某二叉搜尋樹的後序遍歷的結果。如果是則返回true,否則返回false。假設輸入的陣列的任意兩個數字都互不相同。   例如在下面的一顆二叉搜尋樹中,輸入陣列{5,7,6,9,11,10,8},則返回true,因為這個整數序列是

Offer試題14.連結串列的倒數第k個節點

PS:這是一道出境率極高的題目,記得去年參加校園招聘時我看到了3次,但是每次寫的都不完善。 一、題目:連結串列的倒數第k個節點 題目:輸入一個連結串列,輸出該連結串列中倒數第k個結點。為了符合大多數人的習慣,本題從1開始計數,即連結串列的尾結點是倒數第1個結點。例如一個連結串列有6個結點,從頭結點開始

Offer試題28.連續子陣列的最大和

一、題目:連續子陣列的最大和 題目:輸入一個整型陣列,數組裡有正數也有負數。陣列中一個或連續的多個整陣列成一個子陣列。求所有子陣列的和的最大值。要求時間複雜度為O(n)。例如輸入的陣列為{1,-2,3,10,-4,7,2,-5},和最大的子陣列為{3,10,-4,7,2},因此輸出為該子陣列的和18。

Offer試題4.從尾到頭列印連結串列

一、題目:從尾到頭列印連結串列 題目:輸入一個連結串列的頭結點,從尾到頭反過來打印出每個結點的值。   到解決這個問題肯定要遍歷連結串列。遍歷的順序是從頭到尾的順序,可輸出的順序卻是從尾到頭。也就是說第一個遍歷到的結點最後一個輸出,而最後一個遍歷到的結點第一個輸出。這就是典型的“後進先出”,我

Offer試題10.數值的整數次方

一、題目:數值的整數次方 題目:實現函式double Power(doublebase, int exponent),求base的exponent次方。不得使用庫函式,同時不需要考慮大數問題。   在.NET Framework提供的BCL中,Math類實現了一個Pow方法,例如要求2的三次方,可

Offer試題6.用兩個棧實現佇列

一、題目:用兩個棧實現佇列 題目:用兩個棧實現一個佇列。佇列的宣告如下,請實現它的兩個函式appendTail和deleteHead,分別完成在佇列尾部插入結點和在佇列頭部刪除結點的功能。   原文是使用C++結合模板實現的定義,這裡我們採用C#結合泛型來實現這個佇列的定義,我們要實現的就是兩

Offer試題20.棧的壓入、彈出序列

一、題目:棧的壓入、彈出序列 題目:輸入兩個整數序列,第一個序列表示棧的壓入順序,請判斷第二個序列是否為該棧的彈出順序。假設壓入棧的所有數字均不相等。例如序列1、2、3、4、5是某棧的壓棧序列,序列4、5、3、2、1是該壓棧序列對應的一個彈出序列,但4、3、5、1、2就不可能是該壓棧序列的彈出序列。

Offer試題30.第一個只出現一次的字元

一、題目:第一個只出現一次的字元 題目:在字串中找出第一個只出現一次的字元。如輸入"abaccdeff",則輸出'b'。要求時間複雜度為O(n)。   最直觀的想法是從頭開始掃描這個字串中的每個字元。當訪問到某字元時拿這個字元和後面的每個字元相比較,如果在後面沒有發現重複的字元,則該字元就是隻出現

Offer試題23.二叉樹中和某一值的路徑

一、題目:二叉樹中和為某一值的路徑 題目:輸入一棵二叉樹和一個整數,打印出二叉樹中結點值的和為輸入整數的所有路徑。從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。例如輸入下圖中二叉樹和整數22,則打印出兩條路徑,第一條路徑包含結點10、12,第二條路徑包含結點10、5和7。   二叉

Offer試題11.列印1到最大的n位數

一、題目:列印1到最大的n位數 題目:輸入數字n,按順序打印出從1最大的n位十進位制數。比如輸入3,則打印出1、2、3一直到最大的3位數即999。 二、不同的解法 2.1 不假思索的解法   最容易想到的辦法是先求出最大的n位數,然後用一個迴圈從1開始逐個列印: static v

Offer試題13.調整陣列順序使奇數位於偶數前面

一、題目:調整陣列順序使奇數位於偶數前面 題目:輸入一個整數陣列,實現一個函式來調整該陣列中數字的順序,使得所有奇數位於陣列的前半部分,所有偶數位於陣列的後半部分。   例如有以下一個整數陣列:12345,經過調整後可以為:15342、13542、13524等等。 二、解題思路 2.1 基本解

Offer試題32.數字在排序陣列中出現的次數

一、題目:數字在排序陣列中出現的次數 題目:統計一個數字在排序陣列中出現的次數。例如輸入排序陣列{1,2,3,3,3,3,4,5}和數字3,由於3在這個陣列中出現了4次,因此輸出4。 二、解題思路 2.1 直接運用二分查詢   既然輸入的陣列是排序的,那麼我們很自然地就能想到用二分查詢演算法。