穷举

求31a + 30b + 29c + 28d = 1461的非负整数解

#include <stdio.h>
#define M 1461

int main(void) {
  printf("%4s%4s%4s%4s\n", "a", "b", "c", "d");

  for (int a = 0; a < M; ++a) {
    for (int b = 0; b < M; ++b) {
      for (int c = 0; c < M; ++c) {
        for (int d = 0; d < M; ++d) {
          int sum = 31*a + 30*b + 29*c + 28*d;

          if (sum == M) {
            printf("%4d%4d%4d%4d\n", a, b, c, d);
          } else if (sum > M) {
            break;
          }
        }
      }
    }
  }

  return 0;
}

高效与高级

以前我们用低级语言,现在我们用高级语言。C语言时期,实现个队列要手写数组,在C++时期直接用STL就行了。

语言是高级了,但是时间复杂度的常数却越来越大了。抽象数据结构真的好吗?


宏列表

在Mozilla的代码中常常用到。

可以方便地重用标识符列表。

#define FLAG_LIST(_)                   \
    _(InWorklist)                      \
    _(EmittedAtUses)                   \
    _(LoopInvariant)                   \
    _(Commutative)                     \
    _(Movable)                         \
    _(Lowered)                         \
    _(Guard)

FLAG_LIST的参数是一个宏,它将被依次调用与列表中的每一个标识符。

类型

#define DEFINE_FLAG(flag) flag,
   enum Flag {
       None = 0,
       FLAG_LIST(DEFINE_FLAG)
       Total
   };
#undef DEFINE_FLAG

操作

#define FLAG_ACCESSOR(flag) \
bool is##flag() const {\
    return hasFlags(1 << flag);\
}\
void set##flag() {\
    JS_ASSERT(!hasFlags(1 << flag));\
    setFlags(1 << flag);\
}\
void setNot##flag() {\
    JS_ASSERT(hasFlags(1 << flag));\
    removeFlags(1 << flag);\
}
 
FLAG_LIST(FLAG_ACCESSOR)
#undef FLAG_ACCESSOR

IOCCC

国际C语言混乱代码大赛(International Obfuscated C Code Contest)。从1984年开始,每年举办一次。目的是写出最有创意、最难理解的代码。

http://www.ioccc.org/

浙江大学侯启明教授常常获奖。他有一个作品是支持三角函数和四则运算的计算器,使用了hash来实现三角函数解析的。

指定初始化

数组

/* Entries may not correspond to actual numbers. Some entries omitted. */
#define EINVAL 1
#define ENOMEM 2
#define EFAULT 3
/* ... */
#define E2BIG  7
#define EBUSY  8
/* ... */
#define ECHILD 12
/* ... *


char *err_strings[] = {
 	     [0] = "Success",
	[EINVAL] = "Invalid argument",
	[ENOMEM] = "Not enough memory",
	[EFAULT] = "Bad address",
	/* ... */
	[E2BIG ] = "Argument list too long",
	[EBUSY ] = "Device or resource busy",
	/* ... */
	[ECHILD] = "No child processes"
	/* ... */
};

结构体和联合体

struct point {
	int x;
	int y;
	int z;
}

struct point p = {.x = 3, .y = 4, .z = 5};

联合体类似,但是只初始化一个字段。

#if 0来注释代码

#if 0
...
#endif

printf %m

打印errno的出错内容,如果errno=0,输出Success

没有类型的变量

默认为int

g;main(i){
   printf("g = %d, i = %d \n",g,i);
}

用宏来代替循环

以下代码打印1~200。

#include<stdio.h>
#define STEP1 step();
#define STEP2 STEP1 STEP1
#define STEP4 STEP2 STEP2
#define STEP8 STEP4 STEP4
#define STEP16 STEP8 STEP8
#define STEP32 STEP16 STEP16
#define STEP64 STEP32 STEP32
#define STEP128 STEP64 STEP64
#define STEP256 STEP128 STEP128

int n = 0;

int step()
{
       if (++n <= 200)
       printf("%d\n", n);
}

int main()
{
      STEP256;
      return 1;
}

结构体置0

struct mystruct a = {0}; 

把printf中的长度控制符放到参数里。

*

#include <stdio.h>
int main()
 {
   int a = 3;
   float b = 6.412355;
   printf("%.*f\n",a,b);
   return 0;
}

scanf无视某个输入

*

char last[20];

scanf("%*s %s", last);

第一个参数会被忽略。如输入John Smith只会把Smith读到last里面。

scanf扫描字符集

%[...],输出到字符串,^代表扫描不在此字符集里的。

char *a;
/* .... */
scanf("%[^,]", a);

把逗号前的所有东西都读进来。

scanf("%[^,],", a);

把逗号前的所有东西都读进来,然后把缓冲区里的逗号吃掉。

拷贝字符串

while (*dest++ = *src++) ;
posted on 2016-12-07 13:40  yanhh  阅读(146)  评论(0编辑  收藏  举报