fgets () 입력에서 후행 줄 바꿈 문자 제거


235

사용자로부터 일부 데이터를 가져 와서 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하고 적절한 문자열을 보내 려면 어떻게해야합니까?


21
if (!fgets(Name, sizeof Name, stdin))(최소한 두 가지 부정,! 및! =을 사용하지 마십시오)

4
@Roger Pate는 "두 가지 부정을 사용하지 마십시오"-> 흠, 우리가 깊이 "만두 지"및 "부정"을 파헤 치면 모두 부정 입니다. ;-). 아마도 "사용합니다 if (fgets(Name, sizeof Name, stdin)) {.
chux-복원 자 Monica

3
@ chux, 난 당신이 의미 확신if (fgets(Name, sizeof Name, stdin) == NULL ) {
R Sahu

@RSahu True : 성가신 !:
chux-복원 모니카

답변:


154

약간 못생긴 방법 :

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

약간 이상한 방법 :

strtok(Name, "\n");

strtok사용자가 빈 문자열을 입력하면 (예 : Enter 만 누름) 이 기능은 예상대로 작동하지 않습니다. \n캐릭터를 그대로 둡니다 .

물론 다른 것도 있습니다.


7
스레드를 인식하는 (즉, 다중 스레드 플랫폼을 대상으로하는 대부분의) C 런타임 라이브러리는 스레드 strtok()로부터 안전합니다 ( '인터 통화'상태에 스레드 로컬 스토리지를 사용함). 즉, 일반적으로 비표준 (그러나 일반적인) strtok_r()변형 을 사용하는 것이 좋습니다 .
Michael Burr

2
귀하의 strtok접근 방식 과 유사한 완전히 스레드 안전하고 재진입 변형에 대한 내 답변을 참조하십시오 (빈 입력으로 작동 함). 실제로 구현하는 좋은 방법 strtokstrcspnand 를 사용하는 것 strspn입니다.
Tim Čas

2
너무 긴 라인의 위험이있는 환경에있는 경우 else 케이스를 처리하는 것이 중요합니다. 입력을 자동으로 자르면 매우 심각한 버그가 발생할 수 있습니다.
Malcolm McLean

2
원 라이너를 좋아하고 glibc를 사용하는 경우을 사용해보십시오 *strchrnul(Name, '\n') = '\0';.
twobit

strchr(Name, '\n') == NULL다음 옆에서 "입력 너무 오래 버퍼, 플래그 오류에 대해"다른 가능성이 존재, :의 마지막 문자 stdin로 끝날하지 않았 '\n'거나 드문 임베디드 널 (null) 문자는 읽을 수 있었다.
chux-Reinstate Monica

439

아마도 가장 간단한 해결책은 내가 좋아하는 거의 알려지지 않은 기능 중 하나를 사용하는 것입니다 strcspn().

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

'\r'스트림을 바이너리로 처리하는 경우에도 처리 하려면 :

buffer[strcspn(buffer, "\r\n")] = 0; // works for LF, CR, CRLF, LFCR, ...

그것은을 돌 때까지이 기능은 문자의 수를 계산 '\r'또는이 '\n'(즉, 그것은 처음 발견 '\r'또는 '\n'). 아무 것도 맞지 않으면 '\0'(문자열 길이를 반환) 에서 멈 춥니 다 .

이 때문에, 더 줄 바꿈이없는 경우에도 잘 작동합니다 strcspn멈추는에 '\0'. 그 경우에, 전체 행은 단순히 대체 '\0'하여 '\0'.


30
심지어 접근 방식에 대한 슬픔을 유발하는 buffer것으로 시작 하는 것보다 드문 경우를 처리합니다 . '\0'buffer[strlen(buffer) - 1] = '\0';
chux-복원 모니카

5
@ chux : 응, 더 많은 사람들이 알고 있었으면 좋겠다 strcspn(). 라이브러리에서 더 유용한 기능 중 하나 인 IMO. 저는 오늘 이와 같은 일반적인 C 핵을 작성하고 게시하기로 결정했습니다. codepad.org/2lBkZk0w를strtok_r 사용 strcspn하고 구현 한 구현체 strspn: codepad.org/2lBkZk0w ( 경고 : 버그가 없다는 것을 보장 할 수는 없습니다; 서둘러 작성되었으며 아마도 몇 가지가있을 것입니다). 그래도 아직 게시 할 부분은 없지만 유명한 "비트 트위들 링 핵"의 정신으로 만들려고합니다.
Tim Čas

4
견고하게 다듬는fgets() 방법을 조사했습니다 . 이것은 유일한 올바른 하나의 라이너 인 strcspn()것 같습니다 . 간단하지는 않지만 빠릅니다. strlen
chux-복원 모니카

6
@sidbushes : 제목과 내용 모두에서 질문 fgets()입력 에서 후행 줄 바꿈에 대해 묻습니다 . 어느 것도 항상 첫 번째 줄 바꿈입니다.
Tim Čas

9
@sidbushes : 어디에서 왔는지 이해하지만 특정 용어에 대한 Google 검색 결과에 대한 책임을지지 않습니다. 나와 Google이 아니라 대화하십시오.
Tim Čas

83
size_t ln = strlen(name) - 1;
if (*name && name[ln] == '\n') 
    name[ln] = '\0';

8
문자열이 비어 있으면 예외가 발생합니까? 범위를 벗어난 인덱스처럼.
Edward Olamisan

1
@EdwardOlamisan, 그러나 문자열은 결코 비어 있지 않습니다.
제임스 모리스

5
@James Morris 비정상적인 경우 fgets(buf, size, ....)-> strlen(buf) == 0. 1) fgets()첫 번째 chara 로 읽습니다 '\0'. 2) size == 13) fgets()반환 NULL하면 buf내용이 무엇이든 될 수 있습니다. (OP의 코드는 NULL을 테스트합니다) 제안 :size_t ln = strlen(name); if (ln > 0 && name[ln-1] == '\n') name[--ln] = '\0';
chux-Monica Monica 복원

2
문자열이 비어 있으면 어떻게합니까? ln사실 size_t은 부호가 없으므로 임의의 메모리에 쓰는 경우 -1 이됩니다. 나는 당신이 사용 ssize_t하고 싶다고 생각하고 ln> 0입니다.
abligh

2
@ legends2k : 컴파일 타임 값에 대한 검색 (특히에서와 같이 0 값 strlen)은 일반 char-by-char 검색보다 훨씬 효율적으로 구현 될 수 있습니다. 어떤 이유로 나는 것보다이 솔루션 더 나은 생각 하는데요 strchr또는 strcspn기초 것.
AnT

17

아래는에 '\n'의해 저장된 문자열에서 잠재력을 제거하는 빠른 방법 fgets()입니다. 두 가지 테스트로을
사용 strlen()합니다.

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()에 포함되지 않습니다 "\n": 어떤 상황에서
A) 라인이 너무 오랫동안이었다 buffer때문에 만 char가 이전 '\n'에 저장됩니다 buffer. 읽지 않은 문자는 스트림에 남아 있습니다.
B) 파일의 마지막 줄은로 끝나지 않았습니다 '\n'.

입력에 널 문자가 포함되어 있으면 '\0'보고 된 길이 strlen()'\n'위치가 포함되지 않습니다 .


다른 답변의 문제 :

  1. strtok(buffer, "\n");(가) 제거에 실패 '\n'할 때 buffer입니다 "\n". 이 답변에서 -이 제한 이후에 경고하기 위해이 답변 이후 수정되었습니다.

  2. 첫 번째 charby by fgets()가 인 경우는 드물지만 다음에 실패합니다 '\0'. 입력이 포함 된로 시작될 때 발생합니다 '\0'. 이어서 buffer[len -1]된다 buffer[SIZE_MAX]의 정상적인 범위 밖에 확실히 액세스 메모리 buffer. 해커가 UTF16 텍스트 파일을 어리석게 읽을 때 시도하거나 발견 할 수있는 것. 이 답변이 작성되었을 때 의 답변 상태입니다 . 나중에 비 OP 가이 답변의 check과 같은 코드를 포함하도록 편집했습니다 "".

    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()훌륭한 대안입니다.


유용한 답변에 감사드립니다. ?를 strlen(buffer)사용하여 버퍼 크기를 동적으로 할당 할 때 사용할 수 있습니까 malloc?
rrz0

@ Rrz0 buffer = malloc(allocation_size); length = strlen(buffer);이 잘못되었습니다. 메모리가 가리키는 데이터를 buffer알 수 없습니다. buffer = malloc(allocation_size_4_or_more); strcpy(buffer, "abc"); length = strlen(buffer);괜찮아
chux-복원 모니카

감사합니다 !! 저는 CS 과정을 수강하며 과제 중 하나에 큰 도움이되었습니다. 나는 소스 코드에서 당신의 대답을 인정했습니다.
Nathaniel Hoyt

8

모든 줄에 '\ 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';
}

1
대신 사용 하는 것이 더 안전 합니다 . strnlenstrlen
Mike Mertsock 2016 년

3
링크 된 질문의 첫 번째 답변에 대한 주석은 "strlen (), strcmp () 및 strdup ()은 안전합니다. 'n'대안은 추가 기능을 제공합니다."
Étienne

4
@esker 아니오, 그렇지 않습니다. 를 삽입 n해도 안전이 마술처럼 향상되지는 않습니다.이 경우 실제로 코드가 더 위험 해집니다. 마찬가지로 strncpy매우 안전하지 않은 기능입니다. 연결 한 게시물이 좋지 않습니다.
MM

3
빈 문자열 ( "")에 대해 비참하게 실패합니다 . 또한 not을 strlen()반환합니다 . size_tint
alk

4
이것은 빈 문자열에 대해 안전하지 않으며 인덱스 -1에 씁니다. 이것을 사용하지 마십시오.
Jean-François Fabre

3

단일 '\ 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';
  }
}

1
?를 if사용하여 단순히 하나의 조건을 작성할 수 있는데 왜 중첩 &&합니까? 그 while루프는 이상한 구조를 가지고 있습니다. 단순히 될 수 있습니다 while (length > 0 && string[length-1] == '\n') { --length; string[length] = '\0'; }.
melpomene

@melpomene 제안에 감사드립니다. 코드를 업데이트하십시오.
BEPP

1
첫 번째 함수가 더 자연스럽게 다음과 같이 정의되어 있다고 제안합니다 size_t length = strlen(string); if (length > 0 && string[length-1] == '\n') { string[length-1] = '\0'; }. 또한 두 번째 정의를 더 잘 반영합니다 ( if대신에 사용 while).
melpomene

@elpomene 감사합니다. 말이 되는군요. 코드를 업데이트했습니다.
BEPP

1

내 초보자 방법 ;-) 그것이 올바른지 알려주십시오. 내 모든 경우에 효과가있는 것 같습니다.

#define IPT_SIZE 5

int findNULL(char* arr)
{
    for (int i = 0; i < strlen(arr); i++)
    {
        if (*(arr+i) == '\n')
        {
            return i;
        }
    }
    return 0;
}

int main()
{
    char *input = malloc(IPT_SIZE + 1 * sizeof(char)), buff;
    int counter = 0;

    //prompt user for the input:
    printf("input string no longer than %i characters: ", IPT_SIZE);
    do
    {
        fgets(input, 1000, stdin);
        *(input + findNULL(input)) = '\0';
        if (strlen(input) > IPT_SIZE)
        {
            printf("error! the given string is too large. try again...\n");
            counter++;
        }
        //if the counter exceeds 3, exit the program (custom function):
        errorMsgExit(counter, 3); 
    }
    while (strlen(input) > IPT_SIZE);

//rest of the program follows

free(input)
return 0;
}

1

가장 분명한 방법으로 개행 문자를 제거하는 단계 :

  1. , header NAME를 사용하여 문자열의 길이를 결정하십시오 . 참고 종료를 계산하지 않습니다 .strlen()string.hstrlen()\0
size_t sl = strlen(NAME);

  1. 문자열이 하나의 \0문자로 시작하거나 하나의 문자 만 포함하는지 확인하십시오 (빈 문자열). 이때 sl0때문에 strlen()I가 계산 나던 위에 상기와 같은 \0그것의 첫번째 발생 정차 :
if(sl == 0)
{
   // Skip the newline replacement process.
}

  1. 적절한 문자열의 마지막 문자가 개행 문자인지 확인하십시오 '\n'. 이 경우, 대체 \n로모그래퍼 \0. 인덱스 수는 처음부터 시작 0되므로 다음을 수행해야합니다 NAME[sl - 1].
if(NAME[sl - 1] == '\n')
{
   NAME[sl - 1] = '\0';
}

fgets()문자열 요청 에서 Enter 만 누른 경우 (문자열 내용은 개행 문자로만 구성됨) NAME이후 문자열은 빈 문자열이됩니다.


  1. if논리 연산자를 사용하여 2 단계와 3 단계를 하나의 문장으로 결합 할 수 있습니다 &&.
if(sl > 0 && NAME[sl - 1] == '\n')
{
   NAME[sl - 1] = '\0';
}

  1. 완성 된 코드 :
size_t sl = strlen(NAME);
if(sl > 0 && NAME[sl - 1] == '\n')
{
   NAME[sl - 1] = '\0';
}

fgets매번 다시 입력하지 않고 일반적으로 출력 문자열 을 처리하여이 기술을 사용하는 함수를 선호하는 경우 다음과 fgets_newline_kill같습니다.

void fgets_newline_kill(char a[])
{
    size_t sl = strlen(a);

    if(sl > 0 && a[sl - 1] == '\n')
    {
       a[sl - 1] = '\0';
    }
}

제공된 예에서 다음과 같습니다.

printf("Enter your Name: ");

if (fgets(Name, sizeof Name, stdin) == NULL) {
    fprintf(stderr, "Error reading Name.\n");
    exit(1);
}
else {
    fgets_newline_kill(NAME);
}

입력 문자열에 \0s 가 포함되어 있으면이 방법이 작동하지 않습니다 . 이 경우 strlen()첫 번째까지만 문자 수를 반환합니다 \0. 그러나 대부분의 문자열 읽기 기능은 일반적으로 처음에 멈추고 \0해당 null 문자까지 문자열을 가져 오기 때문에 이것은 일반적인 접근 방식이 아닙니다.

그 자체로 질문을 제외하고. 코드가 명확하지 않은 이중 부정을 피하십시오 if (!(fgets(Name, sizeof Name, stdin) != NULL) {}. 간단하게 할 수 있습니다 if (fgets(Name, sizeof Name, stdin) == NULL) {}.


왜 당신이 이것을하고 싶은지 모르겠습니다. 줄 바꿈을 제거하는 요점은 문자열을 null로 종료하는 것이 아닙니다. 개행을 제거하는 것입니다. 교체 \nA를을 \0상기 문자열은 줄 바꿈을 "제거"하는 방법입니다. 그러나 \n문자열 내 문자를 바꾸면 기본적으로 문자열이 변경됩니다. 의도적으로 여러 줄 바꿈 문자가있는 문자열을 갖는 것은 드문 일이 아니며, 이는 해당 문자열의 끝을 효과적으로 잘라냅니다. 이러한 줄 바꿈 을 제거 하려면 배열 내용을 왼쪽으로 이동하여를 덮어 씁니다 \n.
전 nihilo

@exnihilo 누군가 어떻게 사용하여 여러 줄 바꿈이있는 문자열을 입력 할 수 fgets()있습니까?
RobertS는

글을 여러 번 호출하여 얻은 문자열을 연결할 수 있습니다 fgets(). 그러나 나는 당신의 반대 의견을 이해하지 못합니다 : 당신은 여러 줄 바꿈을 처리하는 코드를 제안하는 사람입니다.
전 nihilo

@exnihilo 당신이 옳습니다, 나는 전략을 너무 생각할 것입니다. 원하는 결과를 얻을 수있는 매우 가혹하지만 가능한 방법을 추가하고 싶었습니다.
RobertS는

@exnihilo 내 대답을 완전히 편집하고 strlen등 을 사용하여 주요 접근 방식을 따랐습니다 . 중복되지 않는 이유 : 1. 단계별 코드 설명. 2. 기능 및 컨텍스트 기반 솔루션으로 제공됩니다. 이중 부정 표현을 피하기 위해 힌트.
RobertS는

0

Tim Čas one liner는 fgets 호출로 얻은 문자열에 놀랍습니다. 마지막에 줄 바꿈이 하나 포함되어 있기 때문입니다.

다른 컨텍스트에 있고 둘 이상의 개행을 포함 할 수있는 문자열을 처리하려는 경우 strrspn을 찾고있을 수 있습니다. POSIX가 아니므로 모든 Unices에서 찾을 수 없습니다. 나는 내 자신의 필요를 위해 하나를 썼습니다.

/* Returns the length of the segment leading to the last 
   characters of s in accept. */
size_t strrspn (const char *s, const char *accept)
{
  const char *ch;
  size_t len = strlen(s);

more: 
  if (len > 0) {
    for (ch = accept ; *ch != 0 ; ch++) {
      if (s[len - 1] == *ch) {
        len--;
        goto more;
      }
    }
  }
  return len;
}

C에서 Perl chomp에 해당하는 것을 찾는 사람들에게는 이것이 있다고 생각합니다 (chomp는 후행 줄 바꿈 만 제거합니다).

line[strrspn(string, "\r\n")] = 0;

strrcspn 함수 :

/* Returns the length of the segment leading to the last 
   character of reject in s. */
size_t strrcspn (const char *s, const char *reject)
{
  const char *ch;
  size_t len = strlen(s);
  size_t origlen = len;

  while (len > 0) {
    for (ch = reject ; *ch != 0 ; ch++) {
      if (s[len - 1] == *ch) {
        return len;
      }
    }
    len--;
  }
  return origlen;
}

1
"마지막에 줄 바꿈이 하나 있다는 것을 알고 있기 때문에." -> '\n'없거나 문자열이 인 경우 에도 작동합니다 "".
chux-복원 Monica Monica

첫 번째 코멘트 chux에 대한 응답으로, 내 대답은 그것을 유지합니다. 내가 strrcspn없을 때 나는 resetlen을 던져야했다 \n.
Philippe A.

goto end;대신에 사용 return len;합니까?
chqrlie

@chqrlie 나는이 우아한 2 레벨 루프에서 벗어나야했습니다. 해가됐다. 왜 안가?
Philippe A.

goto코드 에는 두 가지 종류가 있습니다 : 문장 goto으로 대체 될 수 없는 쓸모없는 것과 악으로 간주 return되는 뒤로 goto. 사용하여 strchr구현하는 데 도움 strrspnstrrcspn: 간단한 방식으로 size_t strrspn(const char *s, const char *accept) { size_t len = strlen(s); while (len > 0 && strchr(accept, s[len - 1])) { len--; } return len; }size_t strrcspn(const char *s, const char *reject) { size_t len = strlen(s); while (len > 0 && !strchr(reject, s[len - 1])) { len--; } return len; }
chqrlie

0

using getline이 보안 문제를 무시하지 않고 포인터를 괄호로 묶는 옵션 인 경우 getline문자 수를 반환하므로 문자열 함수를 피할 수 있습니다 . 아래와 같은 것

#include<stdio.h>
#include<stdlib.h>
int main(){
char *fname,*lname;
size_t size=32,nchar; // Max size of strings and number of characters read
fname=malloc(size*sizeof *fname);
lname=malloc(size*sizeof *lname);
if(NULL == fname || NULL == lname){
 printf("Error in memory allocation.");
 exit(1);
}
printf("Enter first name ");
nchar=getline(&fname,&size,stdin);
if(nchar == -1){ // getline return -1 on failure to read a line.
 printf("Line couldn't be read.."); 
 // This if block could be repeated for next getline too
 exit(1);
}
printf("Number of characters read :%zu\n",nchar);
fname[nchar-1]='\0';
printf("Enter last name ");
nchar=getline(&lname,&size,stdin);
printf("Number of characters read :%zu\n",nchar);
lname[nchar-1]='\0';
printf("Name entered %s %s\n",fname,lname);
return 0;
}

참고 : [ 보안 문제 ]getline무시해서는 안됩니다.


-1

아래 함수는 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


당신은 제거해야합니다 **src++;와 확인 bad, tokend const char *. 또한 왜 strchr대신에 사용 하지 zChrSearch않습니까? 당신의 기능에 *src있을 수 없습니다 . '\0'zStrrmv
chqrlie

감사합니다 @chqrlie! 귀하의 제안을 반영하기 위해 코드를 업데이트했습니다 ..... zstring은 표준 라이브러리 기능을 사용하지 않고 문자열 조작 라이브러리를 만들기위한 재미있는 프로젝트로 시작되었으므로 사용하지 않았습니다.strchr
fnisi

1
" 표준 라이브러리 함수를 사용하지 않고 문자열 조작 라이브러리 "를 작성하는 것은 좋은 연습이지만 다른 사람들에게 사용하도록 지시하는 이유는 무엇입니까? 무엇이든 표준 라이브러리보다 속도가 느리고 테스트가 적습니다.
melpomene

이것은 질문에서 요구하는 것과 다른 일을하고 있습니다. 아마도 유일한 줄 바꿈을 제거하는 데 사용될 수 있지만 과도하게 느껴집니다.
Jonathan Leffler

-1
 for(int i = 0; i < strlen(Name); i++ )
{
    if(Name[i] == '\n') Name[i] = '\0';
}

당신은 그것을 시도해야합니다. 이 코드는 기본적으로 '\ n'을 찾을 때까지 문자열을 반복합니다. 발견되면 '\ n'은 널 문자 종결 자 '\ 0'으로 대체됩니다.

이 줄에서 문자열이 아닌 문자를 비교하는 경우 strcmp ()를 사용할 필요가 없습니다.

if(Name[i] == '\n') Name[i] = '\0';

큰 따옴표가 아닌 작은 따옴표를 사용하기 때문입니다. 여기 당신이 더 많은 것을 알고 싶은 경우에 큰 따옴표 대 싱글에 대한 링크


2
코드 형식을 설명하고 편집하면 더 좋습니다.
Anh Pham

일반적으로 익명 코드 행을 게시하는 대신 솔루션을 설명하는 것이 좋습니다. 좋은 답변을 작성하는 방법전체 코드 기반 답변 설명을 읽을 수 있습니다 .
Massimiliano Kraus

1
이것이 내가 처음으로 기여한 것이 유감입니다. 내가 고칠 게 피드백 주셔서 감사합니다
Matheus Martins Jerônimo

3
비효율적이 : for(int i = 0; i < strlen(Name); i++ )호출 strlen(Name)여러 번 (루프 변경 Name[], 길이 정도) N, 이것은이다 O(N*N)솔루션. strlen(Name)O (N)`솔루션을 제공하는 데 필요한 경우 한 번만 호출하면 됩니다. 왜 int i대신에 사용 되는지 확실하지 않습니다 size_t i. 고려for(size_t i = 0; i < Name[i]; i++ )
chux-Reinstate Monica

@chux 더 좋아요for (size_t i = 0; Name[i]; i++) { if (Name[i] == '\n') { Name[i] = '\0'; break; } }
melpomene

-1

이거 한번 해봐:

        int remove_cr_lf(char *str)
        {
          int len =0;


          len = strlen(str);

          for(int i=0;i<5;i++)
          {
            if (len>0)
            if (str[len-1] == '\n')
            {
              str[len-1] = 0;
              len--;
            }

            if (len>0)
            if (str[len-1] == '\r')
            {
              str[len-1] = 0;
              len--;
            }
          }

          return 0;
        }

1
len = strlen(str)오버 플로우 수 strlen반환 size_t하지 int. 이상한 if (len>0) if (...)조건 은 무엇입니까 ? 당신은 몰라 &&? CR / LF의 여러 후행 인스턴스를 제거하려는 경우 왜 5로 제한합니까? 왜 모두 제거하지 않습니까? 함수가 int항상 리턴 할 때 리턴 유형을 갖는 이유는 무엇 0입니까? 왜 돌아 오지 void않습니까?
melpomene
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.