我的任务是在C语言中编写具有动态内存分配的伪向量。我大部分时候都取得了成功,但是有一个奖励部分,它要求我们实现我们选择的排序功能。只是为了查看是否可以正确地获得索引,我选择了冒泡排序,但是在此方面我还是完全没有成功。我认为这是由于我如何将向量结构传递到函数中,但似乎我正在访问错误的数据。我还将使用向量类型添加对交换函数的尝试(不成功)。我希望有人告诉我我在做什么错。
这是家庭作业,如果尚未明确的话。我尝试添加正确的标签,但似乎这里不存在。
vec.c
#include "vec.h"
#include <stdio.h>
#include <stdlib.h>
#include <crtdbg.h>
#define GOOD 0;
#define BAD -1;
struct SVec VecInit(void) {
struct SVec vec;
vec.pData = 0;
vec.uiCount = 0;
return vec;
}
int VecAdd(struct SVec * const vec, int const iVal) {
int newsz = vec->uiCount + 1;
if (vec->pData == 0)
vec->pData = (int*)malloc(newsz * sizeof(int));
else
vec->pData = (int*)realloc(vec->pData, newsz * sizeof(int));
*(vec->pData + vec->uiCount) = iVal;
vec->uiCount++;
return 1;
}
int VecContains(struct SVec const * const vec, int const iVal) {
int index;
if (iVal < 0) return BAD;
for (index = 0; index < vec->uiCount; index++) {
if (*(vec->pData + index) == iVal) {
return GOOD; //success, change later
}
}
return BAD; //fail, change later
}
int VecDie(struct SVec * const vec) {
free(vec->pData);
vec->pData = NULL;
vec->uiCount = 0;
//free(vec); //not sure if this is necessary
}
int VecGet(struct SVec const * const vec, int const index) {
if (index > vec->uiCount || vec->uiCount <= 0 || index < 0)
return BAD; //failure
return vec->pData[index];
}
int VecIndexAt(struct SVec const * const vec, int const iVal) {
int index;
if (!VecContains(&vec, iVal))
return BAD; //value wasn't found
for (index = 0; index < vec->uiCount; index++) {
if (*(vec->pData + index) == iVal)
return index;
}
return BAD; //value wasn't found, should not be able to get here but let's be explicit
}
int VecRemove2(struct SVec * const vec, int const iVal) {
int newsize = vec->uiCount - 1;
int start;
for (size_t i = 0; i < vec->uiCount; i++) {
if (*(vec->pData + i) == iVal) {
*(vec->pData + i) = NULL;
start = i;
for (start; start < vec->uiCount; start++) {
if (start + 1 >= vec->uiCount) break; //bound check the end of vector
*(vec->pData + start) = *(vec->pData + start + 1);
}
vec->pData = (int*)realloc(vec->pData, newsize * sizeof(int));
vec->uiCount--;
return GOOD;
}
}
return BAD;
}
int VecRemove(struct SVec * const vec, int const iVal) {
int newsz = vec->uiCount - 1;
int indexToRemove;
int index;
if (vec->uiCount == 0) { return BAD; }
if (!VecContains(&vec, iVal)) { return BAD; }
else {
indexToRemove = VecIndexAt(&vec, iVal);
*(vec->pData + indexToRemove + 1) = NULL;
for (index = 0; index < sizeof(vec[0]) / sizeof(vec); index++) {
if (index == 0) continue;
vec->pData[index] = vec->pData[index + 1];
}
//vec->pData = (int*)realloc(vec->pData, newsz * sizeof(int));
vec->uiCount--;
return GOOD;
}
}
int VecSet(struct SVec * const vec, int const index, int const iVal) {
if (!VecContains(&vec, iVal) || index > vec->uiCount || index < 0) return BAD;
vec->pData[index] = iVal;
}
int VecShow(struct SVec const * const vec) {
int count = vec->uiCount;
int index;
if (vec->uiCount == 0) return -1;
for (index = 0; index <= count; index++) {
if (index == count - 1) {
printf("%d", *(vec->pData + index));
break;
}
printf("%d, ", *(vec->pData + index));
}
printf("\n");
}
//does not work
void VecShuffle(struct SVec * const vec, int const size) {
int i, j, tmp;
for (i = size - 1; i > 0; i--) {
j = rand() % (i + 1);
tmp = VecGet(&vec, j);
VecSet(&vec, j, VecGet(&vec, i));
VecSet(&vec, i, tmp);
}
}
int VecSize(struct SVec const * const vec) {
return vec->uiCount;
}
//does not work
void VecSort(struct SVec * vec) {
int i;
int j;
for (i = 0; i < vec->uiCount - 1; i++) {
for (j = 0; j < vec->uiCount - i - 1; j++) {
if (VecGet(&vec, j) > VecGet(&vec, j + 1)) {
int temp = VecGet(&vec, i);
int iValIndex = VecIndexAt(&vec, i);
int jValIndex = VecIndexAt(&vec, j);
VecSet(&vec, iValIndex, i);
VecSet(&vec, jValIndex, temp);
}
}
}
}
//REMOVE LATER
int VecValueAt(struct SVec const * const vec, int const index) {
if (index > vec->uiCount || vec->uiCount <= 0 || index < 0)
return BAD; //failure
return *(vec->pData + index);
}
//does not work
void VecSwap(struct SVec * vec, int const iVal, int const jVal) {
int temp = VecGet(&vec, iVal);
int iValIndex = VecIndexAt(&vec, iVal);
int jValIndex = VecIndexAt(&vec, jVal);
VecSet(&vec, iValIndex, iVal);
VecSet(&vec, jValIndex, temp);
}
void main() {
struct SVec vec = VecInit();
for (size_t i = 0; i < 5 ; i++)
{
VecAdd(&vec, i);
}
VecShow(&vec);
//VecSort(&vec);
VecShow(&vec);
getchar();
}
vec.h
typedef unsigned int uint;
struct SVec
{
int *pData;
uint uiCount;
};
struct SVec VecInit(void);
int VecAdd(struct SVec const * vec, int const iVal);
int VecContains(struct SVec const const * vec, int const iVal);
int VecDie(struct SVec const * vec);
int VecGet(struct SVec const * const vec, int const index);
int VecIndexAt(struct SVec const * const vec, int const iVal);
int VecRemove(struct SVec const * vec, int const iVal);
int VecRemove2(struct SVec const * vec, int const iVal);
int VecSet(struct SVec * const vec, int const index, int const iVal);
int VecShow(struct SVec const * const vec);
void VecShuffle(struct SVec * const vec, int const size);
int VecSize(struct SVec const * const vec);
void VecSort(struct SVec * const vec);
int VecValueAt(struct SVec const * const vec, int const index);
当我可以使用该函数时,它对向量没有任何影响,这就是让我考虑结构传递问题的原因。现在,如果我使用VecSort(),程序将无法编译,而且我不记得自己所做的更改。
更新了代码,以反映所提到的一些更改以及完整性,原型和头文件。
答案 0 :(得分:3)
以下作品:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <assert.h>
typedef unsigned int uint;
#define GOOD 0
#define BAD ( assert(0), -1 )
struct SVec
{
int *pData;
uint uiCount;
};
void VecShow(struct SVec const * const vec);
int VecAdd(struct SVec * const vec, int const iVal);
void VecSwap(struct SVec * vec, int const iVal, int const jVal);
int VecSet(struct SVec * const vec, int const index, int const iVal);
int VecIndexAt(struct SVec const * const vec, int const iVal);
int VecGet(struct SVec const * const vec, int const index);
int VecContains(struct SVec const * const vec, int const iVal);
int VecAdd(struct SVec * const vec, int const iVal) {
int newsz = vec->uiCount + 1;
if (vec->pData == 0)
vec->pData = (int*)malloc(newsz * sizeof(int));
else
vec->pData = (int*)realloc(vec->pData, newsz * sizeof(int));
*(vec->pData + vec->uiCount) = iVal;
vec->uiCount++;
return 1;
}
void VecShow(struct SVec const * const vec) {
int count = vec->uiCount;
int index;
if (vec->uiCount == 0) return;
for (index = 0; index <= count; index++) {
if (index == count - 1) {
printf("%d", *(vec->pData + index));
break;
}
printf("%d, ", *(vec->pData + index));
}
printf("\n");
}
void VecSwap(struct SVec * vec, int const iVal, int const jVal) {
int temp = VecGet(vec, iVal);
int iValIndex = VecIndexAt(vec, iVal);
int jValIndex = VecIndexAt(vec, jVal);
VecSet(vec, iValIndex, iVal);
VecSet(vec, jValIndex, temp);
}
int VecSet(struct SVec * const vec, int const index, int const iVal) {
if (!VecContains(vec, iVal) || index > vec->uiCount || index < 0) return BAD;
vec->pData[index] = iVal;
}
int VecIndexAt(struct SVec const * const vec, int const iVal) {
int index;
if (!VecContains(vec, iVal))
return BAD; //value wasn't found
for (index = 0; index < vec->uiCount; index++) {
if (*(vec->pData + index) == iVal)
return index;
}
return BAD; //value wasn't found, should not be able to get here but let's be explicit
}
int VecContains(struct SVec const * const vec, int const iVal) {
int index;
if (iVal < 0) return BAD;
for (index = 0; index < vec->uiCount; index++) {
if (*(vec->pData + index) == iVal) {
return GOOD;
}
}
return BAD;
}
int VecGet(struct SVec const * const vec, int const index) {
if (index > vec->uiCount || vec->uiCount <= 0 || index < 0)
return BAD; //failure
return vec->pData[index];
}
void VecSort(struct SVec * vec) {
int i;
int j;
for (i = 0; i < vec->uiCount - 1; i++) {
for (j = 0; j < vec->uiCount - i - 1; j++) {
if (VecGet(vec, j) > VecGet(vec, j + 1)) {
int tmp = vec->pData[j];
vec->pData[j] = vec->pData[j + 1];
vec->pData[j + 1] = tmp;
}
}
}
}
int main()
{
struct SVec vec = {0};
for (size_t i = 5; i > 0; i--) {
VecAdd(&vec, i);
}
VecShow(&vec);
VecSort(&vec);
VecShow(&vec);
// leak memory
return 0;
}
输出:
5, 4, 3, 2, 1
1, 2, 3, 4, 5
&
地址应用于指针时会误用它。 void VecSwap(struct SVec * vec, int const iVal, int const jVal) {
int temp = VecGet(&vec, iVal);
中的示例-&vec
是struct SVec * vec
指针的地址(不是数据!),因此您将传递给VecGet
函数struct SVec **
指针,即指向数据指针的指针。这会使代码在多个地方无效。编译器至少不应对此发出警告。 j
和j + 1
处的元素之后,您希望交换该索引处的元素。不是存储j
值的元素(可以是任何索引,也可能没有索引),而是完全位于索引j
和j + 1
的元素。return BAD
在#define BAD -1
中没有意义。我如何将减一存储在阵列中? -1
是一个重要数字吗?通常,程序员会选择最大值(INT_MAX)或最小值(INT_MIN)来返回错误,或者他们返回0
并设置一个全局标志(看着您strtol
...)部分:
if (vec->pData == 0)
vec->pData = (int*)malloc(newsz * sizeof(int));
else
vec->pData = (int*)realloc(vec->pData, newsz * sizeof(int));
可以简化为:
vec->pData = realloc(vec->pData, newsz * sizeof(int));
realloc(NULL, ...)
等同于调用malloc(...)
。并且0
可以隐式转换为NULL
,因为NULL
的定义为(void*)0
(我们不再赘述...)
*(arr + index)
语法,但是我认为这里没有任何正当性。您正在索引一个数组,只是arr[index]
,它是完全等效的(请不要index[arr]
)const struct SVec *
对我来说比struct SVec const *
更好,更常见。void VecShow(...)
函数包含return -1
,这至少是未定义的行为,我很惊讶地发现它实际上是在我使用的旧gcc版本上编译的。最好包括分配错误检查。通常,在使用realloc
时,正确的方法是使用临时指针。
void * const tmp = realloc(vec->pData, newsz * sizeof(*vec->pData));
if (tmp == NULL) {
// the old pointer vec->pData is still valid!
return BAD;
}
// success
vec->pData = tmp;
除了那些错误外,这看起来像是具有良好封装和组织性的非常好的代码。结构很好,需要时有const
个指针,良好的缩进,很多检查,可读性强。抱歉,我的英语还不够完善。