Cプログラムを使用してユーザーが入力した名前を読みたい。
このために私は書いた:
char name[20];
printf("Enter name: ");
gets(name);
しかし、gets
を使用するのは良くないので、より良い方法は何ですか?
nevergets
(または無制限の文字列サイズのscanf
)を使用する必要があります。これにより、バッファオーバーフローが発生する可能性があります。 fgets
ハンドルでstdin
を使用すると、バッファーに配置されるデータを制限できるためです。
以下は、ユーザーからの行入力に使用する小さなスニペットです。
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
これにより、最大サイズを設定し、行に入力されたデータが多すぎるかどうかを検出し、残りの行もフラッシュして、次の入力操作に影響を与えないようにします。
次のようなものでテストできます:
// Test program for getLine().
int main (void) {
int rc;
char buff[10];
rc = getLine ("Enter string> ", buff, sizeof(buff));
if (rc == NO_INPUT) {
// Extra NL since my system doesn't output that on EOF.
printf ("\nNo input\n");
return 1;
}
if (rc == TOO_LONG) {
printf ("Input too long [%s]\n", buff);
return 1;
}
printf ("OK [%s]\n", buff);
return 0;
}
ユーザーが入力した文字列を読み取るための最良かつ最も安全な方法は、 getline()
を使用することです
これを行う方法の例を次に示します。
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *buffer = NULL;
int read;
unsigned int len;
read = getline(&buffer, &len, stdin);
if (-1 != read)
puts(buffer);
else
printf("No line read...\n");
printf("Size read: %d\n Len: %d\n", read, len);
free(buffer);
return 0;
}
POSIXシステムでは、可能であれば getline
を使用する必要があります。
また、Chuck Falconerのパブリックドメインggets
関数を使用して、gets
に近い構文を提供できますが、問題はありません。 (チャックファルコナーのウェブサイトは利用できなくなりましたが、 archive.orgにはコピーがあります 、私は ggetsの自分のページ を作成しました。)
私は簡単で素敵な解決策を見つけました:
char*string_acquire(char*s,int size,FILE*stream){
int i;
fgets(s,size,stream);
i=strlen(s)-1;
if(s[i]!='\n') while(getchar()!='\n');
if(s[i]=='\n') s[i]='\0';
return s;
}
これはfgetsに基づいていますが、「\ n」およびstdinの余分な文字はありません(すべてのOSで機能しないfflush(stdin)を置き換えるため、この後に文字列を取得する必要がある場合に便利です)。
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
はnullで終了せず、最後に\n
(またはプラットフォームが使用しているもの)を含みます。ストリームに対する次のI/O操作の後に無効になります。返されたline
バッファーを変更できます。
Scanf関数を使用して文字列を読み取ることができます
scanf("%[^\n]",name);
文字列を受信する他のより良いオプションについては知りません、