使用 calloc 后检查列表数组中是否有单个列表为空的最佳方法是什么?
What's the best approach to check if in a array of lists a single list is empty after I used calloc?
通常我在使用链表的时候会这样写:
struct node *startPtr = NULL;
所以我稍后检查它是否为NULL,如果是,则表示该列表为空。
但是在这段代码中:
struct card{
char face[3];
char suit[4];
};
typedef struct card Card;
struct stack{
Card cardd;
struct stack *nextPtr;
};
typedef struct stack Stack;
int main(){
/*
creation of *stacks also with calloc
*/
Stack *topstacks = calloc(4,sizeof(Stack)); // array of lists initialized by calloc
/*
scanf pos1, pos2 to switch
*/
move_card(stacks, topstacks, pos1, pos2);
}
int move_card(Stack *stacks, Stack *topstacks, unsigned int pos1, unsigned int pos2){
Stack *prevfromPtr;
Stack *fromPtr = &(stacks[pos1]);
Stack *toPtr = &(topstacks[pos2]);
while(fromPtr->nextPtr!=NULL){
prevfromPtr = fromPtr;
fromPtr = fromPtr->nextPtr;
}
Stack *newmovingcard = calloc(1,sizeof(Stack));
newmovingcard->cardd = fromPtr->cardd;
newmovingcard->nextPtr = NULL;
if (toPtr!=NULL){ // here I'd like to check if the list is empty and has not any item. This way it does not work because toPtr can't be NULL, it's a pointer
while(toPtr->nextPtr!=NULL){
toPtr = toPtr->nextPtr;
}
toPtr->nextPtr = newmovingcard;
free(fromPtr);
prevfromPtr->nextPtr = NULL;
return 0;
} else {
toPtr->cardd = newmovingcard->cardd;
toPtr->nextPtr = NULL;
free(fromPtr);
prevfromPtr->nextPtr = NULL;
return 0;
}
}
我有一个列表数组 (topstacks),用 calloc 初始化。而在move_card
里面的注释行中,我需要检查列表数组的单个列表是否为空。但我不知道该怎么做。
这是完整的代码,但有些 printf 的部分是意大利语,很抱歉:https://wtools.io/paste-code/b2gz
您可以尝试将 nextPtr
分配给同一个元素,或者您可以引入一个特殊的全局项,这将意味着一个空列表。
同时处理两个链表有点繁琐和烦人,但它是可行的:
int move_card(Stack **source, Stack **target, int source_pos, int target_pos) {
// Walk through the linked list, but in every case stop one short of the
// insertion point
// Walk through the source chain and identify which pointer needs
// to be manipulated.
for (int i = 0; i < source_pos; ++i) {
if (*source == NULL) {
return -1;
}
source = &((*source)->nextPtr);
}
// Walk through the target chain and identify the insertion point.
for (int i = 0; i < target_pos - 1; ++i) {
if (*target == NULL) {
return 1;
}
target = &((*target)->nextPtr);
}
// Capture the pointer we're actually moving
Stack* moving = *source;
// Skip this link in the chain by reassigning source
*source = moving->nextPtr;
// Capture the record that's being bumped
Stack* bumped = *target;
// Reassign the target
*target = moving;
// Re-link the bumped entry back in the chain
moving->nextPtr = bumped;
return 0;
}
我冒昧地重命名了一些东西,以便于理解。请注意它如何使用双指针,以便在必要时可以操纵原始指针。从链表中删除第一张卡片时,指向“head”条目的指针必须改变。
这是该代码的更完整的“演示”工具:
#include <stdio.h>
#include <stdlib.h>
struct stack {
char card[2];
struct stack *nextPtr;
};
typedef struct stack Stack;
Stack* make_stack(char face, char suit, Stack* nextPtr) {
Stack* stack = calloc(1, sizeof(Stack));
stack->card[0] = face;
stack->card[1] = suit;
stack->nextPtr = nextPtr;
return stack;
}
void print_stack(Stack* stack) {
while (stack) {
printf("%c%c ", stack->card[0], stack->card[1]);
stack = stack->nextPtr;
}
printf("\n");
}
int main(int argc, char** argv) {
Stack* source = make_stack('A', 'S', make_stack('2', 'S', make_stack('3', 'S', NULL)));
Stack* target = NULL;
print_stack(source);
move_card(&source, &target, 2, 0);
print_stack(source);
print_stack(target);
return 0;
}
其中使用了简化的 Card 模型。
如果您使用 malloc
和 memset
而不是 calloc
,您可以将您的值设置为您自己的“无效”值。
我的意思是这样的:
int* example;
example=malloc(100*sizeof(int)); // allocate memory to store 100 int
if(example){
memset(example,1,100*sizeof(int)); // initialize it with value 1
}
通常我在使用链表的时候会这样写:
struct node *startPtr = NULL;
所以我稍后检查它是否为NULL,如果是,则表示该列表为空。
但是在这段代码中:
struct card{
char face[3];
char suit[4];
};
typedef struct card Card;
struct stack{
Card cardd;
struct stack *nextPtr;
};
typedef struct stack Stack;
int main(){
/*
creation of *stacks also with calloc
*/
Stack *topstacks = calloc(4,sizeof(Stack)); // array of lists initialized by calloc
/*
scanf pos1, pos2 to switch
*/
move_card(stacks, topstacks, pos1, pos2);
}
int move_card(Stack *stacks, Stack *topstacks, unsigned int pos1, unsigned int pos2){
Stack *prevfromPtr;
Stack *fromPtr = &(stacks[pos1]);
Stack *toPtr = &(topstacks[pos2]);
while(fromPtr->nextPtr!=NULL){
prevfromPtr = fromPtr;
fromPtr = fromPtr->nextPtr;
}
Stack *newmovingcard = calloc(1,sizeof(Stack));
newmovingcard->cardd = fromPtr->cardd;
newmovingcard->nextPtr = NULL;
if (toPtr!=NULL){ // here I'd like to check if the list is empty and has not any item. This way it does not work because toPtr can't be NULL, it's a pointer
while(toPtr->nextPtr!=NULL){
toPtr = toPtr->nextPtr;
}
toPtr->nextPtr = newmovingcard;
free(fromPtr);
prevfromPtr->nextPtr = NULL;
return 0;
} else {
toPtr->cardd = newmovingcard->cardd;
toPtr->nextPtr = NULL;
free(fromPtr);
prevfromPtr->nextPtr = NULL;
return 0;
}
}
我有一个列表数组 (topstacks),用 calloc 初始化。而在move_card
里面的注释行中,我需要检查列表数组的单个列表是否为空。但我不知道该怎么做。
这是完整的代码,但有些 printf 的部分是意大利语,很抱歉:https://wtools.io/paste-code/b2gz
您可以尝试将 nextPtr
分配给同一个元素,或者您可以引入一个特殊的全局项,这将意味着一个空列表。
同时处理两个链表有点繁琐和烦人,但它是可行的:
int move_card(Stack **source, Stack **target, int source_pos, int target_pos) {
// Walk through the linked list, but in every case stop one short of the
// insertion point
// Walk through the source chain and identify which pointer needs
// to be manipulated.
for (int i = 0; i < source_pos; ++i) {
if (*source == NULL) {
return -1;
}
source = &((*source)->nextPtr);
}
// Walk through the target chain and identify the insertion point.
for (int i = 0; i < target_pos - 1; ++i) {
if (*target == NULL) {
return 1;
}
target = &((*target)->nextPtr);
}
// Capture the pointer we're actually moving
Stack* moving = *source;
// Skip this link in the chain by reassigning source
*source = moving->nextPtr;
// Capture the record that's being bumped
Stack* bumped = *target;
// Reassign the target
*target = moving;
// Re-link the bumped entry back in the chain
moving->nextPtr = bumped;
return 0;
}
我冒昧地重命名了一些东西,以便于理解。请注意它如何使用双指针,以便在必要时可以操纵原始指针。从链表中删除第一张卡片时,指向“head”条目的指针必须改变。
这是该代码的更完整的“演示”工具:
#include <stdio.h>
#include <stdlib.h>
struct stack {
char card[2];
struct stack *nextPtr;
};
typedef struct stack Stack;
Stack* make_stack(char face, char suit, Stack* nextPtr) {
Stack* stack = calloc(1, sizeof(Stack));
stack->card[0] = face;
stack->card[1] = suit;
stack->nextPtr = nextPtr;
return stack;
}
void print_stack(Stack* stack) {
while (stack) {
printf("%c%c ", stack->card[0], stack->card[1]);
stack = stack->nextPtr;
}
printf("\n");
}
int main(int argc, char** argv) {
Stack* source = make_stack('A', 'S', make_stack('2', 'S', make_stack('3', 'S', NULL)));
Stack* target = NULL;
print_stack(source);
move_card(&source, &target, 2, 0);
print_stack(source);
print_stack(target);
return 0;
}
其中使用了简化的 Card 模型。
如果您使用 malloc
和 memset
而不是 calloc
,您可以将您的值设置为您自己的“无效”值。
我的意思是这样的:
int* example;
example=malloc(100*sizeof(int)); // allocate memory to store 100 int
if(example){
memset(example,1,100*sizeof(int)); // initialize it with value 1
}