306

ユーザーからデータを取得して、gcc の別の関数に送信しようとしています。コードはこのようなものです。

printf("Enter your Name: ");
if (!(fgets(Name, sizeof Name, stdin) != NULL)) {
    fprintf(stderr, "Error reading Name.\n");
    exit(1);
}

\nただし、最後に改行文字があることがわかりました。したがって、入力するJohnと送信されJohn\nます。\nそれを削除して適切な文字列を送信するにはどうすればよいですか。

4

14 に答える 14

210

エレガントな方法:

Name[strcspn(Name, "\n")] = 0;

少し醜い方法:

char *pos;
if ((pos=strchr(Name, '\n')) != NULL)
    *pos = '\0';
else
    /* input too long for buffer, flag error */

少し奇妙な方法:

strtok(Name, "\n");

strtokユーザーが空の文字列を入力した場合(つまり、Enterキーのみを押した場合)、関数は期待どおりに機能しないことに注意してください。それは\nキャラクターを無傷のままにします。

もちろん、他にもあります。

于 2010-04-22T19:26:52.803 に答える
84
size_t ln = strlen(name) - 1;
if (*name && name[ln] == '\n') 
    name[ln] = '\0';
于 2010-04-22T19:26:55.620 に答える
22

'\n'以下は、によって保存された文字列からポテンシャルを削除する簡単な方法fgets()です。
を使用しstrlen()、2 つのテストがあります。

char buffer[100];
if (fgets(buffer, sizeof buffer, stdin) != NULL) {

  size_t len = strlen(buffer);
  if (len > 0 && buffer[len-1] == '\n') {
    buffer[--len] = '\0';
  }

buffer必要に応じてとを使用lenします。

このメソッドには、len後続のコードの値という副次的な利点があります。よりも簡単に高速化できますstrchr(Name, '\n')YMMV を参照しますが、両方の方法が機能します。


buffer、ある状況下では元のfgets()に含まれません: A) 行が長すぎるため、の前のみが に保存されます。未読文字はストリームに残ります。 B) ファイルの最後の行が . で終わっていませんでした。 "\n"
bufferchar'\n'buffer
'\n'

入力のどこかに null 文字が埋め込まれている場合'\0'、 によって報告される長さにはその場所strlen()は含まれません。'\n'


他の回答の問題:

  1. strtok(buffer, "\n");'\n'when bufferisを削除できません"\n"。この回答から- この回答の後に修正して、この制限を警告します。

  2. char以下は、最初の読み取りが でfgets()ある場合にまれに失敗します'\0'。これは、入力が埋め込まれた で始まる場合に発生します'\0'。すると、確実に の正当な範囲外のメモリにアクセスするようにbuffer[len -1]なります。ハッカーがUTF16テキストファイルをばかげて読み取る際に試みたり見つけたりする可能性のあるもの。これは、この回答が書かれたときの回答の状態でした。後で非 OP がそれを編集して、この回答の check for のようなコードを含めました。buffer[SIZE_MAX]buffer""

    size_t len = strlen(buffer);
    if (buffer[len - 1] == '\n') {  // FAILS when len == 0
      buffer[len -1] = '\0';
    }
    
  3. sprintf(buffer,"%s",buffer);は未定義の動作です: Ref . さらに、先頭、区切り、または末尾の空白は保存されません。現在は削除されています。

  4. [後で良い回答のため編集]アプローチbuffer[strcspn(buffer, "\n")] = 0;と比較して、パフォーマンス以外に1つのライナーに問題はありません。strlen()コードが I/O (CPU 時間のブラック ホール) を実行していることを考えると、通常、トリミングのパフォーマンスは問題になりません。次のコードで文字列の長さが必要な場合、またはパフォーマンスを重視する場合は、このstrlen()方法を使用してください。それ以外の場合strcspn()は、優れた代替手段です。

于 2015-01-01T10:29:35.873 に答える
11

すべての行に「\n」がある場合、fgets 出力から「\n」を削除するように指示します。

line[strlen(line) - 1] = '\0';

さもないと:

void remove_newline_ch(char *line)
{
    int new_line = strlen(line) -1;
    if (line[new_line] == '\n')
        line[new_line] = '\0';
}
于 2013-06-30T01:15:09.803 に答える
2

シングル '\n' トリミングの場合、

void remove_new_line(char* string)
{
    size_t length = strlen(string);
    if((length > 0) && (string[length-1] == '\n'))
    {
        string[length-1] ='\0';
    }
}

複数の '\n' トリミングの場合、

void remove_multi_new_line(char* string)
{
  size_t length = strlen(string);
  while((length>0) && (string[length-1] == '\n'))
  {
      --length;
      string[length] ='\0';
  }
}
于 2015-03-16T05:45:21.433 に答える
-2

以下の関数は、私が Github で保守している文字列処理ライブラリの一部です。文字列から不要な文字を削除します。まさにあなたが望むものです

int zstring_search_chr(const char *token,char s){
    if (!token || s=='\0')
        return 0;

    for (;*token; token++)
        if (*token == s)
            return 1;

    return 0;
}

char *zstring_remove_chr(char *str,const char *bad) {
    char *src = str , *dst = str;
    while(*src)
        if(zstring_search_chr(bad,*src))
            src++;
        else
            *dst++ = *src++;  /* assign first, then incement */

    *dst='\0';
        return str;
}

使用例は次のとおりです。

Example Usage
      char s[]="this is a trial string to test the function.";
      char const *d=" .";
      printf("%s\n",zstring_remove_chr(s,d));

  Example Output
      thisisatrialstringtotestthefunction

他の利用可能な機能を確認したり、プロジェクトに貢献したりすることもできます:) https://github.com/fnoyanisi/zString

于 2016-02-18T00:41:19.600 に答える