6

私は最近、C で小さなおもちゃのプロジェクトを開始し、python 文字列オブジェクトの一部である strip() 機能を模倣する最良の方法について頭を悩ませています。

fscanf または sscanf を読み回すと、最初に検出された空白まで文字列が処理されることがわかります。

fgets は、まだ改行が残っているため、役に立ちません。strchr() を使用して空白を検索し、返されたポインターを明示的に '\0' に設定しようとしましたが、うまくいかないようです。

4

4 に答える 4

13

Python 文字列のstripメソッドは、末尾と先頭の両方の空白を削除します。C の「文字列」(char の配列、\0 で終了) を処理する場合、問題の 2 つの部分は大きく異なります。

末尾の空白の場合: ポインター (または同等のインデックス) を既存の末尾の \0 に設定します。文字列の先頭または白以外の文字に到達するまで、ポインタをデクリメントし続けます。\0 をこの終了後方スキャン ポイントの直後に設定します。

先頭の空白の場合: 文字列の先頭にポインター (または同等のインデックス) を設定します。白以外の文字 (おそらく末尾の \0) に到達するまでポインタをインクリメントし続けます。memmove 文字列の残りを移動して、最初の非白が文字列の先頭に移動するようにします (以降のすべてについても同様です)。

于 2009-09-28T17:48:10.913 に答える
12

strip() または trim() 関数の標準 C 実装はありません。そうは言っても、Linuxカーネルに含まれるものは次のとおりです。

char *strstrip(char *s)
{
        size_t size;
        char *end;

        size = strlen(s);

        if (!size)
                return s;

        end = s + size - 1;
        while (end >= s && isspace(*end))
                end--;
        *(end + 1) = '\0';

        while (*s && isspace(*s))
                s++;

        return s;
}
于 2009-09-28T17:51:07.023 に答える
1

行の最後の改行を所定の位置で削除する場合は、次のスニペットを使用できます。

size_t s = strlen(buf);
if (s && (buf[s-1] == '\n')) buf[--s] = 0;

Pythonのメソッド(私がその動作を解釈した方法)を忠実に模倣するstr.strip([chars])には、新しい文字列にスペースを割り当て、新しい文字列を埋めて返す必要があります。その後、ストリップされた文字列が不要になったら、メモリリークが発生していなかったメモリを解放する必要があります。

または、Cポインターを使用して初期文字列を変更し、同様の結果を得ることができます。
最初の文字列が"____forty two____\n"であり、すべてのアンダースコアと'\n'を削除するとします。

____forty two___\n
^ ptr

'f'に変更ptrし、その後の最初の' _'を結果に置き換えるtwo'\0'、結果はPythonと同じになります。"____forty two____\n".strip("_\n");

____forty two\0___\n
    ^ptr

繰り返しますが、これはPythonと同じではありません。文字列はその場で変更され、2番目の文字列はなく、変更を元に戻すことはできません(元の文字列は失われます)。

于 2009-09-28T18:07:47.813 に答える
0

この関数を実装する C コードを書きました。また、関数が適切に動作することを確認するために、いくつかの簡単なテストも作成しました。

この関数は、ユーザーが提供するバッファーに書き込みます。バッファーの末尾を超えて書き込むことはありません。そのため、バッファー オーバーフローのセキュリティ問題が発生する可能性はありません。

注: Test() のみが stdio.h を使用するため、関数だけが必要な場合は、ctype.h (isspace() 用) と string.h (strlen() 用) を含めるだけで済みます。

// strstrip.c -- implement white space stripping for a string in C
//
// This code is released into the public domain.
//
// You may use it for any purpose whatsoever, and you don't need to advertise
// where you got it, but you aren't allowed to sue me for giving you free
// code; all the risk of using this is yours.



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



// strstrip() -- strip leading and trailing white space from a string
//
// Copies from sIn to sOut, writing at most lenOut characters.
//
// Returns number of characters in returned string, or -1 on an error.
// If you get -1 back, then nothing was written to sOut at all.

int
strstrip(char *sOut, unsigned int lenOut, char const *sIn)
{
    char const *pStart, *pEnd;
    unsigned int len;
    char *pOut;

    // if there is no room for any output, or a null pointer, return error!
    if (0 == lenOut || !sIn || !sOut)
        return -1;

    pStart = sIn;
    pEnd = sIn + strlen(sIn) - 1;

    // skip any leading whitespace
    while (*pStart && isspace(*pStart))
        ++pStart;

    // skip any trailing whitespace
    while (pEnd >= sIn && isspace(*pEnd))
        --pEnd;

    pOut = sOut;
    len = 0;

    // copy into output buffer
    while (pStart <= pEnd && len < lenOut - 1)
    {
        *pOut++ = *pStart++;
        ++len;
    }


    // ensure output buffer is properly terminated
    *pOut = '\0';
    return len;
}


void
Test(const char *s)
{
    int len;
    char buf[1024];

    len = strstrip(buf, sizeof(buf), s);

    if (!s)
        s = "**null**";  // don't ask printf to print a null string
    if (-1 == len)
        *buf = '\0';  // don't ask printf to print garbage from buf

    printf("Input: \"%s\"  Result: \"%s\" (%d chars)\n", s, buf, len);
}


main()
{
    Test(NULL);
    Test("");
    Test(" ");
    Test("    ");
    Test("x");
    Test("  x");
    Test("  x   ");
    Test("  x y z   ");
    Test("x y z");
}
于 2009-09-28T21:13:15.663 に答える