2014-12-06 4 views
6

fgets()을 사용하여 긴 입력을 읽으려면 어떻게해야 하나? fgets를 사용하여 알 수없는 길이의 입력을 읽는 방법

나는이

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

int main() 
{ 
    char buffer[10]; 
    char *input; 
    while (fgets(buffer,10,stdin)){ 
     input = malloc(strlen(buffer)*sizeof(char)); 
     strcpy(input,buffer); 
    } 
    printf("%s [%d]",input, (int)strlen(input)); 
    free(input); 
    return 0; 
} 
+2

'realloc'을 참조하십시오. 그리고 매번 할당을 두 배로 늘리거나 버퍼로 직접 읽어들이는 전략을 고려하십시오. BTW :'size_t '의 printf 형식은'% zu'입니다. – Deduplicator

+1

가지고 있다면'fgets' 대신에''getline' (http://linux.die.net/man/3/getline)을 사용해보십시오. – 5gon12eder

+0

getline에 대해 알고 있지만, fgets를 사용해야합니다. – lllook

답변

5
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main(void) 
{ 
    char buffer[10]; 
    char *input = 0; 
    size_t cur_len = 0; 
    while (fgets(buffer, sizeof(buffer), stdin) != 0) 
    { 
     size_t buf_len = strlen(buffer); 
     char *extra = realloc(input, buf_len + cur_len + 1); 
     if (extra == 0) 
      break; 
     input = extra; 
     strcpy(input + cur_len, buffer); 
     cur_len += buf_len; 
    } 
    printf("%s [%d]", input, (int)strlen(input)); 
    free(input); 
    return 0; 
} 

이것은 완전한 입력 행을 제공하는 최소한의 변경 사항에 관한 것입니다. 이것은 한 번에 최대 9 바이트 씩 공간을 늘립니다. 그것은 최선의 방법은 아니지만 더 나은 방법 (할당 된 공간을 두 배로 늘리고 사용량과 할당량을 기록하는 방법을 유지하는 것)이 필요한 추가 부기가 있습니다. cur_len은 단말 null을 제외하고 input이 가리키는 공간에 문자열의 길이를 기록합니다. 또한 extra을 사용하면 할당 실패시 메모리 누수가 방지됩니다.

strcpy() 작업은 합법적으로 memmove(input + cur_len, buffer, buf_len + 1) (이 맥락에서, 대신 memmove()memcpy()을 사용할 수 있지만 memmove() 항상 작동합니까하면서 memmove()를 사용하는 것이 더 신뢰할 수 있도록 항상 작동하지 않습니다)로 대체 될 수있다. 길이 두 배와


- 할당 된 공간의 양을 cur_max 변수 기록, 사용중인 공간이 얼마나 cur_len 기록.

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

int main(void) 
{ 
    char buffer[10]; 
    char *input = 0; 
    size_t cur_len = 0; 
    size_t cur_max = 0; 
    while (fgets(buffer, sizeof(buffer), stdin) != 0) 
    { 
     size_t buf_len = strlen(buffer); 
     if (cur_len + buf_len + 1 > cur_max) 
     { 
      size_t new_len = cur_max * 2 + 1; 
      if (buf_len + 1 > new_len) 
       new_len = buf_len + 1; 
      char *extra = realloc(input, new_len); 
      if (extra == 0) 
       break; 
      input = extra; 
      cur_max = new_len; 
     } 
     strcpy(input + cur_len, buffer); 
     cur_len += buf_len; 
    } 
    printf("%s [%d]", input, (int)strlen(input)); 
    free(input); 
    return 0; 
} 
+0

일반적으로 매우 긴 행을 읽고 싶다면 realloc을 이전 크기보다 2 배 더 크기 조정해야합니다. – lllook

+0

아니요; 가장 간단한 방법은'char buffer [4096];'을 사용하고 생명을 얻는 것입니다. JSON만이 이보다 더 긴 줄로 나온다. 그러면 한 줄로 전체 파일을 읽게된다. (나는 과장하지 만, 모든 것만큼 과장하지는 않습니다.) 처음에는 10 바이트를 할당하고 20을 재 할당 한 다음 40을 재 할당 (그러나 2 단위를 10 여분의 공간으로 읽음) 한 다음, 80, 160, then 320 ... 함수가 끝나기 전에 공간을 비우지 않고 64 바이트를 사용하지 않는다면, realloc()을 사용하여 할당을 필요한만큼 축소 할 수 있습니다 크기. –

+0

작고 작은 기계가 아니라면 4 KiB 버퍼로 인해 슬픔이 생기지 않습니다. 이런 작은 머신을 사용하고 있다면, 아마도'malloc()'을 사용하지 않았을 것입니다. –

3

더 나은 방법을 위해 할당합니다 입력 메커니즘을 사용하면 같은 getline (또는 scanf)를 사용하는 것입니다 썼다. (참고 :.scanf 그것은 gcc/Linux에서하는 모든 컴파일러에 할당 할 수 있지만, Windows/Codeblocks/gcc하지 않습니다 않음)

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

int main() 
{ 
    char *input; 
    scanf ("%m[^\n]%*c", &input); 
    printf("\n %s [%d]\n\n",input, (int)strlen(input)); 
    free(input); 
    return 0; 
} 

출력 :

$ ./bin/scanfinput 
This is my longer string. 

This is my longer string. [25] 

의 getline 예를

#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
    char *input = NULL;  /* input buffer, NULL forces getline to allocate */ 
    size_t n = 0;   /* maximum characters to read (0 - no limit  */ 
    ssize_t nchr = 0;  /* number of characters actually read   */ 

    if ((nchr = getline (&input, &n, stdin)) != -1) 
     input[--nchr] = 0; /* strip newline */ 

    printf ("\n %s [%zd]\n\n", input, nchr); 
    free(input); 

    return 0; 
} 
+0

감사합니다. 이것은 알려지지 않은 형식 % m, c90으로 작업중인 메신저를 알려줍니다. – lllook

+1

Windows에서 작업하는 경우'codeblocks' 등을 사용하면'scanf'가 할당되지 않습니다.'getline'을 사용하십시오. Linux 용으로 만 업데이트하겠습니다. gnu 확장자로'gcc/C89' 작업을하고있었습니다. –

+0

리눅스 코드 블럭에서 컴파일 중임 – lllook

관련 문제