web-dev-qa-db-ja.com

未知の長さの入力文字列を読み取るにはどうすればよいですか?

Wordの長さがわからない場合、char m[6];と書くことができません。
Wordの長さは、おそらく10または20の長さです。 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;
}

lenght = 5の文字列を入力してください
こんにちは
これは文字列です:こんにちは

57

領域を動的に確保しながら入力

例えば。

#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(char)*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(char)*(size+=16));
            if(!str)return str;
        }
    }
    str[len++]='\0';

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

int main(void){
    char *m;

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

    free(m);
    return 0;
}
84
BLUEPIXY

今日のコンピューターでは、コンピューターの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);
       inputlen += templen;
       input = realloc(input, inputlen+1);
       strcat(input, tempbuf);
    } 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ルーチンの場合、バイトが無駄にならないことに注意してください。文字列には、必要な正確なメモリサイズがあります。

13
Mr Lister

simple任意の長い文字列を読み取る方法は1つしか見ていませんが、使用したことはありません。私はそれがこのようになると思う:

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()はユーザー入力の処理には推奨されません。別のアプリケーションで作成された基本的な構造化テキストファイルに最適です。その場合でも、誰かがあなたのプログラムを壊そうとするために入力に干渉したかもしれないので、入力が期待どおりにフォーマットされないかもしれないことに注意する必要があります。

9
sh1

より安全なアプローチを提案する場合:

文字列を保持するのに十分な大きさのバッファを宣言します。

char user_input[255];

safeの方法でユーザー入力を取得します。

fgets(user_input, 255, stdin);

入力を取得する安全な方法。最初の引数は入力が保存されるバッファへのポインタ、2番目は関数が読み込むべき最大入力、3番目は標準入力へのポインタ-ユーザー入力が来る場所から。

特に安全性は、バッファオーバーランを防ぐ読み取り量を制限する2番目の引数から得られます。また、fgetsは、処理された文字列のヌル終了を処理します。

その関数の詳細 here

編集:書式設定(文字列を数値に変換するなど)が必要な場合は、入力が完了したら atoi を使用できます。

5
Nobilis

より安全で高速な(2倍の容量)バージョン:

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);
}
3
KIM Taegyoon

文字ポインターを使用して、必要な文字列を格納します。文字列の可能なサイズについて何らかの考えがある場合は、関数を使用します

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

それ以外の場合は、要求されたメモリを動的に提供するmalloc()関数を使用して、ランタイムにもメモリを割り当てることができます。

1
Dayal rai

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;
}
0
chux

私は4年後に到着し、遅すぎることを知っていますが、誰かが使用できる別の方法があると思います。私はこのような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
0
user8677351

また、標準の入力と出力を備えたソリューションもあります

#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