在C语言中生成随机字符

8

我刚开始学习C语言编程,现在的任务是创建一个二维数组,用random()函数随机存储A到Z的字母。我知道如何生成随机数字。

nextvalue = random ( ) % 10001;

我不确定如何创建随机字符。我知道可以使用ASCII表中65-90的范围来创建随机字符。能否有人帮我想出解决方案?非常感激。

2个回答

35
你需要假设系统的字符编码。我们假设它是 ASCIIUTF-8,并且限制在拉丁字母表的 26 个大写字母 ABC...XYZ 内。
然后你可以编写以下代码:
 char randomletter = 'A' + (random() % 26);

这在EBCDIC上不起作用。你也可以尝试

 char randomletter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[random () % 26];

这段内容可以使用任何编码(包括 EBCDIC, ASCII, UTF-8, ISO-Latin-1),其中每个 A...Z 字母都由单个 char 编码。

但是 this 是一个有趣的答案,解释了为什么 random() % 26 是错误的。在我这个幼稚的非专业观点中,它已经足够好了。

random() % 26 替换为我们定义的 myrandomlt26(),其中

static inline unsigned myrandomlt26() {
   long l;
   do { l = random(); } while (l>=(RAND_MAX/26)*26);
   return (unsigned)(l % 26);
}

应该稍微改进一下(很多时候上面的do...while循环只需要运行一次)。

然而,如果了解更多关于Unicode的信息,你会发现在某些人类语言中,字母(或大写字母)的概念并不像你想象的那么简单。

我不是这方面的专家,但是流言说法称奇怪的法语œ不是一个字母(而只是一个连字号),因为在一次ISO会议上讨论时,代表法国的人生病了。在法国学校,我记得我学过(可能是在1966-1972年间)它不是一个字母(但是手写连字号 - 在法语中有一个特殊的名称"E dans l'O" - 是一个拼写错误),但是有些人相信相反的观点。通常,像éà这样带重音符号的字母在法语中被认为是字母(但它们的UTF-8编码需要几个连续的char...)。同样,我相信并学过西里尔字母soft-sign ь不是一个字母,即使看起来像一个字母。定义arabichebrewkoreancherokeethai中的字母也应该很有趣,也是无休止的辩论话题...


第二种选择比第一种更棒,因为它是可移植的,并且在一个始终有趣的字符串字面值上使用数组索引。 - unwind
1
是的,random() % 26 不会给出均匀分布的结果。然而,假设 RAND_MAX 是 2147483647,则数字 0-23 有一个额外的机会被选中,但偏差非常小。更大的问题是如果序列中存在一些隐藏的循环,通过对2或13取模就会暴露出来。在我的计算机上,文档中说没有这种情况。 - JeremyP
@JeremyP:出于好奇,你的系统是什么,你所说的文档是哪些? - Basile Starynkevitch
OS X。random(3) 的 man 手册说:“rand(3) 产生的序列远不够随机——事实上,由 rand 生成的低十几位会遵循一个循环模式。所有由 random() 生成的位都是可用的。例如,random()&01 将生成一个随机的二进制值。” - JeremyP
warning: implicit declaration of function 'random' is invalid in C99 [-Wimplicit-function-declaration] - User

1
我认为你已经解决了这个问题。你只需要更努力地思考并进行更多的尝试。在C语言中,你可以很容易地以十进制形式显示任何ASCII字符。这里是 ASCII表供参考。例如:
char c = 65;
char c = 'A'; // Both are the same thing.

所以它可能与生成介于65和90之间的随机数相同。希望这有所帮助 ;) 我也是一个在C++方面有一些背景的新手。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接