我有这个C函数,它基本上接受用户的输入并将其保存在static char[]
中。然后它检查它是否为空。如果它为空,则会输出错误,否则会附加文件扩展名。这是我关注的一段代码:
const char* text_entry(){
char c;
while((c=getchar())!='\n' && c!=EOF);
static char input[20];
fgets(input, sizeof(input),stdin);
input[strcspn(input,"\n")]=0;
if(strlen(input)>0){
strncat(input, ".txt",4);
return input;
}
printf("Error! no text entered!");
return NULL;
}
我担心的是我想从中删除IF语句,使其更加干燥。我怎么能这样做?
答案 0 :(得分:1)
" DRY"正在使用strcspn()
,strlen()
和strncat()
。你可以通过
size_t l = strcspn(input, "\n");
bool ok = false;
if (l == 0) {
fprintf(stderr, "error: too short\n");
} else if (l > sizeof input - sizeof(".txt")) {
fprintf(stderr, "error: too long\n");
} else {
strcpy(input + l, ".txt");
ok = true;
}
return ok ? input : NULL;
答案 1 :(得分:1)
这是最小循环版本。如果结果适合输入缓冲区, 检查*。
注意:我不说这是最好的方法。但它避免了对输入的多次扫描。 (性能上的提升大多是徒劳的......)
#include <stdio.h>
#include <string.h>
char* text_entry(){
int ch;
size_t pos;
static char input[20];
//this is dubious: it consumes characters upto and including the first '\n'
while((ch=getchar())!='\n' && ch!=EOF) {;}
for (pos=0; pos < sizeof input; pos++) {
ch=getchar();
if (ch =='\n' || ch==EOF) break;
input[pos] = ch;
}
// noinput
if(!pos) return NULL;
// input too large: cannot append suffix
if(pos + sizeof ".txt" > sizeof input) return NULL;
memcpy(input+pos, ".txt", sizeof ".txt" );
// fprintf(stderr, "[%zu]\n",strlen(input));
return input;
}
int main(void)
{
char *result;
while(1) {
result = text_entry();
if (!result) continue;
printf("%s\n", result);
}
return 0;
}
答案 2 :(得分:0)
我没有缩短您的代码,但我认为您可能会发现此解决方案更具弹性,使用libreadline -lreadline
在返回在堆栈上声明的缓冲区之前,这意味着它在返回时未分配,但是您返回其地址。这是一个错误。
我修复了它并让你有机会在参数和扩展中获取缓冲区和缓冲区大小,因此调用者可以为你管理内存以及最大字符串长度需求。
循环现在可以很好地处理最大输入大小。它可能不会更短,但它应该具有弹性。
/*
** Args:
** input_buffer: a buffer that will be whiped then filled with the user input
** buffer_size: the total size of the input buffer (maximum result length)
** extension: a dotted file type extension
**
** Returns: 0 on error or the input_buffer
*/
const char* text_entry(char *buffer, size_t buffer_size, char *extension) {
int maxsize = buffer_size - strlen(extension) - 1;
char *user_input;
int user_input_len;
do {
user_input = readline("Enter a file name: ");
user_input_len = strlen(user_input);
if (user_input_len > maxsize) {
printf("The name is too long! %d characters maximum. Try again.\n", maxsize);
free(user_input);
}
} while (!user_input_len || user_input_len > maxsize);
strcpy(buffer, user_input);
free(user_input);
strcat(buffer, extension);
printf("%s\n", buffer);
return buffer;
}