1. 要件の説明 文字列を入力し、文字列内の単語を逆順に組み立てて出力するプログラムを作成します。たとえば、入力文字列が「Hello, how do you do」の場合、出力文字列は「do you do how Hello」になります。単語と対応する句読点の間には必ずスペースを入れてください。 2. アルゴリズム設計 例の文字列 (つまり、「こんにちは、お元気ですか」) を観察すると、文字列内の単語とスペースの関係が、単語の総数 = スペースの総数 + 1 であることがわかります。つまり、例の文字列内のスペースの合計数は 4 で、単語の数は 5 です (つまり、「Hello」、「how」、「do」、「you」、「do」)。 したがって、最初に入力文字列内のスペースの合計数を見つけ、次にスペースに基づいて各単語を見つけ、最後にこれらの単語を逆の順序で組み立てることを検討できます。 プログラムの全体的な流れを図 1 に示します。 図1 プログラムの全体的なプロセス 3. 特別なプロセスに関する考慮事項 プログラムを作成する過程では、次のような入力文字列の形式を考慮する必要があります。 1. 入力文字列の最初の数文字はスペースです。つまり、「Hello, how do you do」という形式の場合、後続の処理に進む前に最初の数文字のスペースを削除する必要があります。 2. 入力文字列の最後の数文字はスペースです。つまり、「Hello, how do you do」の形式では、後続の処理に進む前に最後の数文字のスペースを削除する必要があります。 3. 入力文字列の中央の文字は、「Hello, how do you do」のように連続したスペースです。後続の処理に進む前に、連続したスペースを 1 つのスペースに結合する必要があります。 4. 入力文字列内の 2 つの単語の間にスペースがある場合は、その 2 つの単語に実際の意味がない場合でも、それらを 2 つの異なる単語として扱います。つまり、「Hello, how do y ou do」という形式では、「y」と「ou」を結合して意味を成す必要がありますが、それでも 2 つの異なる単語として扱います。 4. プログラムコード - /******************************************************************************************
- * 著作権 (C) 2016、Zhou Zhaoxiong。
- *
- * ファイル名: ReverseTheString.c
- * ファイルID: なし
- * 概要: 文字列内の単語の順序を逆にする
- * その他の指示: たとえば、「私は学生です」を「学生です」に変更します
- * 現在のバージョン: V1.0
- * 著者: 周昭雄
- * 完成日: 20160215
- *
- ******************************************************************************/
- #include < stdio.h >
- #include < stdlib.h >
-
- // データ型を再定義する
- typedef signed char INT8;
- typedef 符号なし短整数 UINT16;
- 型定義 int INT32;
- typedef 符号なし int UINT32;
-
- // 関数宣言
- INT32 GetFieldFromString(INT8 *pszIn、INT8 cSplitter、UINT16 iIdx、INT8 *pszOut、UINT16 iLen);
- void CombineSpace(INT8 *pszOldStr, INT8 *pszNewStr);
-
-
- /******************************************************************************************
- * 機能説明: 主な機能
- * 入力パラメータ: なし
- * 出力パラメータ: なし
- * 戻り値: 0 - 実行成功 その他 - 実行失敗
- * その他の指示: なし
- * 変更日 バージョン番号 修正者 変更内容
- * ---------------------------------------------------------------------
- * 20160215 V1.0 作成者: Zhou Zhaoxiong
- ******************************************************************************/
- INT32 メイン()
- {
- INT8 szTestStr[500] = {0};
- INT8 szTmpStr[500] = {0}; // 正規化後の文字列を格納するために使用
- INT8 szResultStr[500] = {0};
- INT8 szFieldVal[100] = {0};
- INT32 iPosFlag = 0 ;
- INT32 iRetFlag = 0 ;
- UINT32 iBlankCount = 0 ;
-
- printf("文字列を入力してください: \n");
- szTestStr を取得します。
- printf(" TestStr =%s\n", szTestStr);
-
- // テスト文字列内の余分なスペースと先頭と末尾のスペースを削除します
- スペースを結合します(szTestStr、szTmpStr);
-
- // テスト文字列内のスペース文字の数を取得します
- iPosフラグ= 0 ;
- (szTmpStr[iPosFlag] != '\0') の間
- {
- szTmpStr[iPosFlag] == ' ' の場合
- {
- iBlankCount++;
- }
-
- iPosFlag++;
- }
-
- // テスト文字列内の単語を逆順に連結する
- strcat(szTmpStr, " "); // テスト文字列の最初の部分にスペースを追加して各単語を解析します
- ( iPosFlag = iBlankCount ; iPosFlag > = 0; iPosFlag --)の場合
- {
- memset(szFieldVal, 0x00, sizeof(szFieldVal));
- iRetFlag = GetFieldFromString (szTmpStr、' '、iPosFlag、szFieldVal、sizeof(szFieldVal)-1);
- (iRetFlag != 0) の場合
- {
- printf("FieldVal を取得するための GetFieldFromString の実行に失敗しました!\n");
- -1 を返します。
- }
-
- if (strlen(szResultStr) > sizeof(szResultStr)-1) // 文字列が長すぎるので、そのまま終了します
- {
- 壊す;
- }
- それ以外
- {
- strcat(szResultStr, szFieldVal); // 単語を連結する
- strcat(szResultStr, " "); // 各単語の後にスペースを追加します
- }
- }
-
- (szResultStr[strlen(szResultStr)-1] == ' ')の場合
- {
- szResultStr[strlen(szResultStr)-1] = '\0'; // 最初のページの空白を削除します
- }
-
- printf(" ResultStr =%s\n", szResultStr);
-
- 0を返します。
- }
-
-
- /******************************************************************************************
- * 関数の説明: 文字列からフィールドの値を取得する
- * 入力パラメータ: なし
- * 出力パラメータ: なし
- * 戻り値: 0 - 実行成功 その他 - 実行失敗
- * その他の指示: なし
- * 変更日 バージョン番号 修正者 変更内容
- * ---------------------------------------------------------------------
- * 20160215 V1.0 作成者: Zhou Zhaoxiong
- ******************************************************************************/
- INT32 GetFieldFromString(INT8 *pszIn、INT8 cSplitter、UINT16 iIdx、INT8 *pszOut、UINT16 iLen)
- {
- INT8 * pszStart = NULL ;
- INT8 * pszEnd = NULL ;
- UINT16 iCount = 0 ;
- UINT16 iFiledLen = 0 ;
- INT8 szBuf[1024] = {0};
-
- ( NULL == pszIn || NULL == pszOut)の場合
- {
- -1 を返します。
- }
-
- pszStart = pszIn ;
- for ( iCount = 0 ; iIdx != iCount; iCount++) // forループは現在のフィールドの開始位置を見つけるために使用されます
- {
- pszStart = strchr (pszStart、cSplitter);
- if ( NULL == pszStart)
- {
- 壊す;
- }
- それ以外
- {
- pszStart++;
- }
- }
-
- if ( NULL == pszStart)
- {
- -2 を返します。
- }
-
- pszEnd = strchr (pszStart、cSplitter);
- ( NULL == pszEnd の場合)
- {
- -3 を返します。
- }
-
- // 文字列の範囲外のコピーを防ぐために長さを決定する
- (pszEnd - pszStart > sizeof(szBuf)-1)の場合
- {
- iFiledLen = sizeof (szBuf)-1;
- }
- それ以外
- {
- iFiledLen = pszEnd - pszStart;
- }
-
- strncpy(szBuf、pszStart、iFiledLen);
-
- if (iLen < iFiledLen ) // 渡された長さが小さすぎます
- {
- -4 を返します。
- }
-
- strncpy(pszOut, szBuf, iFiledLen);
-
- 0を返します。
- }
-
-
- /******************************************************************************************
- * 関数の説明: 連続する複数のスペースを1つに結合し、先頭のスペースを削除します
- * 入力パラメータ: pszOldStr - スペースを結合する前の文字列
- * 出力パラメータ: pszNewStr - スペースを結合した後の文字列
- * 戻り値: なし
- * その他の指示: なし
- * 変更日 バージョン番号 修正者 変更内容
- * -------------------------------------------------------------------
- * 20160215 V1.0 作成者: Zhou Zhaoxiong
- ******************************************************************************/
- void CombineSpace(INT8 *pszOldStr, INT8 *pszNewStr)
- {
- UINT32 iOldIndex = 0 ;
- UINT32 iNewIndex = 0 ;
- INT8 chSingleChar = '\0' ;
- INT8 iIsSpace = 0 ;
- INT8 szTmpNewStr[100] = {0};
-
- if (( NULL == pszOldStr) || ( NULL == pszNewStr))
- {
- 戻る;
- }
-
- while ('\0' != ( chSingleChar = pszOldStr [iOldIndex++]))
- {
- if ( chSingleChar == ' ') // 連続する複数のスペースは1つだけ保持されます
- {
- ( iIsSpace == 0 )の場合
- {
- スペース= 1 ;
- szTmpNewStr[iNewIndex++] = chSingleChar;
- }
- }
- それ以外
- {
- スペース= 0 ;
- szTmpNewStr[iNewIndex++] = chSingleChar;
- }
- }
-
- // 最後の文字がスペースの場合はそれを削除します
- (szTmpNewStr[strlen(szTmpNewStr)-1] == ' ')の場合
- {
- szTmpNewStr[strlen(szTmpNewStr)-1] = '\0';
- }
-
- // 最初の文字がスペースの場合はそれを削除します
- szTmpNewStr[0] == ' ' の場合
- {
- memcpy(pszNewStr、szTmpNewStr+1、strlen(szTmpNewStr)-1);
- }
- それ以外
- {
- memcpy(pszNewStr、szTmpNewStr、strlen(szTmpNewStr));
- }
-
- 戻る;
- }
5. プログラムのテスト 作成したプログラム「ReverseTheString.c」を Linux マシンにアップロードし、「gcc -g -o ReverseTheStringReverseTheString.c」コマンドを使用してプログラムをコンパイルし、「ReverseTheString」ファイルを生成します。以下はプログラムの詳細なテストです。 1. 入力文字列が「Hello, how do you do」の場合、プログラムは次のように実行されます。 - 文字列を入力してください:
- こんにちは、お元気ですか
- TestStr =こんにちは、お元気ですか
- ResultStr =こんにちは、
2. 入力文字列が「Hello, how do you do」の場合(先頭に 2 つのスペースがあることに注意してください)、プログラムは次のように実行されます。 - 文字列を入力してください:
- こんにちは、お元気ですか
- TestStr =こんにちは、お元気ですか
- ResultStr =こんにちは、
3. 入力文字列が「Hello, how do you do 」の場合(その後に 2 つのスペースがあることに注意してください)、プログラムは次のように実行されます。 - 文字列を入力してください:
- こんにちは、お元気ですか
- TestStr =こんにちは、お元気ですか
- ResultStr =こんにちは、
4. 入力文字列が「Hello, how do you do」の場合(途中に連続したスペースがあることに注意してください)、プログラムは次のように実行されます。 - 文字列を入力してください:
- こんにちは、お元気ですか
- TestStr =こんにちは、お元気ですか
- ResultStr =こんにちは、
5. 入力文字列が「Hello, how do you do」の場合(複数の完全な単語がスペースで区切られていることに注意してください)、プログラムは次のように実行されます。 - 文字列を入力してください:
- こんにちは、お元気ですか
- TestStr =こんにちは、お元気ですか
- ResultStr =あなた、あなたは誰ですか?こんにちは、
プログラムは、上で検討したいくつかの特殊なケースを正しく処理できることがわかります。 6. 需要拡大 この記事の要件と手順に基づいて、要件の次の拡張を検討できます。 1. 反転後の文字列の最初の文字を小文字にし、反転前の最初の文字を大文字から小文字に変更します。つまり、「Hello, how do you do」を「Do you do how hello」に変換します。 2. 元の文字列の句読点の位置を変更せずに、「Hello, how do you do!」は「do you do how Hello,!」に変換されます。 3. 元の文字列の句読点を削除します。つまり、「Hello, how do you do!」を「do you do how Hello」に変換します。 [この記事は51CTOコラムニストの周兆雄氏によるオリジナル記事です。著者のWeChat公開アカウント:周の論理(logiczhou)] この著者の他の記事を読むにはここをクリックしてください |