繁体   English   中英

基于另一个变量设置一组变量的有效方法?

[英]Efficient way to set a group of variables based on another variable?

我想设置一组2-4个变量,它们的值取决于第5个变量。 我可以通过一长串的if else来做到这一点,我想知道是否有一个我不知道可以学到的技巧,可以更优雅地做到这一点? 我对``C.

例如:

/*some code... x is read from stdin...*/

if (x == 1) {
  a = 10;
  b = 100;
}

else if (x == 2) {
  a = 10;
  b = 50;
  c = 100;
}

else if (x == 3) {
  a = 0;
  b = 25;
  c = 50;
  d = 100;
}
/* and so on...*/

我打算使用指针来设置abc ...,而不是通过main()函数来完成所有操作,但是为了简单起见,这里省略了它。

干杯,

w ^

好吧, switch语句通常比一堆if-else语句更优雅

switch (x) {
    case 1:    a = 10;
               b = 100;
               break;

    case 2:    a = 10;
               b = 50;
               c = 100;
               break;

    case 3:    a = 0;
               b = 25;
               c = 50;
               d = 100;
               break;

    default:   // have a default case or catch it as an error
}

如果您真的很想让这段代码简短易读,则可以通过使用函数来设置变量来进一步加紧代码。

switch (x) {
    case 1:    caseA(&a, &b);
               break;

    case 2:    caseB(&a, &b, &c);
               break;

    case 3:    caseC(&a, &b, &c, &d);
               break;

    default:   // have a default case or catch it as an error
}

void caseA(int *a, int *b) {
    *a = 10;
    *b = 100;
}

您可以使用switch(x) ,如果一些值具有相同的效果,则将允许您回收某些代码。 例如

switch(x){
    case 5:
    case 6:
        a=0;
        b=25; //this code will run for both cases
}

当然有限制。 您不能真正将其应用于所有情况。

同样,通过使用三元运算符,您可以处理一些临界情况。 想象一下,例如,每次x==2a=10 ,那么它就是5。 因此,您可以像这样处理单个变量: a = (x==2)?5:10;

以我的方式,将数据与程序功能区分开来的价值是:

int data[3][4] = {  
   {10, 100, 0, 0},
   {10, 50, 100, 0},
   {0, 25, 50, 100}
};

abcd成为此数组的特定行,您可以使用该行对其进行索引

data[-1 + x]
static const int a[4] = {10, 10, 0};
static const int b[4] = {100, 50, 25};
static const int c[4] = {0, 100, 50};
static const int d[4] = {0, 0, 100};

printf("%d %d %d %d\n", a[x - 1], b[x - 1], c[x - 1], d[x - 1]);

或使用数学,并要牢记以下特定值:

// if (x == 1){a = 10; b = 100;}
// else if (x == 2){a = 10; b = 50; c = 100;}
// else if (x == 3){a = 0; b = 25; c = 50; d = 100;}

void get_values(int x, int *a, int *b, int *c, int *d)
{
   *a = (1 - x / 3) * 10;
   *b = 100 >> (x - 1);
   *c = (x - 1) * (200 >> (x - 1));
   *d = (x / 3) * 10;
}

int main(void)
{
    int a, b, c, d;
    int x = 3;

    get_values(x, &a, &b, &c, &d);
    printf("%d %d %d %d\n", a, b, c, d);
    return (0);
}

通常将比上述所有解决方案都要快,因为编译器无法进行这些超具体的优化,但这取决于您的需求。 同样,最后一个虽然最快,但肯定会损害可读性,因此您应将计算值保留为注释。

如果x值实际上是连续的,则可以创建一个结构数组来保存a,b,c,d的值。 唯一的技巧是,您需要一个哨兵值来指示不应设置变量。 在下面的示例中,值-1是前哨值。

struct setting
{
    int a, b, c, d;
}
settings[] =
{
    {  0,   0,  0,    0 },     // x = 0 not used
    { 10, 100, -1,   -1 },     // -1 indicates that a variable should be skipped
    { 10,  50, 100,  -1 },
    {  0,  25,  50, 100 },
};
static int maxSetting = sizeof(settings) / sizeof(settings[0]);

void updateSettings(int x, int *a, int *b, int *c, int *d)
{
    if (x > 0 && x < maxSetting)
    {
        struct setting *sptr = &settings[x];
        if (sptr->a >= 0)
            *a = sptr->a;
        if (sptr->b >= 0)
            *b = sptr->b;
        if (sptr->c >= 0)
            *c = sptr->c;
        if (sptr->d >= 0)
            *d = sptr->d;
    }
}

如果您想黑客入侵,可以尝试以下技巧:

typedef enum
{
    CASE_1_ = 1,
    CASE_2_,
    CASE_3_

}states;

void caseA(int *a, int *b, int *c, int *d) {
    *a = 10;
    *b = 100;
}

typedef void (*fp)(int *, int *, int *, int *);

fp proccess[] = {[CASE_1_] = caseA, [CASE_3_] = caseB, [CASE_3_] = caseC};

您需要做的只是proccess[x](); ,并且您不需要任何switchif-else语句。

只是为了好玩,如果您现在想使事情复杂化,但是在多种情况下使您的生活更轻松,我有一个解决方案,乍一看很难实施,但是我喜欢它在可伸缩性和可扩展性方面的工作方式。可重用性。

以下代码以交互方式用于测试目的,丢弃您认为不需要的所有内容。

#include<stdio.h>                                                                     

// Lets get handlers for each value                              
int f_One(void);
int f_Two(void);
int f_Three(void);
int f_Four(void);

// Lets have them in an enum rather than mere numbers, may not be required for you
typedef enum {

    ONE = 1,
    TWO,
    THREE,
    FOUR,

    MAX_TASKS,
    TASK_INVALID = -1,

} eValue_t ;

// This is a structure that binds an input and a handler together
typedef struct stTask {

    eValue_t TaskID;
    int (*handler) (void);

} stTask_t;

// Lets have an object
stTask_t Task;

// This is a like look-up table for referencing inputs and their handlers
const stTask_t TaskList[MAX_TASKS-1] =
{
    { ONE,    f_One   },
    { TWO,    f_Two   },
    { THREE,  f_Three },
    { FOUR,   f_Four  },
}; 

// This is your data
int a, b, c, d;

// Handler for 1
int f_One(void)
{
    printf("\nOne: ");
    a = 10;
    b = 100;
    printf("a is %d, b is %d", a, b);

    return 1;
}

// Handler for 2
int f_Two(void)
{
    printf("\nTwo: ");
    a = 10;
    b = 50;
    c = 100;
    printf("a is %d, b is %d, c is %d", a, b, c);

    return 2;
}

// Handler for 3
int f_Three(void)
{
    printf("\nThree: ");
    a = 0;
    b = 25;
    c = 50;
    d = 100;
    printf("a is %d, b is %d, c is %d, d is %d", a, b, c, d);

    return 3;
}

// Handler for 4
int f_Four(void)
{
    printf("\nFour: I didn't set any :D");
    return 4;
}

int main (void)
{
    int Val = -1;
    int ret = 0;

    while(1)
    {
        // Get input
        printf("\n\nPress 1, 2, 3, 4 or 0 for exit, Enter a value: ");
        scanf("%d", &Val);
        // Some validation, can be improved, or discarded
        if(Val > 4)
        {      
            printf("\nInvalid input");
            continue;
        }
        else if(Val == 0)
        {
            printf("\nExiting...");
            break;
        }
        // Assign the task
        Task.TaskID = Val-1;
        // Load the handler
        Task.handler = TaskList[Task.TaskID].handler;
        // Execute the handler
        ret = Task.handler();
        // Do something with 'ret'
    }
    printf("\n\n");
    return 0;
}

可以将枚举与union使用。 结构的大小始终是最大的内容结构之一。

enum type
{
    BAR = 0,
    BAZ,
    OTHER,
};

struct bar
{
    int x;
    char y;
};

struct baz
{
    void * x;
    float y;
};

struct other
{
    char x[2];
};

typedef struct _foo
{
    enum type type;
    union
    {
        struct bar bar;
        struct baz baz;
        struct other other;
    };
} foo;

...

struct bar a = { 1, 'c', };

foo x;
x.type = BAR;
x.bar = a;


struct baz b = { NULL, 1.0f, };

foo y;
y.type = BAZ;
y.baz = b;

if (x.type == BAR)
    printf("%d\n", x.bar.x);

if (y.type == BAZ)
    printf("%p\n", y.baz.x);

仅出于纯粹的乐趣,您就可以使用可变参数函数。 这是一个可能的方法(通过使用示例,您可以轻松地将其放入if阶梯中):

#include <stdarg.h>
#include <stdio.h>

void set_bunch(int n_vars, ...) {
    va_list args;
    va_start(args, n_vars);
    for (int i = 0; i < n_vars; ++i) {
        int* varp = va_arg(args, int*);
        int varv = va_arg(args, int);
        *varp = varv;

    }
    va_end(args);
}

int main() {
    int a, b, c, d;

    set_bunch(2, &a, 20, &b, 30);
    printf("%d %d\n", a, b); // prints 20 30

    set_bunch(3, &a, 30, &b, 40, &c, 50);
    printf("%d %d %d\n", a, b, c); // prints 30 40 50
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM