-5

charの配列へのポインタを取得し、ユーザーから文字列を読み取り、文字列ではない最初のcharが表示されるまで、文字列の先頭にあるすべてのスペースを削除する関数を作成しようとしました。最後に、先頭にスペースを含まない文字列のコピーを返します。

例えば、

入力abcdの場合、関数は文字列へのポインタを返す必要がありますabcd

入力123 123の場合、関数は文字列へのポインタを返す必要があります123 123

機能を以下に示します。

void read_RemoveSpace(char * str)/**read the rest of string**/
{
    char tempRead[30];
    fgets(tempRead,30,stdin);
    char *ptr = strtok(tempRead, " "); /**remove spaces between command and other data**/
    strcpy(str,ptr); /**copy the new string without the spaces.**/
}

しかし、何らかの理由で関数strtok()が期待どおりに機能していません。

入力の場合:

   123 456

この関数は、スペースを含まない最初の部分のみを返しますが、文字列の残りの部分は返しません。つまり、

123

助言がありますか?

4

3 に答える 3

4

strtok期待どおりに動作しています。入力を文字列123とに分割します456

strtok (tempRead, " "); /* Returns 123 */
strtok (NULL, " "); /* Returns 456 */

もっと簡単な解決策でできると思います:

int i = 0;
char tempRead[30];
...
while (tempRead[i] == ' ' && tempRead[i])
  i++;
strcpy(str,tempRead+i);
于 2012-12-25T12:15:08.700 に答える
3

期待どおりに動作しています。

strtok への最初の呼び出しは、トークンの最初の出現を返します。後続の呼び出しでは、最初のパラメーターを NULL として指定している限り、残りのトークンが一度に 1 つずつ返されます。strtok は、トークンがなくなると NULL を返します。

編集:
奇妙なバグが発生する可能性があるため、マニュアルページに記載されている内容と、使用時に常に留意する必要があることをここに引用しますstrtok

これらの機能を使用するときは注意してください。それらを使用する場合は、次の点に注意してください。

  • これらの関数は、最初の引数を変更します。

  • これらの関数は、定数文字列では使用できません。

  • 区切り文字の ID が失われます。

  • 関数はstrtok()解析中に静的バッファーを使用するため、スレッドセーフではありません。これが重要な場合に使用strtok_r()します。

于 2012-12-25T12:15:16.633 に答える
0

使用strtok()することはそれを行うための明白な方法ではありません。

void read_RemoveSpace(char *str)
{
    char *dst = str;
    char tempRead[30];
    if (fgets(tempRead, sizeof(tempRead), stdin) != 0)
    {
        char *src = tempRead;
        char c;
        while ((c = *src++) != '\0')
        {
            if (c != ' ')
                *dst++ = c;
        }
    }
    *dst = '\0';
}

これにより、非空白が改行を含めてにコピーtempReadされます。必要に応じて、またはからstr使用できます。30がローカル文字列に適した長さであるとは確信していませんが、それはあなたが質問で持っていたものです。おそらく、インターフェイスで提供される文字列の大きさを指定する必要があります。また、関数に文字列の最後のnullへのポインタを返すようにすることもできます(これにより、文字列の長さから空白を差し引いた長さを間接的に指定します)。isspace()isblank()#include <ctype.h>void *read_RemoveSpace(char *buffer, size_t buflen)

void read_RemoveSpace(char *buffer, size_t buflen)
{
    char *dst = buffer;
    char tempRead[buflen];
    if (fgets(tempRead, sizeof(tempRead), stdin) != 0)
    {
        char *src = tempRead;
        char c;
        while ((c = *src++) != '\0')
        {
            if (!isspace((unsigned char)c))
                *dst++ = c;
        }
    }
    *dst = '\0';
    return dst;
}

それほど違いはありませんが、はるかに安全です。これは、C99の一部であるローカルVLA(可変長配列)を使用します。VLAを放棄して、ターゲットバッファに直接コピーすることは可能です。

void read_RemoveSpace(char *buffer, size_t buflen)
{
    char *dst = buffer;
    if (fgets(buffer, buflen, stdin) != 0)
    {
        char *src = buffer;
        char c;
        while ((c = *src++) != '\0')
        {
            if (!isspace((unsigned char)c))
                *dst++ = c;
        }
    }
    *dst = '\0';
    return dst;
}

最初の空白まで、このコピーは何もしません。その後、文字を最終的な位置にコピーします。

于 2012-12-25T12:35:22.073 に答える