我创建了一个函数,可以在数组中找到任何数字并删除它们。这是我的代码:
int noNums (char *a) {
int i;
int deleteInd;
for (i = 0; (i < MAX_NAME_SZ) && (a[i] != '\0'); i++) {
if ((a[i] >= '0') && (a[i] <= '9')) {
deleteInd = i;
memmove (&a[deleteInd], &a[deleteInd + 1], strlen (a) - deleteInd);
}
}
}
如果一个数字本身就在char数组中,那么它就被删除了,没问题。但是,如果数组中有连续的数字,那么只会删除其他所有数字吗?
如果我的char数组有
w12345678
然后将数组更改为
w2468
而不是
瓦特
有什么想法吗?
答案 0 :(得分:5)
执行memmove()
后,下一个元素现在位于刚刚删除的元素的索引中。但是你的循环会i++
,所以你不会再次检查那个索引。因此,只要一行中有两个数字,就跳过第二个数字。
解决此问题的一种方法是从数组的末尾循环到开头,而不是从开头到结尾。
另一种方法是在执行i--
之后执行memmove()
,以抵消循环将执行的i++
。
if (isdigit(a[i]) {
deleteInd = i;
memmove (&a[deleteInd], &a[deleteInd + 1], strlen (a) - deleteInd);
i--;
}
顺便说一句,您应该使用isdigit()
来测试一个字符是否为数字。
答案 1 :(得分:1)
您是否注意到您正在删除第一个数字然后跳过一个?
迭代数组时,从位置0开始递增。删除数字时,可以更改字符串索引。
i = 0 (char = w) Index: 012345689 string: w12345678 i = 1 (char = 1) Index: 012345689 string: w2345678 i = 2 (char = 3) Index: 012345689 string: w2345678
基本上,只要删除角色,就会将字符串移动。
删除字符时不要增加i。
请注意,代码中不需要deleteInd,您可以直接使用i。
答案 2 :(得分:0)
这不是答案 - 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
请注意,如果从memcmp()
开始的ilen
字符与从array + ostarted
开始的字符匹配,array + i
将返回零。
如果我们知道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()
在最后一行之后没有追加换行时要非常小心,如果阵列中没有一个换行符。