从此代码中删除IF语句

时间:2017-07-06 19:26:24

标签: c if-statement dry

我有这个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语句,使其更加干燥。我怎么能这样做?

3 个答案:

答案 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;
}