整数文字列と文字列を整数に変換

6518 ワード

1、は関数itob(n,s,b)を記述し、整数nをbをベースとした数に変換し、結果を文字として文字列sに保存する.例えばitob(n,s,16)は、整数nを16進数整数にフォーマットしてsに保存する.
ここで本に提供されている答えに使われているdoを修正しました..whileサイクルをforサイクルに変更
the c programming languageの本で実現されたソースは:
void itob(int n , char s[], int b)
{
	static char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	int i = 0;
	int sign = n;

	if(b < 2 || b > 36)
	{
		fprintf(stderr, "EX3_5: Cannot support base %d
", b); exit(1); } if (sign < 0) { n = -n; } do { s[i++] = digits[n%b]; } while ((n /= b) > 0); if (sign < 0) { s[i++]= '-'; } s[i] = '\0'; reverse(s); }

使用するforループを次のように変更します.
void itob1(int n , char s[], int b)
{
	static char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	int i = 0;
	int sign = n;

	if(b < 2 || b > 36)
	{
		fprintf(stderr, "EX3_5: Cannot support base %d
", b); exit(1); } if (sign < 0) { n = -n; } for (;((n/b) > 0)|((n%b) !=0);n/= b) { s[i++] = digits[n%b]; } if (sign < 0) { s[i++]= '-'; } s[i] = '\0'; reverse(s); }

ソースコード全体およびテストコードは次のとおりです.
#include 
using namespace std;

void reverse(char s[]);
void itob(int n , char s[], int b);
void itob1(int n , char s[], int b);

int main(int argc ,char **argv)
{
	char buffer[10];
	int i;

	for ( i = 2; i <= 20; ++i ) 
	{
		itob(255, buffer, i);
		printf("Decimal 255 in base %-2d : %s
", i, buffer); } return 0; } void reverse(char s[]) { int i, j; char c; for (i = 0, j = strlen(s) - 1; i < j; i++, j--) { c = s[i]; s[i] = s[j]; s[j] =c; } } /*-------------------------------------- n b s ---------------------------------------*/ void itob(int n , char s[], int b) { static char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; int i = 0; int sign = n; if(b < 2 || b > 36) { fprintf(stderr, "EX3_5: Cannot support base %d
", b); exit(1); } if (sign < 0) { n = -n; } do { s[i++] = digits[n%b]; } while ((n /= b) > 0); if (sign < 0) { s[i++]= '-'; } s[i] = '\0'; reverse(s); } void itob1(int n , char s[], int b) { static char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; int i = 0; int sign = n; if(b < 2 || b > 36) { fprintf(stderr, "EX3_5: Cannot support base %d
", b); exit(1); } if (sign < 0) { n = -n; } for (;((n/b) > 0)|((n%b) !=0);n/= b) { s[i++] = digits[n%b]; } if (sign < 0) { s[i++]= '-'; } s[i] = '\0'; reverse(s); }

2、タイトル:整数を表す文字列を入力し、その文字列を整数に変換して出力します.例えば、文字列「345」を入力すると、整数345が出力される.分析:この問題は難しくないが、C/C++言語を学んだことがあると基本的な機能が実現できるのが一般的だが、プログラマーによってこの問題に書かれたコードには大きな違いがあり、プログラマーの思考とプログラミング習慣をよく反映していると言えるため、すでにマイクロソフトを含む多くの会社が面接問題として使われている.読者は下を見る前に自分でコードを書いてから、自分が書いたコードと下の参考コードの違いを比較することをお勧めします.まず,整数を表す文字列を正確に整数に変換する方法として,基本機能をどのように達成するかを解析する.やはり「345」を例に挙げます.文字列の最初の文字'3'をスキャンすると、後ろに何ビットあるか分かりませんが、これが最初の文字であることを知っているだけで、このとき得られた数字は3です.2番目の数字「4」をスキャンすると、前に3があることがわかり、後ろに4が付いていることがわかります.前の3は30に相当します.そのため、得られた数字は3*10+4=34です.次に文字「5」をスキャンし、「5」の前に34があることを知った.後に5を加えると、前の34は340に相当するので、得られた数字は34*10+5=345である.ここまで分析すると、スキャンするたびに、前に得られた数字に10を乗じて現在の文字が表す数字を加える変換の考え方は得られません.この考え方は循環で実現するのは難しくない.整数は数字だけでなく、'+'または'-'で始まる可能性があるため、整数の正負を表すことができます.そのため、この文字列の最初の文字を特別に処理する必要があります.最初の文字が'+'番号の場合、何もする必要はありません.最初の文字が'-'番号であれば、この整数は負数であることを示し、最後に得られた数値を負数にします.次に不正入力を処理してみます.ポインタを入力するので、ポインタを使用する前に、私たちが最初にしなければならないのは、このポインタが空であるかどうかを判断することです.空のポインタにアクセスしてみると、プログラムがクラッシュすることは避けられません.また、入力した文字列には数字ではない文字が含まれている場合があります.これらの不正な文字に遭遇するたびに、変換を続ける必要はありません.最後に考慮すべき問題はオーバーフロー問題である.入力された数字は文字列で入力されるため、大きな数値変換を入力すると表示できる最大の整数を超えてオーバーフローする可能性があります.今では分析の差が少なく、コードの作成を考え始めました.まず、この関数をどのように宣言するかを考えます.文字列を整数に変換するので、int StrToInt(const char*str);このような声明は問題ないように見えます.しかし、入力した文字列が空のポインタまたは不正な文字が含まれている場合、どの値を返すべきですか?0はどうですか.では、不正入力と文字列自体が「0」であることをどのように区別しますか?次に別の考えを考えます.入力が有効かどうかを示すブール値を返し、変換された整数をパラメータリストに配置して参照またはポインタとして入力できます.bool StrToInt(const char*str,int&num);この考え方は前の問題を解決した.しかし、この関数のユーザーはこの関数を使うとき、得られた整数を直接他の整形変顔に与えることができず、直感的ではないと感じます.前の最初の声明は直感的だ.直感的な前提で不正入力に遭遇したときにユーザーに通知するにはどうすればいいのでしょうか.1つの解決策は、不正な入力に遭遇するたびにグローバル変数をマークするグローバル変数を定義することです.ユーザは、この関数を呼び出した後、グローバル変数を検証して変換が成功したかどうかを判断することができる.次に、完全な実装コードを書きます.参照コード: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); }
ディスカッション:リファレンスコードでは、最初の宣言方法を選択します.しかし、面接では、任意の声明方式で実現することができます.しかし、面接官が私たちに選択の理由を聞いたとき、私たちは両者の長所と短所を評価しなければなりません.第1の宣言方式はユーザーにとって非常に直感的であるが、グローバル変数を使用しており、優雅ではない.第2の考え方は,入力が正当であるか否かを返す値で示すことであり,多くのAPIでこの方法が用いられているが,この方法で宣言された関数は直感的に使用されていない.最後に,C言語で提供されるライブラリ関数では,関数atoiが文字列を整数に変換できる.その宣言はint atoi(const char*str)です.この関数は、入力が合法かどうかを示すグローバル変数です.