[英]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.