这不是答案——Barmar's 是——但这个和 OP 的 other question 都表明他们可以重新审视如何修改字符数组。
写这篇文章是希望对其他学习 C 的人也有用。
元素或元素序列可以有效地从数组中删除,只需对其内容进行简单循环即可。
关键是要保留两个索引:一个用于要检查的下一个(或多个)元素,另一个用于存储的最后一个元素(或要存储到的下一个位置)。
例如,要删除数组中的数字,可以使用以下伪代码函数:
Function removedigits(array, length):
Let i = 0 # Index of next element to examine, "input"
Let o = 0 # Position of next element to store, "output"
While (i < length):
If (array[i] is not a digit):
Let array[o] = array[i]
Let o = o + 1
End If
Let i = i + 1
End While
# For a string, we'll also want to terminate the array
# at o, because the rest of it contains garbage (old contents):
Let array[o] = '\0'
End Function
在处理序列时,保留多个索引可能很有用。例如,要删除重复的行,可以使用以下函数:
Function removeduplicatelines(array):
Let i = 0 # Next position in the array to be examined
Let o = 0 # Next position in the array to store to
Let ostarted = 0 # Index at which the last line stored started at
# Loop over each input line:
While (array[i] != '\0'):
# Find the length of this line. It can end with a newline
# or at the end of the string. The newline is not included.
Let ilen = 0
While (array[i + ilen] != '\n' && array[i + ilen] != '\0'):
Let ilen = ilen + 1
End While
# If the already stored line is of different length
# (the +1 is for the newline, as it is not included in ilen)
# or if it does not match the input line, store input line.
If (ostarted + ilen + 1 != o || memcmp(array + ostarted, array + i, ilen) != 0):
# The lengths or content differs. Store the line.
# Copy ilen characters, starting at array[i],
# to array[o] onwards.
# Because the array parts do not overlap,
# we can safely use memcpy() here.
memcpy(array + o, array + i, ilen)
# It is now the last stored line.
Let ostarted = o
Let o = o + ilen
# If there is a newline following the line,
# store that too.
If (array[i + ilen] == '\n'):
Let array[o] = '\n'
Let o = o + 1
End If
Else:
# It is the same line again. Do not store.
End If
# Proceed to the next input line.
Let i = i + ilen
# Because the newline was not included in ilen,
# skip it if there is one.
If (array[i] == '\n'):
Let i = i + 1
End If
End While
# After index o, the array may contain old contents;
# so terminate the string at index o.
Let array[o] = '\0'
End Function
请注意,如果以array + ostarted 开头的ilen 字符与以array + i 开头的字符匹配,则memcmp() 返回零。
如果我们知道o 永远不会超过i,则此方法有效;也就是说,我们永远不会覆盖我们尚未检查的数组内容。但请注意,o 允许等于 i,因为这只是意味着我们会覆盖我们刚刚检查的相同字符,而不会对数组进行实际更改。
如果我们想修改函数以跳过空行,我们在现有循环之前添加一个新的 while 循环,以删除任何前导换行符:
While (array[i] == '\n'):
Let i = i + 1
End While
并且,为了删除任何空行,我们将 while 循环中的最后一部分修改为
# Because the newline was not included in ilen,
# skip it (and any additional newlines) if there is one.
While (array[i] == '\n'):
Let i = i + 1
End While
最后,请注意上面的removeduplicatelines() 非常注意不要在最后一行之后添加换行符,如果数组中没有以开头的换行符。