IT이야기

fgets() 입력에서 말미의 줄바꿈 문자를 제거하는 중

cyworld 2022. 5. 31. 07:48
반응형

fgets() 입력에서 말미의 줄바꿈 문자를 제거하는 중

사용자로부터 데이터를 받아 gcc의 다른 함수로 보내려고 합니다.암호는 이런 거예요.

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

행이 을 알 수 있습니다.\n지막마 so래 so 라고 입력하면John 보내게 된다.John\n 그 '어디서'를 제거할 수 있을까요\n적절한 스트링을 보냅니다.

아마도 가장 간단한 솔루션은 내가 가장 좋아하는 거의 알려지지 않은 함수 중 하나를 사용합니다.

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

'\r'( 림림이 ( ( ( ( ( ) : )

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

.'\r' ★★★'\n'첫즉, 첫 번째를 찾습니다.'\r' ★★★★★★★★★★★★★★★★★」'\n'안 ). 、 운 、 운 、 운 、 운 、 at at 、 the the the 。'\0'(어느 쪽인가 하면)

은, 새로운이 없어도 정상적으로 합니다.이것은, 「」, 「」, 「」가 있기 때문입니다.strcspn'\0' 줄 줄바꿈을 하고 '\0''\0'.

우아한 방법:

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자자그그 그다다다다다

물론 다른 사람들도 있다.

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

인 제거 합니다.'\n'에 의해 fgets().
it it를 한다.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 그그 so sochar'\n'됩니다.buffer읽지 않은 문자는 스트림에 남아 있습니다.
이 B)로 .'\n'

가 포함되어 있는 null 문자가 포함되어 있습니다.'\0'되는 strlen()에는 will will will will will the the는 포함되지 .'\n'★★★★★★ 。


기타 답변:

  1. strtok(buffer, "\n");'\n'buffer"\n". 이 답변부터 - 이 답변 이후에 이 제한을 경고하기 위해 수정.

  2. 은 첫 입니다.char 읽다로 읽다fgets()'\0'된 입력으로 시작할 때 '\0' .그리고나서buffer[len -1] becomes가 되다buffer[SIZE_MAX] 할 수 있는 것은, 확실히 「메모리」입니다.buffer해커가 UTF16 텍스트파일을 우습게 읽을 때 시도하거나 발견할 수 있는 것.이 답변이 작성되었을 때의 답변 상태였습니다.나중에 비OP가 이 답변의 체크와 같은 코드를 포함하도록 편집했습니다."".

    size_t len = strlen(buffer);
    if (buffer[len - 1] == '\n') {  // FAILS when len == 0
      buffer[len -1] = '\0';
    }
    
  3. sprintf(buffer,"%s",buffer);정의되지 않은 동작: 참조.또한 선행, 분리 또는 후행 공백을 저장하지 않습니다.삭제되었습니다.

  4. [나중에 좋은 답변으로 편집]라이너 1개는 문제없고buffer[strcspn(buffer, "\n")] = 0; .strlen() perform. 에서는 I가 이루어지고 있기 는 보통 가 되지 은 CPU 의 블랙홀입니다.코드 I/O가 CPU 시간의 블랙홀인 경우 트리밍 성능은 일반적으로 문제가 되지 않습니다.를 필요로 하거나 을 중시하는에는 이 코드를 합니다.strlen()★★★★★★★★★★★★★★★★★★★★★★★★★★★★」strcspn()훌륭한 대안입니다.

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

일반적으로 원하지 않는 데이터를 잘라내는 대신 처음부터 데이터를 쓰는 것을 피하십시오.버퍼에 새 줄을 넣지 않으려면 fget을 사용하지 마십시오.''를 합니다.getc ★★★★★★★★★★★★★★★★★」fgetc ★★★★★★★★★★★★★★★★★」scanf과 같다 을 사용하다

#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
        char Name[256];
        char fmt[32];
        if( snprintf(fmt, sizeof fmt, "%%%zd[^\n]", sizeof Name - 1) >= (int)sizeof fmt ){
                fprintf(stderr, "Unable to write format\n");
                return EXIT_FAILURE;
        }
        if( scanf(fmt, Name) == 1 ) {
                printf("Name = %s\n", Name);
        }
        return 0;
}

에서는, 행은 읽지 , 「Newline」이라고 하는 도 모릅니다."%255[^\n]%*c"sprintf(fmt, "%%%zd[^\n]%%*c", sizeof Name - 1);a , scanf, scanf, scanf, scanf를 붙입니다.getchar().

가장 알기 쉬운 방법으로 줄 바꿈 문자를 삭제하는 절차는 다음과 같습니다.

  1. 에 있는 를 정하세요.NAME를 사용하여strlen() , 「」string.h해 주세요.strlen()의 끝은 되지 않습니다.\0.
size_t sl = strlen(NAME);

  1. 이 1로 하는지, 1로 합니다.\0문자(빈 문자열). 경우, 「 」sl0strlen()상술한 바와 같이, 는 계산에 넣지 않는다.\0.
if(sl == 0)
{
   // Skip the newline replacement process.
}

  1. 합니다.'\n' 「 」 「 」 「 」 「 」를 합니다.\n a \0 카운트는 .에서합니다.0 때문에 해야 될 것 같아요.NAME[sl - 1]:
if(NAME[sl - 1] == '\n')
{
   NAME[sl - 1] = '\0';
}

것은 키뿐입니다.fgets() request됨) 스트링 요구(스트링 요구)의NAME그 후에는 빈 문자열이 됩니다.


  1. 수 요.if- operator - "논리 연산자 사용"&&:
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);
}

에 내장되어 있는 는, 이은 기능하지 않는 해 주세요.\0그 안에 있어요.strlen()에서는 첫 번째 까지는 됩니다.\0은 보통 첫 문자열 읽기 때문에 접근법이 \0그 늘 문자까지 문자열을 사용합니다.

문제는 제쳐두고..if (!(fgets(Name, sizeof Name, stdin) != NULL) {} 할 수 있어요.if (fgets(Name, sizeof Name, stdin) == NULL) {}.

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

My Newbie way ;-) 맞다면 알려주세요.모든 케이스에서 효과가 있는 것 같습니다.

#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;
}

fgets 호출로 얻을 수 있는 문자열에는 Tim Chas 1개의 라이너가 매우 적합합니다.이것은, 마지막에 1개의 새로운 행이 포함되어 있기 때문입니다.

다른 컨텍스트에서 여러 줄의 새 행을 포함할 수 있는 문자열을 처리하는 경우 strrspn을 찾을 수 있습니다.이것은 POSIX가 아닙니다.즉, 모든 Unice에서 찾을 수 있는 것은 아닙니다.나는 내 필요에 따라 한 권을 썼다.

/* 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;
}

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

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

한번 시도해 보세요.이 코드는 기본적으로 '\n'을 찾을 때까지 문자열을 루프합니다.발견 시 '\n'은 null 문자 터미네이터 '\0'으로 대체됩니다.

이 행의 문자열이 아닌 문자를 비교하고 있으므로 strcmp()를 사용할 필요가 없습니다.

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

큰따옴표가 아닌 작은따옴표를 사용할 것이기 때문입니다.자세한 내용은 싱글 따옴표와 더블 따옴표에 대한 링크를 참조하십시오.

「 」를 하고 있는 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소홀히 해서는 안 됩니다.

이게 제 해결책입니다.아주 간단합니다.

// Delete new line
// char preDelete[256]  include "\n" as newline after fgets

char deletedWords[256];
int iLeng = strlen(preDelete);
int iFinal = 0;
for (int i = 0; i < iLeng; i++) {
    if (preDelete[i] == '\n') {

    }
    else {
        deletedWords[iFinal]  = preDelete[i];
        iFinal++;
    }
    if (i == iLeng -1 ) {
        deletedWords[iFinal] = '\0';
    }
}

언급URL : https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input

반응형