【问题标题】:sending parameters to a function according to input根据输入向函数发送参数
【发布时间】:2015-05-12 15:21:37
【问题描述】:

我有一个简单的 typedef (typedef int set [4]) 和它的创建。 我有一个函数可以获取 3 个这种 typedef 作为参数。

现在,我希望根据输入使用参数调用函数。 例如,如果输入是 A,D,R(假设这些都已经创建),那么函数将被称为 func(A,D,R)。

我尝试使用 swich 来匹配字符,然后发送适当的参数,但它变得太乱了,我也尝试了一些其他的东西,但我无法在输入和对象名称之间建立联系。

顺便说一句,我是用 C 写的。 任何帮助将不胜感激

【问题讨论】:

  • 你能分享你的代码吗?
  • 如果我理解正确,你想做这样的事情:sscanf("%c%c%c", &c0, &c1, &c2); if (c0 == 'A' && c1 == 'D' && c2 == 'R') func(A, D, R); ?

标签: c function input parameters


【解决方案1】:

如果我正确理解了这个问题,那么您有一些字符要转换为具有该名称的变量。即 'A' 变为 set A?

根据这个假设,这里有一种方法:

#include <assert.h>
set func(set x, set y, set z);

// Global definitions for all set variables.
struct sets {
    set A;
    set B;
    set C;
    ...
    set Z;    
} allSets;

set callFuncForParams(char c1, char c2, char c3)
{
    set *x, *y, *z;

    // Make sure the input is legal
    assert(c1 >= 'A' && c1 <= 'Z');
    assert(c2 >= 'A' && c2 <= 'Z');
    assert(c3 >= 'A' && c3 <= 'Z');

    x = (set *)&allSets + c1 - 'A';
    y = (set *)&allSets + c2 - 'A';
    z = (set *)&allSets + c3 - 'A';

    return func(*x, *y, *z);
}

另一种方法(如果您没有将所有字母都作为变量特别有用)是创建一个struct { char c; set s; } 数组,然后通过该数组找到您的变量。您可以使用宏和 # 运算符来生成该数组。

【讨论】:

    【解决方案2】:

    听起来您想按名称传递参数。假设是这种情况,我想到了两种方法。

    如果您的集合名称确实是单字符名称,例如 A、D、R 等,您可以构建一个由字符索引的 set 指针数组:

    set *sets[128]; // will result in a lot of unused sets, but
                    // indexing is fast and dead easy
    
    sets['A'] = &A;
    sets['D'] = &D;
    sets['R'] = &R;
    ...
    char s1, s2, s3;
    scanf( " %c %c %c", &s1, &s2, &s3 );     // Note a complete lack of error checking
    func( *sets[s1], *sets[s2], *sets[s3] ); // You *will* want to validate your inputs
    

    如果你不想浪费太多空间,你可以这样做

    set *sets[26]; // just uppercase letters
    
    int base = 'A';
    sets['A'-base] = &A;
    sets['D'-base] = &D;
    sets['R'-base] = &R;
    ...
    scanf( " %c %c %c", &s1, &s2, &s3 );                    // Again, absolutely no error checking
    func( *sets[s1-base], *sets[s2-base], *sets[s3-base] ); // You have been warned
    

    这假设您使用的编码是所有大写字母都是连续的(ASCII 或 UTF-8)。

    如果你是一个聪明的代码猴子并为你的集合使用有意义的名称,你可以使用一个由字符字符串索引的查找表,类似于以下内容:

    set foo, bar, bletch...;
    
    struct lut_entry {
      char *name;
      set *data;
    };
    
    struct lut_entry lut[] = { 
      {"foo", &foo}, 
      {"bar", &bar},
      {"bletch", &bletch},
      ...
      { NULL, NULL } // sentinel value
    };
    

    然后您可以在此表中搜索每个输入:

    set *lookup( const char *name, struct lut_entry *lut )
    {
      struct lut_entry *cur = lut;
      while ( cur->name && strcmp( cur->name, name ) )
        cur++;
      return cur->data;
    } 
    

    你会这样称呼它:

    scanf( "%s %s %s", name1, name2, name3 );
    
    set *s1 = lookup( name1, lut );
    set *s2 = lookup( name2, lut );
    set *s3 = lookup( name3, lut );
    
    if ( s1 && s2 && s3 )
      func( *s1, *s2, *s3 ); // note dereference operations!
    else
      // one or more of name1, name2, and name3 are invalid
      // handle as appropriate
    

    根据您管理的集合数量以及对这个应用程序的速度有多重要,您可能希望研究比无序线性数组搜索更复杂的东西,但如果它更少,则不值得付出努力十几个左右。

    为什么我不直接将名称传递给func 并让它完成所有查找工作?你绝对可以这样做,但这意味着func 必须通过全局变量与其调用者共享状态,我尽量避免这样做,这意味着func 总是 必须这样做无论您是否想要查找。最好让func 按原样接收集合并让调用函数进行查找,因为调用函数知道它是否由用户输入驱动。

    【讨论】:

    • 是的,它成功了 :) 感谢您如此迅速而详细地回答,你们是最棒的!
    猜你喜欢
    • 1970-01-01
    • 2021-08-28
    • 1970-01-01
    • 2014-03-04
    • 1970-01-01
    • 1970-01-01
    • 2019-04-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多