[英]How to accept string input only if it of certain length in C else ask user to input the string again
如何在 C 中接受一組字符串作為輸入,如果超過一定長度,如何再次提示用戶重新輸入字符串。 我嘗試如下
#include<stdio.h>
int main()
{
char arr[10][25]; //maximum 10 strings can be taken as input of max length 25
for(int i=0;i<10;i=i+1)
{
printf("Enter string %d:",i+1);
fgets(arr[i],25,stdin);
}
}
但是這里 fgets 也接受大於該長度的字符串。 如果用戶點擊返回,則必須將第二個字符串作為輸入。 我是 C 的新手
僅當字符串輸入具有一定長度時如何接受
形成一個助手 function 來處理各種邊緣情況。 使用fgets()
,然后刪除潛在'\n'
( fgets()
保留)並檢測長輸入。
一些未經測試的代碼給 OP 一個想法:
#include <assert.h>
#include <stdio.h>
// Pass in the max string _size_.
// Return NULL on end-of-file without input.
// Return NULL on input error.
// Otherwise return the buffer pointer.
char* getsizedline(size_t sz, char *buf, const char *reprompt) {
assert(sz > 0 && sz <= INT_MAX && buf != NULL); // #1
while (fgets(buf, (int) sz, stdin)) {
size_t len = strlen(buf);
// Lop off potential \n
if (len > 0 && buf[--len] == '\n') { // #2
buf[len] = '\0';
return buf;
}
// OK if no more input
if (feof(stdin)) { // #3
return buf;
}
// OK if next ends the line
int ch = fgetc(stdin);
if (ch == '\n' || feof(stdin)) { // #4
return buf;
}
// Consume rest of line;
while (ch != '\n' && ch != EOF) { // #5
ch = fgetc(stdin);
}
if (ch == EOF) { // #6
return NULL;
}
if (reprompt) {
fputs(reprompt, stdout);
}
}
return NULL;
}
不常見:讀取null 字符仍然是一個待定問題。
作為學習者的 OP 的詳細信息。
一些針對健全輸入參數的測試。 零大小不允許保存為null 字符終止字符串的任何輸入。 緩沖區可能大於INT_MAX
,但fgets()
不能直接處理。 可以修改代碼以處理 0 和巨大的緩沖區,但將其留到另一天。
fgets()
並不總是讀取'\n'
。 緩沖區可能會先滿,或者文件結尾之前的最后一行可能缺少'\n'
。 不常見的是,可能會讀取null 字符- 甚至是第一個字符,因此len > 0
測試,導致strlen()
不足以確定讀取的字符長度。 如果null 字符輸入需要詳細支持,則代碼需要進行重大更改以適應確定大小。
feof(stdin)
如果之前的fgets()
讀取了一些東西,但是文件結束發生了,那么很高興回到這里。
如果之前的fgets()
填滿了它的緩沖區,並且下一次讀取字符嘗試導致文件結束或'\n'
,則此測試為真並且正常,因此返回成功。
如果先前的fgetc()
導致輸入錯誤,則此循環立即退出。 否則,我們需要使用 rest 來查找'\n'
或EOF
(這可能是由於文件結束或輸入錯誤。)
如果返回EOF
(由於文件結尾或輸入錯誤),則沒有理由繼續。 返回NULL
。
用法
// fgets(arr[i],25,stdin);
if (getsizedline(arr[i], sizeof(arr[i]), "Too long, try again.\n") == NULL) {
break;
}
此代碼使用的緩沖區略大於所需的最大長度。 如果無法將文本行和換行符讀入緩沖區,則讀取該行的 rest 並將其丟棄。 如果可以,它會在太長(或太短)時再次丟棄。
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define INPUTS 10
#define STRMAX 25
int main(void) {
char arr[INPUTS][STRMAX+1];
char buf[STRMAX+4];
for(int i = 0; i < INPUTS; i++) {
bool success = false;
while(!success) {
printf("Enter string %d: ", i + 1);
if(fgets(buf, sizeof buf, stdin) == NULL) {
exit(1); // or sth better
}
size_t index = strcspn(buf, "\n");
if(buf[index] == '\0') { // no newline found
// keep reading until end of line
while(fgets(buf, sizeof buf, stdin) != NULL) {
if(strchr(buf, '\n') != NULL) {
break;
}
}
if(feof(stdin)) {
exit(1); // or sth better
}
continue;
}
if(index < 1 || index > STRMAX) {
continue; // string is empty or too long
}
buf[index] = '\0'; // truncate newline
strcpy(arr[i], buf); // keep this OK string
success = true;
}
}
printf("Results:\n");
for(int i = 0; i < INPUTS; i++) {
printf("%s\n", arr[i]);
}
return 0;
}
fgets()
的好處是它會將換行符( '\n'
)放在輸入緩沖區中。 您所要做的就是尋找它。 如果它在那里,你就會得到一整行輸入。 如果沒有,還有更多內容需要閱讀。
那么策略是:
fgets( s, size_of_s, stdin );
char * p = strpbrk( s, "\r\n" );
if (p)
{
// end of line was found.
*p = '\0';
return s; (the complete line of input)
}
如果p
是NULL
,那么還有更多工作要做。 由於您希望簡單地忽略太長的行,這與丟棄輸入相同。 用一個簡單的循環來做到這一點:
int c;
do c = getchar(); while ((c != EOF) && (c != '\n'));
流通常在幕后緩沖,由 C 庫或操作系統(或兩者)緩沖,但即使它們不是,這也不是太大的開銷。 (在播放“我是一個優化編譯器”之前使用分析器。不要假設 C 庫有壞處。)
一旦你扔掉了所有你不想要的東西(到 EOL),確保你的輸入不在 EOF 並循環要求用戶再試一次。
char * prompt( const char * message, char * s, size_t n )
{
while (!feof( stdin ))
{
// Ask for input
printf( "%s", message );
fflush( stdout ); // This line _may_ be necessary.
// Attempt to get an entire line of input
if (!fgets( s, n, stdin )) break;
char * p = strpbrk( s, "\r\n" );
// Success: return that line (sans newline character(s)) to the user
if (p)
{
*p = '\0';
return s;
}
// Failure: discard the remainder of the line before trying again
int c;
do c = getchar(); while ((c != EOF) && (c != '\n'));
}
// If we get this far it is because we have
// reached EOF or some other input error occurred.
return NULL;
}
現在您可以輕松地使用此實用程序 function:
char user_name[20]; // artificially small
if (!prompt( "What is your name (maximum 19 characters)? ", user_name, sizeof(user_name) ))
{
complain_and_quit();
// ...because input is dead in a way you likely cannot fix.
// Feel free to check ferror(stdin) and feof(stdin) for more info.
}
這個小prompt
function 只是您可以編寫的各種幫助實用程序函數的示例。 你可以做一些事情,比如當用戶不服從你的時候有一個額外的提示:
你叫什么名字? 約翰·雅各布·金勒海默·施密特
唉,我被限制在 19 個字符之內。 請再試一次:
你叫什么名字? 約翰施密特
你好約翰施密特。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.