簡體   English   中英

如何僅在 C 中具有一定長度時才接受字符串輸入,否則請用戶再次輸入字符串

[英]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 的詳細信息。

  1. 一些針對健全輸入參數的測試。 零大小不允許保存為null 字符終止字符串的任何輸入。 緩沖區可能大於INT_MAX ,但fgets()不能直接處理。 可以修改代碼以處理 0 和巨大的緩沖區,但將其留到另一天。

  2. fgets()並不總是讀取'\n' 緩沖區可能會先滿,或者文件結尾之前的最后一行可能缺少'\n' 不常見的是,可能會讀取null 字符- 甚至是第一個字符,因此len > 0測試,導致strlen()不足以確定讀取的字符長度。 如果null 字符輸入需要詳細支持,則代碼需要進行重大更改以適應確定大小。

  3. feof(stdin)如果之前的fgets()讀取了一些東西,但是文件結束發生了,那么很高興回到這里。

  4. 如果之前的fgets()填滿了它的緩沖區,並且下一次讀取字符嘗試導致文件結束或'\n' ,則此測試為真並且正常,因此返回成功。

  5. 如果先前的fgetc()導致輸入錯誤,則此循環立即退出。 否則,我們需要使用 rest 來查找'\n'EOF (這可能是由於文件結束或輸入錯誤。)

  6. 如果返回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)
}

如果pNULL ,那么還有更多工作要做。 由於您希望簡單地忽略太長的行,這與丟棄輸入相同。 用一個簡單的循環來做到這一點:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM