콘솔에서 C로 줄을 읽는 방법은 무엇입니까?
C 콘솔 프로그램에서 전체 줄을 읽는 가장 간단한 방법은 무엇입니까 입력 된 텍스트는 가변 길이를 가질 수 있으며 내용에 대해 어떤 가정도 할 수 없습니다.
동적 메모리 관리가 필요하고 fgets
기능을 사용 하여 라인을 읽습니다. 그러나 얼마나 많은 문자를 읽었는지 확인할 방법이없는 것 같습니다. 따라서 fgetc를 사용합니다.
char * getline(void) {
char * line = malloc(100), * linep = line;
size_t lenmax = 100, len = lenmax;
int c;
if(line == NULL)
return NULL;
for(;;) {
c = fgetc(stdin);
if(c == EOF)
break;
if(--len == 0) {
len = lenmax;
char * linen = realloc(linep, lenmax *= 2);
if(linen == NULL) {
free(linep);
return NULL;
}
line = linen + (line - linep);
linep = linen;
}
if((*line++ = c) == '\n')
break;
}
*line = '\0';
return linep;
}
참고 : get을 사용하지 마십시오! 경계 검사를 수행하지 않으며 버퍼를 오버플로 할 수 있습니다.
GNU C 라이브러리 또는 다른 POSIX 호환 라이브러리를 사용 하는 경우 파일 스트림을 위해 사용 getline()
하고 전달할 수 있습니다 stdin
.
정적 할당을 위해 줄을 읽는 매우 간단하지만 안전하지 않은 구현 :
char line[1024];
scanf("%[^\n]", line);
버퍼 오버플로의 가능성은 없지만 전체 행을 읽지 않을 가능성이있는 더 안전한 구현은 다음과 같습니다.
char line[1024];
scanf("%1023[^\n]", line);
변수를 선언하는 지정된 길이와 형식 문자열에 지정된 길이 사이의 '1만큼 차이'가 아닙니다. 역사적인 유물입니다.
버퍼 오버플로가없고 입력을 자르지 않도록 문자 별 (getc ()) 루프를 사용해야 할 수도 있습니다.
따라서 명령 인수를 찾고 있다면 Tim의 대답을 살펴보십시오. 콘솔에서 한 줄을 읽고 싶다면 :
#include <stdio.h>
int main()
{
char string [256];
printf ("Insert your full address: ");
gets (string);
printf ("Your address is: %s\n",string);
return 0;
}
예, 안전하지 않습니다. 버퍼 오버런을 수행 할 수 있으며 파일 끝을 확인하지 않으며 인코딩 및 기타 많은 항목을 지원하지 않습니다. 사실 나는 그것이 이런 일을하는지 생각조차하지 않았다. 나는 내가 약간 망친 것에 동의한다 :)하지만 ... "어떻게 C로 콘솔에서 한 줄을 읽는가?"와 같은 질문을 볼 때, 나는 사람이 100 줄의 코드가 아닌 gets ()와 같은 간단한 것을 필요로한다고 가정한다. 위와 같이. 실제로 100 줄의 코드를 실제로 작성하려고하면 실수를 더 많이하게 될 것이라고 생각합니다.
getline
실행 가능한 예
이 답변에 대해 언급 했지만 여기에 예가 있습니다.
그것은 POSIX 7 이고, 우리를 위해 메모리를 할당하고, 할당 된 버퍼를 루프에서 멋지게 재사용합니다.
포인터 newbs, 이것을 읽으십시오 : 왜 getline의 첫 번째 인수가 "char *"대신 "char **"포인터에 대한 포인터입니까?
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char *line = NULL;
size_t len = 0;
ssize_t read = 0;
while (read != -1) {
puts("enter a line");
read = getline(&line, &len, stdin);
printf("line = %s", line);
printf("line length = %zu\n", read);
puts("");
}
free(line);
return 0;
}
glibc 구현
POSIX가 없습니까? 아마도 glibc 2.23 구현 을보고 싶을 것 입니다.
이는 임의의 줄 종결자가 getdelim
있는 단순 POSIX 상위 집합 인 getline
으로 확인됩니다.
증가가 필요할 때마다 할당 된 메모리를 두 배로 늘리고 스레드로부터 안전 해 보입니다.
매크로 확장이 필요하지만 훨씬 더 잘할 수는 없습니다.
제안 된대로 getchar ()를 사용하여 줄 끝이나 EOF가 반환 될 때까지 콘솔에서 읽을 수 있으며 자체 버퍼를 구축 할 수 있습니다. 적절한 최대 라인 크기를 설정할 수없는 경우 버퍼가 동적으로 증가 할 수 있습니다.
또한 fgets를 사용하여 C null로 끝나는 문자열로 라인을 얻는 안전한 방법을 사용할 수 있습니다.
#include <stdio.h>
char line[1024]; /* Generously large value for most situations */
char *eof;
line[0] = '\0'; /* Ensure empty line if no input delivered */
line[sizeof(line)-1] = ~'\0'; /* Ensure no false-null at end of buffer */
eof = fgets(line, sizeof(line), stdin);
콘솔 입력을 다 사용했거나 어떤 이유로 작업이 실패한 경우 eof == NULL이 반환되고 라인 버퍼가 변경되지 않을 수 있습니다 (이것이 첫 번째 문자를 '\ 0'으로 설정하는 것이 편리한 이유입니다).
fgets는 line []을 넘치지 않으며 성공적인 리턴시 마지막으로 승인 된 문자 뒤에 널이 있는지 확인합니다.
줄 끝에 도달하면 '\ 0'으로 끝나는 앞의 문자는 '\ n'이됩니다.
종료 '\ 0'전에 종료 '\ n'이 없으면 더 많은 데이터가 있거나 다음 요청이 파일 끝을보고 할 수 있습니다. 어느 것이 무엇인지 결정하기 위해 다른 fgets를 수행해야합니다. (이 점에서 getchar ()로 반복하는 것이 더 쉽습니다.)
위의 (업데이트 된) 예제 코드에서, 성공적인 fgets 후 line [sizeof (line) -1] == '\ 0'이면 버퍼가 완전히 채워진 것을 알 수 있습니다. 그 위치가 '\ n'에 의해 진행된다면 당신은 운이 좋았다는 것을 알고 있습니다. 그렇지 않으면 stdin에 더 많은 데이터 또는 파일 끝이 있습니다. (버퍼가 완전히 채워지지 않은 경우에도 여전히 파일의 끝에있을 수 있으며 현재 줄 끝에 '\ n'이 없을 수도 있습니다. 문자열을 검색하여 찾아야하기 때문에 / 또는 문자열 끝 (버퍼의 첫 번째 '\ 0') 앞의 '\ n'을 제거하면 처음부터 getchar ()를 사용하는 것을 선호합니다.)
첫 번째 청크로 읽은 양보다 더 많은 줄이있는 것을 처리하기 위해해야 할 일을하십시오. 동적으로 늘어나는 버퍼의 예는 getchar 또는 fget과 함께 작동하도록 만들 수 있습니다. 주의해야 할 몇 가지 까다로운 경우가 있습니다 (예 : 버퍼가 확장되기 전에 이전 입력을 종료 한 '\ 0'위치에 다음 입력이 저장되기 시작하는 것을 기억하는 것과 같은).
저와 같은 많은 사람들이 검색된 제목과 일치하는 제목으로이 게시물을 찾습니다. 설명은 가변 길이에 대해 말하고 있습니다. 대부분의 경우 길이를 미리 알고 있습니다.
미리 길이를 알고 있다면 아래에서 시도해보십시오.
char str1[1001] = { 0 };
fgets(str1, 1001, stdin); // 1000 chars may be read
출처 : https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm
콘솔에서 C로 줄을 읽는 방법은 무엇입니까?
자신의 함수를 구축 하는 것은 C 로 콘솔에서 한 줄을 읽는 데 도움이되는 방법 중 하나입니다 .
동적 메모리 할당 을 사용 하여 문자와 함께 한 줄의 모든 문자를 유지하는 데 필요한 충분한 양의 메모리 만 할당 하고
'\0'
있습니다.그리고 여기
getchar()
에서는 사용자가 입력'\n'
하거나EOF
문자를 입력 할 때까지 함수를 사용하여 문자열의 각 문자를 하나씩 스캔하는 루프를 사용하고 있습니다.//the function to read lines of variable length char* scan_line(char *line) { int ch; //as getchar() returns `int` if( (line = malloc(sizeof(char))) == NULL) //allocating memory { //checking if allocation was successful or not printf("unsuccessful allocation"); exit(1); } line[0]='\0'; for(int index = 0; ( (ch = getchar())!='\n' ) && (ch != EOF) ; index++) { if( (line = realloc(line, (index + 2)*sizeof(char))) == NULL ) { //checking if reallocation was successful or not printf("unsuccessful reallocation"); exit(1); } line[index] = (char) ch; //type casting `int` to `char` line[index + 1] = '\0'; //inserting null character at the end } return line; }
이제 다음과 같이 전체 줄을 읽을 수 있습니다.
char *line = NULL; line = scan_line(line);
다음 은 함수를 사용 하는 예제 프로그램입니다scan_line()
.
#include <stdio.h>
#include <stdlib.h> //for dynamic allocation functions
char* scan_line(char *line)
{
..........
}
int main(void)
{
char *a = NULL;
a = scan_line(a); //function call to scan the line
printf("%s\n",a); //printing the scanned line
free(a); //don't forget to free the malloc'd pointer
}
샘플 입력 :
Twinkle Twinkle little star.... in the sky!
샘플 출력 :
Twinkle Twinkle little star.... in the sky!
나는 얼마 전에 같은 문제를 만났고 이것이 나의 해결책이었습니다.
/*
* Initial size of the read buffer
*/
#define DEFAULT_BUFFER 1024
/*
* Standard boolean type definition
*/
typedef enum{ false = 0, true = 1 }bool;
/*
* Flags errors in pointer returning functions
*/
bool has_err = false;
/*
* Reads the next line of text from file and returns it.
* The line must be free()d afterwards.
*
* This function will segfault on binary data.
*/
char *readLine(FILE *file){
char *buffer = NULL;
char *tmp_buf = NULL;
bool line_read = false;
int iteration = 0;
int offset = 0;
if(file == NULL){
fprintf(stderr, "readLine: NULL file pointer passed!\n");
has_err = true;
return NULL;
}
while(!line_read){
if((tmp_buf = malloc(DEFAULT_BUFFER)) == NULL){
fprintf(stderr, "readLine: Unable to allocate temporary buffer!\n");
if(buffer != NULL)
free(buffer);
has_err = true;
return NULL;
}
if(fgets(tmp_buf, DEFAULT_BUFFER, file) == NULL){
free(tmp_buf);
break;
}
if(tmp_buf[strlen(tmp_buf) - 1] == '\n') /* we have an end of line */
line_read = true;
offset = DEFAULT_BUFFER * (iteration + 1);
if((buffer = realloc(buffer, offset)) == NULL){
fprintf(stderr, "readLine: Unable to reallocate buffer!\n");
free(tmp_buf);
has_err = true;
return NULL;
}
offset = DEFAULT_BUFFER * iteration - iteration;
if(memcpy(buffer + offset, tmp_buf, DEFAULT_BUFFER) == NULL){
fprintf(stderr, "readLine: Cannot copy to buffer\n");
free(tmp_buf);
if(buffer != NULL)
free(buffer);
has_err = true;
return NULL;
}
free(tmp_buf);
iteration++;
}
return buffer;
}
BSD 시스템 및 Android에서는 다음을 사용할 수도 있습니다 fgetln
.
#include <stdio.h>
char *
fgetln(FILE *stream, size_t *len);
Like so:
size_t line_len;
const char *line = fgetln(stdin, &line_len);
The line
is not null terminated and contains \n
(or whatever your platform is using) in the end. It becomes invalid after the next I/O operation on stream.
Something like this:
unsigned int getConsoleInput(char **pStrBfr) //pass in pointer to char pointer, returns size of buffer
{
char * strbfr;
int c;
unsigned int i;
i = 0;
strbfr = (char*)malloc(sizeof(char));
if(strbfr==NULL) goto error;
while( (c = getchar()) != '\n' && c != EOF )
{
strbfr[i] = (char)c;
i++;
strbfr = (void*)realloc((void*)strbfr,sizeof(char)*(i+1));
//on realloc error, NULL is returned but original buffer is unchanged
//NOTE: the buffer WILL NOT be NULL terminated since last
//chracter came from console
if(strbfr==NULL) goto error;
}
strbfr[i] = '\0';
*pStrBfr = strbfr; //successfully returns pointer to NULL terminated buffer
return i + 1;
error:
*pStrBfr = strbfr;
return i + 1;
}
This function should do what you want:
char* readLine( FILE* file )
{
char buffer[1024];
char* result = 0;
int length = 0;
while( !feof(file) )
{
fgets( buffer, sizeof(buffer), file );
int len = strlen(buffer);
buffer[len] = 0;
length += len;
char* tmp = (char*)malloc(length+1);
tmp[0] = 0;
if( result )
{
strcpy( tmp, result );
free( result );
result = tmp;
}
strcat( result, buffer );
if( strstr( buffer, "\n" ) break;
}
return result;
}
char* line = readLine( stdin );
/* Use it */
free( line );
I hope this helps.
참고URL : https://stackoverflow.com/questions/314401/how-to-read-a-line-from-the-console-in-c
'Programming' 카테고리의 다른 글
범위 생성에서 '..'(이중 점)과 '…'(삼중 점)의 차이점은 무엇입니까? (0) | 2020.08.23 |
---|---|
Ruby 배열 : select (), collect () 및 map () (0) | 2020.08.23 |
Git 내부에서 Winmerge를 사용하여 파일 비교 (0) | 2020.08.23 |
스택이나 재귀를 사용하지 않고 Morris inorder tree traversal을 설명하십시오. (0) | 2020.08.23 |
uint_fast32_t는 무엇이며 일반 int 및 uint32_t 대신 사용해야하는 이유는 무엇입니까? (0) | 2020.08.23 |