如何将数组转换为cstring?

How to convert an array to a cstring?

我找到了 (here) 使用 Nim 计算文件 MD5 的程序源。 此程序不再编译 (nim 1.4),因为 arraycstring 之间的隐式转换已被禁用。

如何解决这个问题?


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"