我有一个值数组
x = {0,0,1,2,3,0,0,7,8}
,我想使用 C 删除零条目。
尝试:
我试图循环遍历数组中的每个值并检查该条目是否不等于零。如果这个条件成立,那么我将尝试使用原始数组值填充新数组。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int x[] = { 0, 0, 1, 2, 3, 0, 0, 7, 8 };
int i;
int x_upd[100];
for (i = 0; i < 9; i++) {
if (x[i] != 0) {
x_upd[i] = x[i]; // if true, populate new array with value
}
}
for (i = 0; i < 9; i++) {
printf(" Peak updated %d\t", x_upd[i]); //
}
return 0;
}
输出没有给我所需的值
{1,2,3,7,8}
。相反,我在零曾经所在的位置得到了垃圾值。
对我在这里做错了什么有什么建议吗?我需要 else 语句吗?
C++中已经有这样的函数了。它被命名为
remove_copy
。在 C 中,这样的函数可以如下所示,如下面的演示程序所示。
#include <stdio.h>
int * remove_copy(const int *in, size_t n, int *out, int value)
{
for (size_t i = 0; i != n; i++)
{
if (in[i] != value) *out++ = in[i];
}
return out;
}
int main( void )
{
int a[] = { 0, 0, 1, 2, 3, 0, 0, 7, 8 };
int b[sizeof(a) / sizeof(*a)];
const size_t N = sizeof(a) / sizeof(*a);
int *last = remove_copy(a, N, b, 0);
for (int *first = b; first != last; ++first)
{
printf("%d ", *first);
}
putchar('\n');
return 0;
}
程序输出为
1 2 3 7 8
或者函数可以返回复制值的数量
size_t remove_copy(const int *in, size_t n, int *out, int value)
{
size_t m = 0;
for (size_t i = 0; i != n; i++)
{
if (in[i] != value) out[m++] = in[i];
}
return m;
}
对于您的代码,您需要使用一个附加变量来将索引保留在目标数组中。例如
int m = 0;
for ( i = 0; i < sizeof( x ) / sizeof( *x ); i++ )
{
if ( x[i] != 0 )
{
x_upd[m++] = x[i]; // if true, populate new array with value
}
}
for ( i = 0; i < m; i++ )
{
printf(" Peak updated %d\t", x_upd[i] ); //
}
事实上,第一个循环对应于上面所示的第二个函数实现。
您按顺序浏览 0-9 一次值,然后跳过
0
的值,因此得到 {garbage, garbage, 1, 2, 3, garbage, garbage, 7, 8}
。您必须为非 0
: 的值的数量保留一个单独的计数器
int position = 0;
for(i = 0; i < 9; i++)
{
if(x[i] != 0)
{
x_upd[position] = x[i]; // if true, populate new array with value
position++;
}
}
//loop until you get to counter
for(i = 0; i < position; i++)
{
printf(" Peak updated %d\t", x_upd[i]);
}
您应该使用单独的计数器变量,否则在分配给新数组时,您将“跳过”原始数组包含零的索引。
#include <stdio.h>
int main() {
int x[] = { 0, 0, 1, 2, 3, 0, 0, 7, 8 };
int i;
int j = 0;
int x_upd[100];
for (i = 0; i < 9; i++) {
if (x[i] != 0) {
x_upd[j++] = x[i]; // if true, populate new array with value
}
}
for (i = 0; i < j; i++) {
printf(" Peak updated %d\t", x_upd[i]); //
}
return 0;
}
这种情况下的技巧是使用不同的变量来索引到其他数组。
所以代替这个:
x_upd[i] = x[i];
您可以有另一个变量
j
,仅当您为 x_upd
赋值时才会递增
x_upd[j++] = x[i];
无需创建新数组,请参阅使用一个数组的工作代码。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int x[] = { 0, 0, 1, 2, 3, 0, 0, 7, 8 };
int i, n;
for (i = 0, n = 0; i<9; i++)
{
if (x[i] != 0)
{
x[n++] = x[i];
}
}
for (i = 0; i<n; i++)
{
printf("%d,", x[i]);
}
return 0;
}
输出:
1,2,3,7,8,
这个
for(i=0;i<9;i++)
{
if(x[i] != 0)
{
x_upd[i] = x[i]; // if true, populate new array with value
}
}
正在跳过
x_upd
数组中的位置,因为即使您不在新数组中插入值,i
仍然会递增。
你应该这样做:
int j = 0;
for(i=0;i<9;i++)
{
if(x[i] != 0)
{
x_upd[j++] = x[i]; // if true, populate new array with value
}
}
那么,这里
for(i=0;i<9;i++)
{
printf(" Peak updated %d\t",x_upd[i]); //
}
你应该数到
j
:
for(i=0;i<j;i++)
{
printf(" Peak updated %d\t",x_upd[i]); //
}
这个问题可以通过使用两个索引来解决:一个用于源数组(
x
),另一个用于目标数组(x_upd
),分别是i
和j
,在下面的代码中。
int i, j;
for(i=0,j=0; i<9; i++) {
if (!x[i]) // is x[i] zero?
continue; // then skip this element
// otherwise copy current element and update destination index
x_upd[j++] = x[i];
}
正如您所看到的,当
j
中的元素被复制到 x
时,索引 x_upd
才会被 updated(即:增加 1),而索引
i
在每个元素中都会被更新。 for
循环的迭代。
问题就出在这里:
for(i=0;i<9;i++)
{
if(x[i] != 0)
{
x_upd[i] = x[i]; // if true, populate new array with value
}
}
和
for(i=0;i<9;i++) {
printf(" Peak updated %d\t",x_upd[i]); //
}
您需要为 x 和 x_upd 维护单独的索引,因为它们的大小不同(x_upd 不会有“0”)。
试试这个:
int j;
for(i=0,j=0;i<9;i++) {
if(x[i] != 0)
{
x_upd[j] = x[i]; // if true, populate new array with value
j++; // index for values inserted
}
}
要打印,请使用从上述代码获得的正确计数:
int k;
for(k=0;k<=j;k++) {
printf(" Peak updated %d\t",x_upd[k]); //
}
您应该单独增加 x_upd 数组索引。比如:
int y = 0;
for(i=0;i<9;i++)
{
if(x[i] != 0)
{
x_upd[y] = x[i]; // if true, populate new array with value
y++;
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int x[] = {0,0,1,2,3,0,0,7,8};
int i;
int count = 0;
int x_upd[100];
for(i=0;i<9;i++)
{
if(x[i] != 0)
{
x_upd[count] = x[i]; // if true, populate new array with value
count++;
}
}
for(i=0;i<count;i++)
{
printf(" Peak updated %d\t",x_upd[i]); //
}
return 0;
}
输出
Peak updated 1 Peak updated 2 Peak updated 3 Peak updated 7 Peak updated 8
无需索引
int populate(int *src, int *dest, int size)
//usage: - src - source table
//src - source table
//dest - destination table
//size of the source table - source table
//Return: -1 if pointers are null, -2 if source table has zero elements, or number of non zero elements copied
{
int result = (src == NULL || dest == NULL) * -1;
// it an equivalen of:
// int result;
// if(src == NULL || dest == NULL)
// result = -1;
// else
// result = 0;
if(size == 0) result = -2;
if (!result)
{
while(size--)
if (*src)
{
*dest++ = *src;
result++;
}
src++;
}
return result;
}
int main()
{
int x[] = { 0,0,1,2,3,0,0,7,8 };
int x_upd[100];
int result = populate(x,x_upd, sizeof(x) / sizeof(x[0]))
for (int i = 0; i<result; i++)
{
printf(" Peak updated %d\t", x_upd[i]); //
}
return 0;
}
首先,我们必须知道数组中“第一个非零”值的索引:
idx = 0;
while((idx < arrySize) & (arry[idx] == 0)) idx++;
从这里我们可以:
--在涉及数组的后续循环中将 idx 视为“零”...或者
--构造一个新数组,仅保存旧数组的有效元素:
for(j=0; j<arrySize-idx; j++) newarry[j] = arry[j+idx];
.