如何读取未知长度的输入字符串?

问题描述 投票:0回答:11

如果我不知道这个词有多长,我就无法写

char m[6];

这个词的长度可能有十到二十长。 如何使用
scanf
从键盘获取输入?

#include <stdio.h>
int main(void)
{
    char  m[6];
    printf("please input a string with length=5\n");
    scanf("%s",&m);
    printf("this is the string: %s\n", m);
    return 0;
}

请输入长度=5的字符串
输入:你好
这是字符串:你好

c scanf
11个回答
120
投票

动态保护区域时进入

EG

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

char *inputString(FILE* fp, size_t size){
//The size is extended by the input with the value of the provisional
    char *str;
    int ch;
    size_t len = 0;
    str = realloc(NULL, sizeof(*str)*size);//size is start size
    if(!str)return str;
    while(EOF!=(ch=fgetc(fp)) && ch != '\n'){
        str[len++]=ch;
        if(len==size){
            str = realloc(str, sizeof(*str)*(size+=16));
            if(!str)return str;
        }
    }
    str[len++]='\0';

    return realloc(str, sizeof(*str)*len);
}

int main(void){
    char *m;

    printf("input string : ");
    m = inputString(stdin, 10);
    printf("%s\n", m);

    free(m);
    return 0;
}

25
投票

使用当今的计算机,您可以分配非常大的字符串(数十万个字符),同时几乎不会减少计算机的 RAM 使用量。所以我不会太担心。

然而,在过去,当内存非常宝贵时,常见的做法是分块读取字符串。

fgets
从输入中读取最大数量的字符,但保持输入缓冲区的其余部分不变,因此您可以根据需要从中读取其余部分。

在这个例子中,我读取了 200 个字符的块,但是您当然可以使用您想要的任何块大小。

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

char* readinput()
{
#define CHUNK 200
   char* input = NULL;
   char tempbuf[CHUNK];
   size_t inputlen = 0, templen = 0;
   do {
       fgets(tempbuf, CHUNK, stdin);
       templen = strlen(tempbuf);
       input = realloc(input, inputlen+templen+1);
       strcpy(input+inputlen, tempbuf);
       inputlen += templen;
    } while (templen==CHUNK-1 && tempbuf[CHUNK-2]!='\n');
    return input;
}

int main()
{
    char* result = readinput();
    printf("And the result is [%s]\n", result);
    free(result);
    return 0;
}

请注意,这是一个简化的示例,没有进行错误检查;在现实生活中,您必须通过验证

fgets
的返回值来确保输入正确。

还要注意,如果 readinput 例程结束,则不会浪费任何字节;该字符串具有所需的确切内存大小。


16
投票

我只见过一种读取任意长字符串的“简单”方法,但我从未使用过它。我想事情是这样的: char *m = NULL; printf("please input a string\n"); scanf("%ms",&m); if (m == NULL) fprintf(stderr, "That string was too long!\n"); else { printf("this is the string %s\n",m); /* ... any other use of m */ free(m); }

m

%
之间的
s
告诉
scanf()
测量字符串并为其分配内存并将字符串复制到其中,并将分配的内存的地址存储在相应的参数中。一旦你完成了它,你必须
free()
它。

不过,并非所有

scanf()

的实现都支持这一点。


正如其他人指出的那样,最简单的解决方案是对输入的长度设置限制。如果您仍然想使用

scanf()

那么您可以这样做:


char m[100]; scanf("%99s",&m);

请注意,
m[]

的大小必须至少比

%
s
之间的数字大1个字节。

如果输入的字符串超过 99,则剩余字符将等待由另一个调用或传递给

scanf()

的其余格式字符串读取。


通常不建议使用

scanf()

来处理用户输入。它最适用于由其他应用程序创建的基本结构化文本文件。即使如此,您也必须意识到输入的格式可能不符合您的预期,因为有人可能会干扰它以试图破坏您的程序。

    


10
投票
getline

函数会自动分配所需大小的字符串,因此无需猜测字符串的大小。以下代码演示了用法:


#include <stdio.h> #include <stdlib.h> int main(void) { char *line = NULL; size_t len = 0; ssize_t read; while ((read = getline(&line, &len, stdin)) != -1) { printf("Retrieved line of length %zu :\n", read); printf("%s", line); } if (ferror(stdin)) { /* handle error */ } free(line); return 0; }



6
投票

声明一个足够大的缓冲区来容纳字符串:

char user_input[255];


安全

的方式获取用户输入:

fgets(user_input, 255, stdin);


获取输入的安全方法,第一个参数是指向存储输入的缓冲区的指针,第二个参数是函数应读取的最大输入,第三个参数是指向标准输入的指针 - 即用户输入的位置来自。

安全性尤其来自第二个参数,它限制了读取量,从而防止缓冲区溢出。此外,

fgets

还负责对处理后的字符串进行空终止。


有关该功能的更多信息

此处

编辑:如果您需要进行任何格式化(例如将字符串转换为数字),您可以在输入后使用

atoi


3
投票

char *readline(char *prompt) { size_t size = 80; char *str = malloc(sizeof(char) * size); int c; size_t len = 0; printf("%s", prompt); while (EOF != (c = getchar()) && c != '\r' && c != '\n') { str[len++] = c; if(len == size) str = realloc(str, sizeof(char) * (size *= 2)); } str[len++]='\0'; return realloc(str, sizeof(char) * len); }



1
投票
fgets()

直接读入分配的空间。


需要特别注意区分读取成功、文件结束、输入错误和内存不足。 EOF 需要适当的内存管理。

此方法保留一行的

'\n'


#include <stdio.h> #include <stdlib.h> #define FGETS_ALLOC_N 128 char* fgets_alloc(FILE *istream) { char* buf = NULL; size_t size = 0; size_t used = 0; do { size += FGETS_ALLOC_N; char *buf_new = realloc(buf, size); if (buf_new == NULL) { // Out-of-memory free(buf); return NULL; } buf = buf_new; if (fgets(&buf[used], (int) (size - used), istream) == NULL) { // feof or ferror if (used == 0 || ferror(istream)) { free(buf); buf = NULL; } return buf; } size_t length = strlen(&buf[used]); if (length + 1 != size - used) break; used += length; } while (buf[used - 1] != '\n'); return buf; }

使用示例

int main(void) { FILE *istream = stdin; char *s; while ((s = fgets_alloc(istream)) != NULL) { printf("'%s'", s); free(s); fflush(stdout); } if (ferror(istream)) { puts("Input error"); } else if (feof(istream)) { puts("End of file"); } else { puts("Out of memory"); } return 0; }



1
投票
getchar()

函数:-


#include <stdio.h> #include <stdlib.h> #include <string.h> //I had putten the main Function Bellow this function. //d for asking string,f is pointer to the string pointer void GetStr(char *d,char **f) { printf("%s",d); for(int i =0;1;i++) { if(i)//I.e if i!=0 *f = (char*)realloc((*f),i+1); else *f = (char*)malloc(i+1); (*f)[i]=getchar(); if((*f)[i] == '\n') { (*f)[i]= '\0'; break; } } } int main() { char *s =NULL; GetStr("Enter the String:- ",&s); printf("Your String:- %s \nAnd It's length:- %lu\n",s,(strlen(s))); free(s); }

这是该程序的示例运行:-

Enter the String:- I am Using Linux Mint XFCE 18.2 , eclispe CDT and GCC7.2 compiler!! Your String:- I am Using Linux Mint XFCE 18.2 , eclispe CDT and GCC7.2 compiler!! And It's length:- 67



1
投票

char *fgets (char *str, int size, FILE* file);

否则,您也可以使用动态提供请求的内存的 
malloc()

函数在运行时分配内存。

    


0
投票

#include<stdio.h> #include<malloc.h> int main() { char *str,ch; int size=10,len=0; str=realloc(NULL,sizeof(char)*size); if(!str)return str; while(EOF!=scanf("%c",&ch) && ch!="\n") { str[len++]=ch; if(len==size) { str = realloc(str,sizeof(char)*(size+=10)); if(!str)return str; } } str[len++]='\0'; printf("%s\n",str); free(str); }



0
投票

#include <stdio.h> #include <stdlib.h> #include <string.h> typedef char* string; typedef struct stringClass { char ch; struct stringClass *next; }stringClass; void get_str(char **str) { char ch, *buffer, a; stringClass *new = NULL; stringClass *head = NULL, *tmp = NULL; int c = 0, k = 0; while ((ch = getchar()) != '\n') { new = malloc(sizeof(stringClass)); if(new == NULL) { return NULL; } new->ch = ch; new->next = NULL; new->next = head; head = new; } tmp = head; while (tmp != NULL) { c++; tmp = tmp->next; } if(c == 0) { *str = ""; } else { buffer = malloc(sizeof(char) * (c + 1)); *str = malloc(sizeof(char) * (c + 1)); if(buffer == NULL || *str == NULL) { return NULL; } tmp = head; while (tmp != NULL) { buffer[k] = tmp->ch; k++; tmp = tmp->next; } buffer[k] = '\0'; for (int i = 0, j = strlen(buffer)-1; i < j; i++, j--) { a = buffer[i]; buffer[i] = buffer[j]; buffer[j] = a; } strcpy(*str, buffer); // Dealloc free(buffer); while (head != NULL) { tmp = head; head = head->next; free(tmp); } } } int main() { string str; printf("Enter text: "); get_str(&str); printf("%s\n", str); return 0; }

© www.soinside.com 2019 - 2024. All rights reserved.