(为了清晰起见,我编辑了这篇文章,并根据EOL的回答稍微修改了一下实际问题)
我试图用C语言将下面的函数转换成Python,但是失败得很惨(参见下面的C代码)。据我所知,它从from
所指的内存位置开始使用四个1字节字符,将它们视为无符号长整型,以便为每个字符提供4个字节的空间,并进行一些位移位以将它们排列为一个32位的大整数。然后将其用于检查文件有效性的算法中。(来自Treaty of Babel)
static int32 read_alan_int(unsigned char *from)
{
return ((unsigned long int) from[3])| ((unsigned long int)from[2] << 8) |
((unsigned long int) from[1]<<16)| ((unsigned long int)from[0] << 24);
}
/*
The claim algorithm for Alan files is:
* For Alan 3, check for the magic word
* load the file length in blocks
* check that the file length is correct
* For alan 2, each word between byte address 24 and 81 is a
word address within the file, so check that they're all within
the file
* Locate the checksum and verify that it is correct
*/
static int32 claim_story_file(void *story_file, int32 extent)
{
unsigned char *sf = (unsigned char *) story_file;
int32 bf, i, crc=0;
if (extent < 160) return INVALID_STORY_FILE_RV;
if (memcmp(sf,"ALAN",4))
{ /* Identify Alan 2.x */
bf=read_alan_int(sf+4);
if (bf > extent/4) return INVALID_STORY_FILE_RV;
for (i=24;i<81;i+=4)
if (read_alan_int(sf+i) > extent/4) return INVALID_STORY_FILE_RV;
for (i=160;i<(bf*4);i++)
crc+=sf[i];
if (crc!=read_alan_int(sf+152)) return INVALID_STORY_FILE_RV;
return VALID_STORY_FILE_RV;
}
else
{ /* Identify Alan 3 */
bf=read_alan_int(sf+12);
if (bf > (extent/4)) return INVALID_STORY_FILE_RV;
for (i=184;i<(bf*4);i++)
crc+=sf[i];
if (crc!=read_alan_int(sf+176)) return INVALID_STORY_FILE_RV;
}
return INVALID_STORY_FILE_RV;
}
我正在尝试用Python重新实现它。为了实现read_alan_int
函数,我认为导入struct
并执行{bf
,它总是返回24,这意味着跳过for
循环。
…但那该死的东西还是24小时。很遗憾,我的原版程序不可能打印出来。
我做错什么了?
好吧,所以我很明显读错了。然而,对我来说失败的是检查前4个字符是“艾伦”。我所有的测试文件都没有通过这个测试。我修改了代码,删除了这个if/else语句,只利用了早期的返回,现在我所有的单元测试都通过了。所以,从实际的角度来说,我已经结束了。然而,我将继续提出这个问题来解决这个新问题:我怎样才能把前4个字符中的“ALAN”弄出来呢?
def is_a(file_buffer):
crc = 0
if len(file_buffer) < 160:
return False
#if file_buffer.startswith('ALAN'):
# Identify Alan 2.x
bf = read_long(file_buffer, 4)
if bf > len(file_buffer)/4:
return False
for i in range(24, 81, 4):
if read_long(file_buffer, i) > len(file_buffer)/4:
return False
for i in range(160, bf * 4):
crc += ord(file_buffer[i])
if crc == read_long(file_buffer, 152):
return True
# Identify Alan 3.x
crc = 0
bf = read_long(file_buffer, 12)
if bf > len(file_buffer)/4:
return False
for i in range(184, bf * 4):
crc += ord(file_buffer[i])
if crc == read_long(file_buffer, 176):
return True
return False
假设1:你在Windows上运行,你没有以二进制模式打开文件。在
啊,我想我明白了。请注意,描述中说
我读到的意思是艾伦3中有个神奇的词,但艾伦2中没有。然而,您的代码则相反,即使C代码只假设alan3文件存在ALAN。在
为什么?因为你不会说C,所以你猜得很自然!如果sf和ALAN的前四个字符相等,那么memcmp将返回True(相当于Python)。。但不是这样。如果内容相等,memcmp returns 0如果内容不同,则非零。在
这似乎就是它的工作方式:
^{pr2}$你的Python版本在我看来不错。在
PS:我错过了DSM找到的“
memcmp()
catch”,因此if memcmp(…)…
的Python代码实际上应该是`if file_buffer[0:4]!=“艾伦”。在从C代码和您在对原始问题的注释中给出的示例文件中可以看出,示例文件确实无效;以下是值:
所以,
crc != read_alan_int(sf+176)
,确实如此。在您确定样本文件是有效文件吗?或者原始帖子中缺少
crc
计算的一部分??在相关问题 更多 >
编程相关推荐