\n 在scanf 格式串中不表示等待换行符, 而是读取并放弃所有的空白字符。
在scanf() 转换数字的时候, 它遇到的任何非数字字符都会终止转换并被保留在输入流中。因此, 除非采用了其它的步骤, 那么未预料到的非数字输入会不断“阻塞” scanf(): scanf() 永远都不能越过错误的非数字字符而处理后边的合法数字字符。
通常先用类似fgets() 的函数读入整行, 然后再用sscanf() 或其它技术解释。
要避免溢出问题, 你可以使用限制长度的sprintf() 版本, 即snprintf()。这样使用:snprintf(buf, bufsize, “You typed \”%s\”", answer);
snprintf() 在几个stdio 库中已经提供好几年了, 包括GNU 和4.4bsd。在C99中已经被标准化了。作为一个额外的好处, C99 的snprintf() 提供了预测任意sprintf() 调用所需的缓冲区大小的方法。C99 的snprintf() 返回它可能放到缓冲区的字符数, 而它又可以用0 作为缓冲区大小进行调用。因此nch = snprintf(NULL, 0, fmtstring, /* 其它参数*/ );这样的调用就可以预测出格式串扩展后所需要的字符数。
没有什么标准的办法可以丢弃标准输入流的未读取字符, 即使有, 那也不够,因为未读取字符也可能来自其它的操作系统级的输入缓冲区。
读取二进制数据文件的时候你应该用“rb” 调用fopen(), 确保不会发生文本文件的解释。类似的, 写二进制文件时, 使用“wb”。注意文本/二进制区别只是发生在文件打开时: 一旦文件打开之后, 在其上调用何种I/O 函数无关紧要。
怎样产生标准分布或高斯分布的随机数?
这里有一个由Marsaglia 首创Knuth 推荐的方法:
#include <stdlib.h>
#include <math.h>
double gaussrand()
{
static double V1, V2, S;
static int phase = 0;
double X;
if(phase == 0) {
do {
double U1 = (double)rand() / RAND_MAX;
double U2 = (double)rand() / RAND_MAX;
V1 = 2 * U1 - 1;
V2 = 2 * U2 - 1;
S = V1 * V1 + V2 * V2;
} while(S >= 1 || S == 0);
X = V1 * sqrt(-2 * log(S) / S);
} else
X = V2 * sqrt(-2 * log(S) / S);
phase = 1 - phase;
return X;
}
大多数电脑都是用二进制来表示浮点和整数的。在十进制里, 0.1 是个简单、精确的小数, 但是用二进制表示起来却是个循环小数0.0001100110011 . . . 。
“参数默认晋级” 规则适用于在可变参数中的可变动部分: 参数类型为float 的总是晋级(扩展) 到double, char 和short int 晋级到int。所以va arg(arpg, float)是错误的用法。应该总是用va arg(arpg, double)。
程序在执行用之前就崩溃了, 用调试器单步跟进, 在main() 之前就死了。
也许你定义了一个或多个非常大的局部数组(超过上千字节)。许多系统只有固定大小的堆栈, 即使那些自动动态堆栈分配的系统也会因为一次性要分配大段堆栈而失败。
一般对大规模数组, 定义为静态的数组会更好。如果由于递归的原因, 每次都需要一组新的数组, 可以用malloc() 动态申请内存。