C比较函数中的数组元素

时间:2013-02-19 22:21:56

标签: c arrays function int

这可能是一个非常基本的问题,但我对如何实现这样的事情感到困惑。

对于我正在使用C的类,我需要采用两个长度不同的数组,并在一个单独的函数中比较它们的元素。 (此函数仅将数组作为参数,而不是它们的大小)两个数组中的任何元素我需要放入另一个数组并返回该数组(注意:每个数组都像一个集合,因为没有元素在同一个数组中重复)。我已经研究了如何实现这一点,以下是我遇到的一些问题。

  1. 我如何知道数组末尾的位置?

    我想我看到我可以将{0}作为null元素的数组中的元素。如果这是真的,我不知道我将比较这个元素以检查是否为空。

  2. 我想我应该将指针传递给数组的第一个元素,因为我不认为C会让数组的值传递,但有点不确定。

    如果我将数组作为指针传递,我如何访问数组元素以获取数据?

  3. 将数组返回到main函数时,如何在不清除内存的情况下返回结果函数?

    我应该将结果数组设为全局数据,还是有更好的处理方式?

  4. 提前致谢。

4 个答案:

答案 0 :(得分:2)

你的问题有点模糊。看起来你想要实现set intersection,你有两个集合,由数组表示,输出是另一个实现为数组的数组。

<强> 1。我怎么知道数组的末尾在哪里?

在C中,没有办法说出来。如果您无法将长度作为函数传递,那么您将无法执行强大的解决方案。它需要与#2类似。

<强> 2。我想我看到我可以将{0}作为一个元素     null元素的数组。如果这是真的,我不知道我会做什么     比较此元素以检查是否为空。

你可以添加一个空字符,它只是值0.要检查,你需要比较0.我不知道你的每个数组元素是由什么组成的,但有一点需要注意的是这些值都不允许为零,因为它被保留为数组标记的结尾。

第3。我想我应该将指针传递给第一个元素     数组因为我不认为C会让数组的值为     通过,但有点不确定。

是。您将传递指向第一个元素,在C中是数组符号。

int A[10]; // pass A

<强> 4。如果我确实将数组作为指针传递,我该如何访问数组     获取数据的元素?

假设您传递了指针A,您可以通过简单索引作为A [i]来访问元素,以获取元素i。

<强> 5。将数组返回到main函数时,如何在不清除内存的情况下返回结果函数?

在您正在编写的函数中,您可以malloc一个数组并将指针传递给malloc创建的数组。当函数退出时,不会删除Malloce'd内存。

答案 1 :(得分:1)

  

我怎么知道数组的结尾在哪里?

如果你没有将数组的大小作为单独的参数传递(你应该是这样),那么你将使用来使用某种类型的sentinel值(C字符串的方式)在字符串中的最后一个字符后使用0)。

  

我想我应该将指针传递给数组的第一个元素,因为我不认为C会让数组的值传递,但有点不确定。

C的数组语义有点棘手。除非它是sizeof_Alignof或一元&运算符的操作数,或者是用于在声明中初始化数组的字符串文字,否则表达式为“N” -element数组T“将转换为”指向T的指针“的表达式,表达式的值将是数组中第一个元素的地址。所以,给定代码

int arr1[10];

foo(arr1); // equivalent to foo(&arr1[0]);

arr1调用中的表达式foo将从“{10}元素数组int”转换为“指向int”,并且收到的值by foo是数组第一个元素的地址:

void foo(int *a)
{
  // do stuff with a[i]
}

表达式a[i]被解释为*(a + i);我们在i之后找到a'元素的地址,并取消引用结果。

这是一种冗长的方式,说你会在函数的参数上使用[]运算符,就像它们是常规数组一样。

  

将数组返回到main函数时,如何在不清除内存的情况下返回结果函数?

不完全清楚你的意思。请注意,以下代码不会工作:

int *foo(int *a1, int *a2)
{
  int a3[SOME_SIZE];

  // copy elements from a1 and a2 to a3;

  return a3;
}

一旦foo退出,数组a3就不复存在了;该内存由系统回收,因此返回的指针值不再有效。您有三种选择:

首先,您可以将目标数组作为第三个参数传递:

int main(void)
{
  int arr1[N];
  int arr2[M];
  int arr3[K];
  ...
  foo(arr1, arr2, arr3);
  ...
}

void foo(int *a1, int *a2, int *result) { ... }

前提是result指向一个足够大的数组来容纳你找到的所有元素(它应该与两个源数组中较大的一个一样大)。如果你不想搞乱动态内存管理,这就是你要走的路。

其次,您可以在函数中动态分配目标数组:

int main(void)
{
  int a1[M];
  int a2[N];
  int *a3;
  ...
  a3 = foo(a1, a2);
  ...
  free(a3);
}

int *foo(int *a1, int *a2)
{
  int *result = malloc(sizeof *result * SOME_SIZE);
  ...
  if (element_in_both_arrays())
    result[n++] = element_from_both_arrays();
  ...
  return result;
}

一旦完成记忆,你必须记住释放内存。

最后,您可以将目标数组声明为全局变量(即,在文件范围内)。我不会举一个例子,因为你不想那样做。

无论何时将数组传递给函数或返回动态分配的缓冲区,您都需要将数组大小作为单独的参数传递。通常,不可能仅根据指针值确定数组中有多少个元素。您可以使用sentinel值,但它们只会告诉您数组的逻辑大小,而不是 physical 大小。例如:

char buffer[1024] = "foo";

buffer逻辑大小为3(字符串的长度),但其物理大小为1千字节。

答案 2 :(得分:0)

  1. 要知道数组的长度,您需要将长度作为参数传递,或者您需要在数组中使用一个特殊值来表示它是最后一项。

  2. 如果传递数组,则传递指向数组的指针。如果不清楚,也许你应该包括一些代码。

  3. 如果将数组传递给函数,则对调用方法可以看到对数组所做的任何更改。没有必要退货。

答案 3 :(得分:0)

For 1:函数的调用者应该知道每个数组的长度。允许将此信息传递给函数。您可以选择使用sentinel值来指示有效元素的结尾,但您必须确保该函数的所有用户都知道此约定并遵循它。

For 2:数组名称将降级为指针类型,其值为数组的第一个元素的地址(在大多数情况下)。没有什么特别需要做的事情。

For 3:您可以让调用者提供指向要复制输出的内存的指针。或者,可以通过函数动态分配数组,但调用者需要知道释放此内存。

/* Finds elements common to both a and b, and copies them to c. The c out
   parameter is assumed to be at least as large as the smaller of the a_sz
   and b_sz. Returns the number of elements copied into c. */
int find_in_common (const int *a, size_t a_sz, const int *b, size_t b_sz,
                    int *c)
{
    /* ... */
}