를 사용해야 하 fgets 또는 scanf 으로 한정 입력에서 c?

0

질문

사용해야 합니까 fgets 또는 형식 scanfscanf("%10s", foo).

는 제외 scanf 읽지 않습니다면 빈 문자는 해결될 수 있습니하고 더 많은 물건으로 scanset,왜 나를 사용해야 fgetsscanf?

어떤 도움을 감사하겠습니다.


편집

하나 더 많은 것을 물어보고 싶은 경우에도 우리가 사용하는 fgets 무슨 일이 일어날 경우 사용자가 문자를 입력보다 더 경계선(내가 많은 것을 의미의 캐릭터),그것으로 이어질 buffer overflow? 한 다음을 처리하는 방법은?

c fgets input scanf
2021-11-23 13:53:00
4

최고의 응답

5

대부분의 운영체제에서는 시스템,사용자 입력이 기본적으로 라인을 기반으로 합니다. 그 이유 중 하나는 사용자를 허용하는 누이를 입력,보내기 전에 입력하면 프로그램입니다.

에 대한 온라인 기반의 사용자 입력,그것은 의미있는 직관적인 프로그램에 대한 읽을 줄 하나 입니다. 이것은 어떤 기능 fgets 가(제공하는 버퍼에 저장 전체의 라인 입력).

기능 scanf에,다른 한편으로는,일반적으로 읽지 않습 중 하나는 라인 입력니다. 예를 들어,사용하는 경우 %s%d 변환 형식 지정과 scanf을 소모하지 않습 전체의 라인 입력이 있습니다. 대신,그것은 단지 소비로 많이 입력으로 일치하는 형식으로 변환자입니다. 이 의미는 줄 바꿈 문자의 끝 부분에 라인이 정상적으로 소비(는 쉽게 이어질 수 있는 프로그램의 버그). 또한, scanf%d 변환 형식을 지는 것을 고려와 같이 입력 6sldf23dsfh2 으로 유효한 입력 수 6지만,더 전화 scanf 와 같은 지정이 실패하지 않는 한,당신은 버리의 나머지 부분에 라인에서 입력 스트림입니다.

이 문제의 scanf 카운터-직관적이는 반면,동작 fgets 직관적을 다룰 경우 라인-기반 사용자 입력이 있습니다.

후에 사용하는 fgets당신이 기능을 사용할 수 있습니다 sscanf 문자열에 대한 구문 분석하는 내용의 개인 라인입니다. 이를 계속 사용할 수 있 scansets. 또는 당신이 구문 분석할 수 있습니다 라는 것을 의미합니다. 어느 방법으로 사용 fgetsscanf 읽기 위해 입력할 것입 취급을 하나 선의에 입력 시간은 자연적이고 직관적 처리하는 방법과 선반 사용자 입력이 있습니다.

우리가 사용하는 경우 fgets 무슨 일이 일어날 경우 사용자가 문자를 입력보다 더 경계선(내가 많은 것을 의미의 캐릭터),그것으로 이어질 buffer overflow? 한 다음을 처리하는 방법은?

는 경우에는 사용자가 입력하는 이상의 문자보다는 버퍼에 맞으로 지정하여 두 번째 fgets 함수의 인자하지 않을 것입 overflow 버퍼입니다. 대신,그것은 단지 추출물로서 많은 캐릭터는 입력 스트림으로 버퍼에 맞. 는지 여부를 확인할 수 있습 전체 라인을 읽었는지 확인하여 문자열이 포함되 줄 바꿈 문자 '\n' 니다.

2021-11-23 15:13:39

정말 감사합니다,당신의 대답이 나에게 정말 도움이됩니다.
Becker

의 동작 fgets()은 직관적 인을 위해 입력하지 않는 예상보다.
supercat
2

이것은 일반적으로 논의 항목,전체의 의견을지만 흥미로운 정보를 요청하는 경우가 있습니다. 관찰하는 대다수 사람들의는 이미 대응하는 비슷한 질문에 이 사이트에서 가을의 측면에 fgets(). 나는 그들 중 하나입니다. 내가 찾기 fgets() 훨씬 더 나은 사용하는 사용자 입력을 위해보 scanf() 몇 가지 예외가 있습니다. scanf() 가 많은 것으로 간주 등으로 최적의 처리하는 방법이 사용자 입력. 예를 들어

"...그것은 당신을 말할 것이다지 성공했지만,당신에게 말할 수 있만 약 곳에 실패했으며,모든 방법 또는 이유. 당신 에는 아주 조금 할 수 있는 기회를 어떠한 오류 복구."
(jamesdlin). 그러나의 관심에서 시도 균형을 것이다,시작을 인용하 는 이론.

사용자 입력에서 오 stdin즉,키보드 입력, fgets() 더 나은 선택이 될 것입니다. 그것은 훨씬 더 관대하는 문자열을 읽을 수 있는 완벽히 검증 하기 전에 변환을 시도

중 하나에 몇 번의 양식을 사용하여 scanf(): fscanf() 괜찮을 것이 사용될 수 있습으로 변환할 때 입력에서 매우 통제된 소스에서 즉,독서 엄격하게 형식의 파일을 반복적으로 예측 가능한 필드가 있습니다.

더 많은 토론, 이 비교 의 하이라이트는 두 개의 추가적인 장점과 단점을 두었습니다.

편집:소 OP 추가적인 질문에 대한 오버플로우:

"하나 더 많은 것을 물어보고 싶은 경우에도 우리가 사용하는 fgets 무슨 일이 일어날 경우 사용자가 문자를 입력보다 더 경계선(내가 많은 것을 의미의 캐릭터),그것으로 이어질 buffer overflow? 한 다음을 처리하는 방법 니까?"

[fgets()](https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm 은 멋지게를 방지하기 위해 설계되었 buffer overflow,을 사용하여 간단하게 그것의 매개 변수를 제대로,예를 들어:

char buffer[100] = {0};
...
while fgets(buffer, sizeof buffer, stdin);  

이 방지 입력 보다 큰 버퍼 크기에서 처리되고 있고,따라서을 방지하는 오버플로우가 발생합니다.

도를 사용하여 scanf()을 방지 버퍼 오버플로우 타임 아웃 기능을 사용하여 폭을 지정자 로서 형식 문자열입니다. 를 읽어들이는 경우에 입력 예를 들어 및 제한을 입력 크기에서 사용하는 최대 100 자 코드는 다음이 포함됩니다.

char buffer[101] = {0};// includes space for 100 + 1 for NULL termination

scanf("%100s", buffer);
        ^^^  width specifier 

그러나 숫자,오버플로우가 너무 좋지 않을 사용하여 scanf(). 을 보여주고,사용이 간단한 코드를 입력 두 값에 표시된 코멘트 하나씩 실행:

int main(void)
{
    int val = 0;
    // test with 2147483647 & 2147483648
    scanf("%d", &val);
    printf("%d\n", val);
    
    return 0;
}

두 번째로 가치,내 시스템에서 발생 다음과 같다:

NON-FATAL RUN-TIME ERROR: "test.c", line 11, col 5, thread id 22832: Function scanf: (errno == 34 [0x22]). Range error `

여기에서 읽을 필요가 문자열을,그 다음에는 문자열을 수 변환 중 하나를 사용하여 strto_() 기능: strtol(), strtod(),...). 모두 할 수있는 기능을 포함한 테스트를 위한 오버플로 전에 일으키는 실행 시간이 경고 또는 오류가 있습니다. 를 사용하여 사항에 유의하십시오 atoi(), atod() 을 보호하지 않습니다에서 오버플로나.

2021-11-23 14:10:20

감사합니다,정말 당신의 대답이다.
Becker

질문에"전체의 의견"? 나는 정중하게 동의하지 않는다. 그것의 문제가 아니라 의견이 scanf 은 거의 완전히 쓸모없는,좋은 최상의 읽기 위해,하나의 단순한 입력을 소개하는 C 프로그램,그러나 엄청나게 어렵게 아무것도 할 원격으로 정교한—이는 분명한 사실! :-)
Steve Summit
1

지금까지,모든 대답을 여기에 제시의 복잡한 scanffgets지만,무엇을 믿는 것은 언급 할 가치가있는 두 사람들의 함수는 사용되지 않습니에서 C 표준입니다. Scanf 특히 위험하기 때문에,그것은 모든 종류의 보안 문제를 buffer overflow. fgets 지 않으로 문제가 있지만,경험,경향이 있 비트 투박하고 그에 유용한 연습이다.

진실은,자주 당신이 정말 모르겠어요 얼마나 오래 사용자 입력이 될 것입니다. 당신은 주위에 얻을 수 있습니다 이를 사용하여 fgets 으로 난 것이 충분히 큰 버퍼하지만 정말 ellegant. 대신,당신이 무엇을 자주하고 싶은 동적이 버퍼는 성장할 것을 저장하기에 충분히 큰 어떤 사용자 입력을 제공할 것입니다. 이 때 getline 기능 놀이로 제공됩니다. 그것의 사용을 읽을 수의 캐릭터에서 사용자까지,\n 가 발생. 기본적으로,그것은 하중 전체 라인을 메모리에는 문자열을 사용합니다.

size_t getline(char **lineptr, size_t *n, FILE *stream);

이 함수 포인터를 동적으로 할당된 문자열 로 첫 번째 인수, 그리고 포인터 크기의 버퍼가 할당된 으로 두 번째 인수며 스트림 으로 세 번째 인수로 합니다. (당신이 본질적으로 배치 stdin 가 명령줄 입력). 하고 반환합의 수를 읽을 포함한 문자\n 끝에,하지만 null.

여기,당신이 볼 수 있를 들어이 기능의 사용:

int main() {

printf("Input Something:\n");  // asking user for input

size_t length = 10;                   // creating "base" size of our buffer
char *input_string = malloc(length);  // allocating memory based on our initial buffer size
size_t length_read = getline(&input_string, &length, stdin);  // loading line from console to input_string
// now length_read contains how much characters we read
// and length contains new size of our buffer (if it changed during the getline execution)

printf("Characters read (including end of line but not null at the end)"
       ": %lu, current size of allocated buffer: %lu string: %s"
       , length_read, length, input_string);

free(input_string);    // like any other dynamically-allocated pointer, you must free it after usage
return 0;
}

물론,이 기능을 사용하여 필요한 기본 지식에 대한 포인터 및 동적인 메모리에서 C,그러나 조금 더 복잡한 자연의 getline 은 확실히 가치가 있기 때문에,그것의 제공된 보안 및 유연성을 제공합니다.

에 대해 자세히 알아볼 수 있습이 기능 및 다른 입력 기능이 사용 가능 C 에서는 이 웹 사이트: https://www.studymite.com/blog/strings-in-c 나는 그것을 믿을 요약의 복잡 C 입니다.

2021-11-23 19:18:00

감사에 대한 조언과 링크,그것은 나에게 많은 도움이됩니다.
Becker
1

이 있는 경우 예를 들어 문자 배열 선언

char s[100];

과를 읽고 싶어하는 문자열이 포함된 공백을 포함한 다음 중 하나를 사용할 수 있습니다 scanf 다음 방법:

scanf( "%99[^\n]", s );

fgets 다음과 같:

fgets( s, sizeof( s ), stdin );

의 차이를 이러한 두 개의 전화는 전화 scanf 읽지 않은 새로운 라인 캐릭터 '\n' 에서 입력 버퍼입니다. 동 fgets 를 읽고 새로운 라인 캐릭터 '\n' 은 충분한 공간이 있는 경우에는 문자 배열입니다.

을 제거하는 새로운 라인 캐릭터 '\n' 에 저장된 문자 배열한 후에 사용하는 fgets 당신을 위해 쓸 수 있는 예제:

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

는 경우에 입력된 문자열에는 99 개 이상의 문자 다음에 모두 통화를 읽 99 캐릭터와 추가 일련의 문자로 종료하는 제 캐릭터 '\0'. 나머지 모든 문자는 될 것입니다에 여전히 입력 버퍼입니다.

에 문제가 있으로 fgets. 예를 들어 당기 전에 fgets 거기에 사용되는 scanf 예를 들어:

scanf( "%d", &x );
fgets( s, sizeof( s ), stdin );

고 사용자는 입력입니다:

10
Hello World

다음의 전화 fgets 을 읽만 새로운 라인 캐릭터 '\n' 는 버퍼에 저장된 후 Enter 키를 눌러면 정수 값에서의 전화 scanf 읽습니다.

이 경우에 당신은 필요를 작성하는 코드를 제거하는 새로운 라인 캐릭터 '\n' 를 호출하기 전에 fgets.

당신이 할 수 있다 예를 들어 다음과 같은 방법으로:

scanf( "%d", &x );
scanf( " " );
fgets( s, sizeof( s ), stdin );

를 사용하는 경우 scanf 다음과 같은 상황에서 작성할 수 있습니다:

scanf( "%d", &x );
scanf( " %99[^\n]", s );
       ^^ 
2021-11-23 14:05:15

다른 언어로

이 페이지는 다른 언어로되어 있습니다

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................