如何将数组转换为cstring?
How to convert an array to a cstring?
我找到了 (here) 使用 Nim 计算文件 MD5 的程序源。
此程序不再编译 (nim 1.4),因为 array 到 cstring 之间的隐式转换已被禁用。
如何解决这个问题?
import md5
import os
proc calculateMD5Incremental(filename: string) : string =
const blockSize: int = 8192
var
c: MD5Context
d: MD5Digest
f: File
bytesRead: int = 0
buffer: array[blockSize, char]
byteTotal: int = 0
#read chunk of file, calling update until all bytes have been read
try:
f = open(filename)
md5Init(c)
bytesRead = f.readBuffer(buffer.addr, blockSize)
while bytesRead > 0:
byteTotal += bytesRead
md5Update(c, buffer, bytesRead) # <--- HERE buffer should be cstring
bytesRead = f.readBuffer(buffer.addr, blockSize)
md5Final(c, d)
except IOError:
echo("File not found.")
finally:
if f != nil:
close(f)
result = $d
if paramCount() > 0:
let arguments = commandLineParams()
echo("MD5: ", calculateMD5Incremental(arguments[0]))
else:
echo("Must pass filename.")
quit(-1)
注意:我对一般问题更感兴趣,而不是 MD5,这是手头的例子。
UPDATE 在这种情况下,这是完全错误的。正如已接受的答案中所指出的,$array 将以“屏幕友好”的方式呈现它。
正确实施
md5(fromFile)的工作过程:
proc calculateMD5Incremental(filename: string) : string =
const blockSize: int = 8192
var
c: MD5Context
d: MD5Digest
f: File
s: cstring
bytesRead: int = 0
buffer: array[blockSize, char]
byteTotal: int = 0
#read chunk of file, calling update until all bytes have been read
try:
f = open(filename)
md5Init(c)
bytesRead = f.readBuffer(buffer.addr, blockSize)
while bytesRead > 0:
byteTotal += bytesRead
s = cast[cstring](create(char, blockSize + 1))
moveMem(s[0].addr, buffer[0].addr, blockSize)
md5Update(c, s, bytesRead)
bytesRead = f.readBuffer(buffer.addr, blockSize)
md5Final(c, d)
except IOError:
stderr.writeLine("ERROR: File not found: ", filename)
finally:
if f != nil:
close(f)
result = $d
转换错误
~我发现常规字符串被接受,所以$buffer
会将数组转换为有效字符串:~
const blockSize: int = 4
var
c: cstring
buffer: array[blockSize, char]
buffer = ['c','i','a','o']
c = $buffer
在您的回答中,您使用 $
将数组转换为字符串。这虽然不是 return "ciao"
但 "['c', 'i', 'a', 'o']"
。不确定您是否需要,但正确的转换方法如下:
const blockSize: int = 4
var
c: cstring
buffer: array[blockSize, char]
buffer = ['c','i','a','o']
c = cast[cstring](create(char, blockSize + 1))
moveMem(c[0].addr, buffer[0].addr, blockSize)
assert c == "ciao"
请注意,这是最佳的不安全解决方案。如果你想安全但速度慢一点,你可以使用这个代码:
const blockSize: int = 4
var
c: cstring
buffer: array[blockSize, char]
temp: string
buffer = ['c','i','a','o']
temp.setLen(blockSize)
for i in 0..<blockSize:
temp[i] = buffer[i]
c = temp
assert c == "ciao"
我找到了 (here) 使用 Nim 计算文件 MD5 的程序源。 此程序不再编译 (nim 1.4),因为 array 到 cstring 之间的隐式转换已被禁用。
如何解决这个问题?
import md5
import os
proc calculateMD5Incremental(filename: string) : string =
const blockSize: int = 8192
var
c: MD5Context
d: MD5Digest
f: File
bytesRead: int = 0
buffer: array[blockSize, char]
byteTotal: int = 0
#read chunk of file, calling update until all bytes have been read
try:
f = open(filename)
md5Init(c)
bytesRead = f.readBuffer(buffer.addr, blockSize)
while bytesRead > 0:
byteTotal += bytesRead
md5Update(c, buffer, bytesRead) # <--- HERE buffer should be cstring
bytesRead = f.readBuffer(buffer.addr, blockSize)
md5Final(c, d)
except IOError:
echo("File not found.")
finally:
if f != nil:
close(f)
result = $d
if paramCount() > 0:
let arguments = commandLineParams()
echo("MD5: ", calculateMD5Incremental(arguments[0]))
else:
echo("Must pass filename.")
quit(-1)
注意:我对一般问题更感兴趣,而不是 MD5,这是手头的例子。
UPDATE 在这种情况下,这是完全错误的。正如已接受的答案中所指出的,$array 将以“屏幕友好”的方式呈现它。
正确实施
md5(fromFile)的工作过程:
proc calculateMD5Incremental(filename: string) : string =
const blockSize: int = 8192
var
c: MD5Context
d: MD5Digest
f: File
s: cstring
bytesRead: int = 0
buffer: array[blockSize, char]
byteTotal: int = 0
#read chunk of file, calling update until all bytes have been read
try:
f = open(filename)
md5Init(c)
bytesRead = f.readBuffer(buffer.addr, blockSize)
while bytesRead > 0:
byteTotal += bytesRead
s = cast[cstring](create(char, blockSize + 1))
moveMem(s[0].addr, buffer[0].addr, blockSize)
md5Update(c, s, bytesRead)
bytesRead = f.readBuffer(buffer.addr, blockSize)
md5Final(c, d)
except IOError:
stderr.writeLine("ERROR: File not found: ", filename)
finally:
if f != nil:
close(f)
result = $d
转换错误
~我发现常规字符串被接受,所以$buffer
会将数组转换为有效字符串:~
const blockSize: int = 4
var
c: cstring
buffer: array[blockSize, char]
buffer = ['c','i','a','o']
c = $buffer
在您的回答中,您使用 $
将数组转换为字符串。这虽然不是 return "ciao"
但 "['c', 'i', 'a', 'o']"
。不确定您是否需要,但正确的转换方法如下:
const blockSize: int = 4
var
c: cstring
buffer: array[blockSize, char]
buffer = ['c','i','a','o']
c = cast[cstring](create(char, blockSize + 1))
moveMem(c[0].addr, buffer[0].addr, blockSize)
assert c == "ciao"
请注意,这是最佳的不安全解决方案。如果你想安全但速度慢一点,你可以使用这个代码:
const blockSize: int = 4
var
c: cstring
buffer: array[blockSize, char]
temp: string
buffer = ['c','i','a','o']
temp.setLen(blockSize)
for i in 0..<blockSize:
temp[i] = buffer[i]
c = temp
assert c == "ciao"