Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I read an input string of unknown length?

Tags:

c

scanf

If I don't know how long the word is, I cannot write char m[6];,
The length of the word is maybe ten or twenty long. How can I use scanf to get input from the keyboard?

#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;
}

please input a string with length=5
input: hello
this is the string: hello

like image 424
showkey Avatar asked Jun 01 '13 07:06

showkey


People also ask

How do you find the input of a string given the length?

Below is my code: Scanner sc=new Scanner(System.in); int T=sc. nextInt(); for(int i=1;i<=T;i++) { int Strlength=sc. nextInt(); String strnew=sc.

How do you declare a string without specifying length?

char w[7] = {'H', 'e', 'l', 'l', 'o', '\0', '\0'}; When used as a string, the first \0 is end of string and anything after it is ignored (not read by string functions). Even if you rewrite the last element of the example char array by a printable character (e.g. w[6] = '!

How do you read string inputs with spaces?

Once the character is equal to New-line ('\n'), ^ (XOR Operator ) gives false to read the string. So we use “%[^\n]s” instead of “%s”. So to get a line of input with space we can go with scanf(“%[^\n]s”,str);


8 Answers

Enter while securing an area dynamically

E.G.

#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; } 
like image 184
BLUEPIXY Avatar answered Sep 22 '22 02:09

BLUEPIXY


With the computers of today, you can get away with allocating very large strings (hundreds of thousands of characters) while hardly making a dent in the computer's RAM usage. So I wouldn't worry too much.

However, in the old days, when memory was at a premium, the common practice was to read strings in chunks. fgets reads up to a maximum number of chars from the input, but leaves the rest of the input buffer intact, so you can read the rest from it however you like.

in this example, I read in chunks of 200 chars, but you can use whatever chunk size you want of course.

#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;
}

Note that this is a simplified example with no error checking; in real life you will have to make sure the input is OK by verifying the return value of fgets.

Also note that at the end if the readinput routine, no bytes are wasted; the string has the exact memory size it needs to have.

like image 26
Mr Lister Avatar answered Sep 19 '22 02:09

Mr Lister


I've seen only one simple way of reading an arbitrarily long string, but I've never used it. I think it goes like this:

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);
}

The m between % and s tells scanf() to measure the string and allocate memory for it and copy the string into that, and to store the address of that allocated memory in the corresponding argument. Once you're done with it you have to free() it.

This isn't supported on every implementation of scanf(), though.

As others have pointed out, the easiest solution is to set a limit on the length of the input. If you still want to use scanf() then you can do so this way:

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

Note that the size of m[] must be at least one byte larger than the number between % and s.

If the string entered is longer than 99, then the remaining characters will wait to be read by another call or by the rest of the format string passed to scanf().

Generally scanf() is not recommended for handling user input. It's best applied to basic structured text files that were created by another application. Even then, you must be aware that the input might not be formatted as you expect, as somebody might have interfered with it to try to break your program.

like image 43
sh1 Avatar answered Sep 21 '22 02:09

sh1


There is a new function in C standard for getting a line without specifying its size. getline function allocates string with required size automatically so there is no need to guess about string's size. The following code demonstrate usage:

#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;
}
like image 30
Parham Alvani Avatar answered Sep 20 '22 02:09

Parham Alvani


Safer and faster (doubling capacity) version:

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);
}
like image 27
KIM Taegyoon Avatar answered Sep 22 '22 02:09

KIM Taegyoon


Take a character pointer to store required string.If you have some idea about possible size of string then use function

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

else you can allocate memory on runtime too using malloc() function which dynamically provides requested memory.

like image 45
Dayal rai Avatar answered Sep 22 '22 02:09

Dayal rai


If I may suggest a safer approach:

Declare a buffer big enough to hold the string:

char user_input[255];

Get the user input in a safe way:

fgets(user_input, 255, stdin);

A safe way to get the input, the first argument being a pointer to a buffer where the input will be stored, the second the maximum input the function should read and the third is a pointer to the standard input - i.e. where the user input comes from.

Safety in particular comes from the second argument limiting how much will be read which prevents buffer overruns. Also, fgets takes care of null-terminating the processed string.

More info on that function here.

EDIT: If you need to do any formatting (e.g. convert a string to a number), you can use atoi once you have the input.

like image 44
Nobilis Avatar answered Sep 19 '22 02:09

Nobilis


Read directly into allocated space with fgets().

Special care is need to distinguish a successful read, end-of-file, input error and out-of memory. Proper memory management needed on EOF.

This method retains a line's '\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;
}

Sample usage

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;
}
like image 23
chux - Reinstate Monica Avatar answered Sep 23 '22 02:09

chux - Reinstate Monica