c-如何最大限度地减少if语句中测试表达式的数量



所以我有4个变量需要检查才能让我的程序工作,如果硬编码的话,一个if语句中可以有16个测试表达式。我怎样才能把它最小化?我唯一想到的方法是布尔代数,我错了。任何人有任何建议或什么我将不胜感激。该函数类似于printf函数。

string = form("%d %s %f %lf %c", 1, "ASA", 4.12345, 1.123421, 'A');

char * form(char * format, ...){
char * result = (char *)calloc(1, 1), val_int[12], * val_str, * pos_int, * pos_str, val_double[12], * pos_double, * pos_char, * pos_float, val_float[12];
va_list arguments; va_start(arguments, format);
do
{
pos_int = strstr(format, "%d"); pos_str = strstr(format, "%s"); pos_double = strstr(format, "%lf"); pos_float = strstr(format, "%f"); pos_char = strstr(format, "%c");
if(pos_int && (pos_int < pos_str && pos_int < pos_float && pos_int < pos_double && pos_int < pos_char))
{
sprintf(val_int, "%d", va_arg(arguments, int));
result = (char *)realloc(result, strlen(val_int) + strlen(result) + (pos_int - format) + 1);
strncat(result, format, pos_int - format);
strcat(result, val_int);
format = pos_int + 2;
}
else if(pos_str && ( pos_str < pos_int && pos_str < pos_float && pos_str < pos_double && pos_str < pos_char))
{
val_str = va_arg(arguments, char *);
result = (char *)realloc(result, strlen(val_str) + strlen(result) + (pos_str - format) + 1);
strncat(result, format, pos_str - format);
strcat(result, val_str);
format = pos_str + 2;
}
else if(pos_double && (pos_double < pos_float && pos_double < pos_char && pos_double < pos_str && pos_double < pos_int))
{
sprintf(val_double, "%lf", va_arg(arguments, double));
result = (char *)realloc(result, strlen(val_double) + strlen(result) + (pos_double - format) + 1);
strncat(result, format, pos_double - format);
strcat(result, val_double);                     
format = pos_double + 3;
}
else if(pos_float && (pos_float < pos_int && pos_float < pos_double && pos_float < pos_str && pos_float < pos_char))
{
sprintf(val_float, "%f", (float)va_arg(arguments, double));
result = (char *)realloc(result, strlen(val_float) + strlen(result) + (pos_float - format) + 1);
strncat(result, format, pos_float - format);
strcat(result, val_float);
format = pos_float + 2;
}
else if(pos_char && (pos_char < pos_int && pos_char < pos_str && pos_char < pos_float && pos_char < pos_double))
{
char val_char[2] = "";
val_char[0] = (char)va_arg(arguments, int);
result = (char *)realloc(result, strlen(val_float) + strlen(result) + (pos_float - format) + 1);
strncat(result, format, pos_float - format);
strcat(result, val_float);
format = pos_float + 2;
}
}while(pos_int || pos_str || pos_double || pos_float || pos_char);
va_end(arguments);
result = (char *)realloc(result, strlen(result) + strlen(format) + 1);
strcat(result, format);
return result; }

在这些if语句中,除了第一个测试表达式之外,只有一个测试表达式,它只查看测试的主变量是否初始化,我需要再做15个,以使每个if语句都处于可能的情况。

如果我们尝试使用您的通用结构,可以通过为每个数据类型提供一个元素的struct表/数组来简化这一点。

但是重复执行strstr有点浪费,并且拥有所有pos_*变量等也不必要地复杂。

通常、更简单、更快的方法是逐字符扫描格式字符串,找到下一个格式说明符(例如%d%f(,然后对类型执行switch

此外,每种类型都在做自己的realloc/strcat/strncat。最好添加一两个辅助函数来保持缓冲区/长度以及用于追加控制的struct

起初,我只是想稍微清理一下您的代码。但是,我很快意识到,唯一有意义的事情就是对它进行大量重构

这是有效的。它可能需要更多的错误/下溢/溢出检查。而且,更简单,[再次]更快

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
struct out {
int len;
char *buf;
};
static void
append_str(struct out *out,const char *str,int ilen)
{
int olen;
if (ilen < 0)
ilen = strlen(str);
out->buf = realloc(out->buf,out->len + ilen + 1);
memcpy(&out->buf[out->len],str,ilen);
out->len += ilen;
out->buf[out->len] = 0;
}
static void
append_char(struct out *out,int chr)
{
char str[2];
str[0] = chr;
str[1] = 0;
append_str(out,str,1);
}
char *
form(char *format, ...)
{
struct out out;
char tmp[100];
int chr;
va_list arguments;
int ilen;
char *cp;
va_start(arguments, format);
out.buf = NULL;
out.len = 0;
while (*format != 0) {
chr = *format++;
// ordinary char
if (chr != '%') {
append_char(&out,chr);
continue;
}
// grab format specifier
int lflg = 0;
while (*format != 0) {
chr = *format++;
if (chr != 'l')
break;
lflg = 1;
}
if (chr == '%') {
append_char(&out,chr);
continue;
}
ilen = -1;
switch (chr) {
case 'd':
ilen = sprintf(tmp, "%d", va_arg(arguments, int));
break;
case 'f':
if (lflg)
ilen = sprintf(tmp, "%lf", va_arg(arguments, double));
else
ilen = sprintf(tmp, "%f", va_arg(arguments, double));
break;
case 'c':
chr = va_arg(arguments,int);
append_char(&out,chr);
break;
case 's':
cp = va_arg(arguments, char *);
append_str(&out,cp,-1);
break;
default:
exit(1);
break;
}
if (ilen > 0)
append_str(&out,tmp,ilen);
}
va_end(arguments);
return out.buf;
}
int
main(void)
{
char *string;
string = form("%d %s %f %lf %c", 1, "ASA", 4.12345, 1.123421, 'A');
printf("%sn",string);
free(string);
return 0;
}

最新更新