什么是阅读一个C控制台程序输入的文本可能有一个可变长度的全线最简单的方法,我们不能对内容做任何假设。
Answer 1:
您需要动态内存管理,并使用fgets
函数来读取你的路线。 然而,似乎没有办法,看看有多少个字符阅读。 所以,你使用龟etc:
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;
}
注意 :不要使用gets! 它不会做边界检查,可以溢出您的缓冲区
Answer 2:
如果您使用的是GNU C库或其他兼容POSIX库,你可以使用getline()
并通过stdin
到它的文件流。
Answer 3:
一个非常简单的,但不安全的实现来读取静态分配线:
char line[1024];
scanf("%[^\n]", line);
一个更安全的实现,没有缓冲区溢出的可能性,但与不读整行的可能性是:
char line[1024];
scanf("%1023[^\n]", line);
未指定声明变量的长度和格式字符串指定的长度之间的“由一个差”。 这是一个历史的假象。
Answer 4:
您可能需要通过字符(GETC())循环使用的字符,以确保你没有缓冲区溢出,不截断输入。
Answer 5:
getline
运行的例子
提到这个答案 ,但这里有一个例子。
这是POSIX 7 ,分配内存对我们来说,和很好的重用上循环分配的缓冲区。
指针newbs,这样说的: 为什么函数getline的第一个参数的指针,指针“字符**”,而不是“字符*”?
#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
与任意的行终止符。
双打每当需要增加分配的内存,并期待线程安全的。
它需要一定的宏观扩张,但你不可能做的更好。
Answer 6:
所以,如果你要找的命令参数,看看添的回答。 如果你只是想读从控制台线:
#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读取一条线吗?”的问题时,我想一个人需要简单的东西,像gets()函数,而不是100行代码像上面。 其实我觉得,如果你尝试写的100行的在现实中的代码,你会做更多的错误,比你会做这样的事,你得选择;)
Answer 7:
至于建议,你可以使用的getchar()从控制台读取,直到最终的行或EOF返回,建立自己的缓冲区。 成长的缓冲区,如果你不能设置一个合理的最大行大小可以动态地发生。
你可以用也用fgets作为一种安全的方式来获得线为C空值终止字符串:
#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不会溢出线[],它会确保有一个成功返回的最后一个接受的字符之后空。
如果的行结束为止,终止“\ 0”之前的字符将是一个“\ N”。
如果存在之前结束“\ 0”没有终止“\ n”也可以是,有更多的数据,或者下一个请求将报告结束文件。 你必须做的另一个与fgets,以确定哪个是哪个。 (在这一点上,在使用getchar循环()更容易。)
在(更新)例如上面的代码,如果成功与fgets后线[的sizeof(线)-1] ==“\ 0”,就知道该缓冲液完全填充。 如果该位置由“\ n”进行你知道你是幸运的。 否则,要么是更多的数据或档案结尾提前了在标准输入。 (当缓冲区没有完全填满,你仍然可能在最终文件中,有也可能不是一个“\ n”在当前行的末尾。既然你已经扫描字符串查找和/或消除串结束前的任何“\ n”(第一“\ 0”在缓冲液中),我倾向于使用的getchar()在第一位置更喜欢)。
你需要做的处理仍然有比你读的第一块量多行的内容。 可以由动态生长缓冲的实例与任一的getchar或与fgets上班。 有一些棘手的边界情况需要注意的(如记住有一个输入开始在的“\ 0”,结束之前的输入延长缓冲之前的位置存储)。
Answer 8:
很多人跟我一样,来到这个帖子什么是搜索标题匹配,虽然说明是怎么说的可变长度。 在大多数情况下,我们所知道的长度事先。
如果你知道前手的长度,请尝试以下:
char str1[1001] = { 0 };
fgets(str1, 1001, stdin); // 1000 chars may be read
来源: https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm
Answer 9:
如何阅读在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!
Answer 10:
我碰到了同样的问题来了,前一段时间,这是我solutuion,希望它帮助。
/*
* 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;
}
Answer 11:
在BSD系统和Android也可以使用fgetln
:
#include <stdio.h>
char *
fgetln(FILE *stream, size_t *len);
像这样:
size_t line_len;
const char *line = fgetln(stdin, &line_len);
该line
是不是空终止,并包含\n
到底(或任何平台使用)。 它成为投产的下一个I / O操作后无效。
Answer 12:
事情是这样的:
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;
}
Answer 13:
这个函数应该做你想要什么:
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 );
我希望这有帮助。