C의 배열에서 요소 제거
C의 어레이에 대해 간단한 질문이 있습니다.
배열에서 요소를 제거하고 그 과정에서 배열을 더 작게 만드는 가장 좋은 방법은 무엇입니까?
은 : n
크기를 조정한 다음 배열에서 요소를 제거한 다음 배열을 제거한 양만큼 더 작아집니다.
기본적으로 저는 배열을 카드 덱처럼 취급하고 있습니다. 카드 덱의 상단에서 카드를 꺼내면 더 이상 거기에 존재하지 않아야 합니다.
편집: 하루가 끝나기 전에 미칠 것 같습니다. 가치 교환을 시도하고 있지만 제대로 작동하지 않습니다. 많은 도움을 주셔서 감사합니다.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
enum faces { Ace = 0, Jack = 10, Queen, King };
char *facecheck(int d);
int draw(int deck, int i);
int main() {
int deck[52], i, n;
char suits[4][9] = {
"Hearts",
"Diamonds",
"Clubs",
"Spades"
};
n = 0;
for (i = 0; i < 52; i++) {
deck[i] = n;
n++;
};
for (i = 0; i < 52; i++) {
if (i % 13 == 0 || i % 13 == 10 || i % 13 == 11 || i % 13 == 12)
printf("%s ", facecheck(i % 13));
else
printf("%d ", i % 13 + 1);
printf("of %s \n", suits[i / 13]);
}
draw(deck, i);
return 0;
}
char *facecheck(int d) {
static char *face[] = {
"Ace",
"Jack",
"Queen",
"King"
};
if (d == Ace)
return face[0];
else {
if (d == Jack)
return face[1];
else {
if (d == Queen)
return face[2];
else {
if (d == King)
return face[3];
}
}
}
}
int draw(int deck, int i) {
int hand[5], j, temp[j];
for (i = 0; i < 52; i++) {
j = i
};
for (i = 0; i < 5; i++) {
deck[i] = hand[];
printf("A card has been drawn \n");
deck[i] = temp[j - 1];
temp[j] = deck[i];
};
return deck;
}
정말로 두가지 별개의 문제가 있습니다.첫 번째는 요소를 제거한 후에 "구멍"이 없도록 배열의 요소를 올바른 순서로 유지하는 것입니다.두 번째는 어레이 자체의 크기를 조정하는 것입니다.
C의 배열은 고정된 수의 연속 요소로 할당됩니다.배열에서 개별 요소가 사용하는 메모리를 실제로 제거할 방법은 없지만 요소를 제거하여 구멍을 메우도록 요소를 이동시킬 수 있습니다.예를 들어,
void remove_element(array_type *array, int index, int array_length)
{
int i;
for(i = index; i < array_length - 1; i++) array[i] = array[i + 1];
}
정적으로 할당된 배열의 크기를 조정할 수 없습니다.동적으로 할당된 배열은 realoc()로 크기를 조정할 수 있습니다.이렇게 하면 전체 배열이 메모리의 다른 위치로 이동할 수 있으므로 배열 또는 해당 요소에 대한 모든 포인터를 업데이트해야 합니다.예를 들어,
remove_element(array, index, array_length); /* First shift the elements, then reallocate */
array_type *tmp = realloc(array, (array_length - 1) * sizeof(array_type) );
if (tmp == NULL && array_length > 1) {
/* No memory available */
exit(EXIT_FAILURE);
}
array_length = array_length - 1;
array = tmp;
realoc은 요청된 크기가 0이거나 오류가 있는 경우 NULL 포인터를 반환합니다.그렇지 않으면 포인터를 재할당된 배열로 반환합니다.임시 포인터는 realoc을 호출할 때 원래 배열을 그대로 두는 대신 오류를 탐지하는 데 사용됩니다.realoc에서 배열을 재할당하지 못할 경우 원래 배열은 변경되지 않습니다.
배열 크기가 크거나 요소를 많이 제거하면 이 두 작업 모두 상당히 느려집니다.링크 리스트, 해시 등 효율적인 삽입 및 삭제가 필요한 경우 사용할 수 있는 다른 데이터 구조가 있습니다.
필요한 솔루션은 어레이의 순서를 유지할지 여부에 따라 달라집니다.
일반적으로 배열 포인터만 있는 것이 아니라 배열 포인터의 현재 논리적 크기를 유지하는 변수와 할당된 크기를 유지하는 변수도 있습니다.또한 저는 제가 생각하기에removeIndex
배열 범위 내에 있습니다.이를 고려하면 제거 작업은 간단합니다.
주문무관
array[removeIndex] = array[--logicalSize];
바로 그겁니다.제거할 요소 위에 마지막 배열 요소를 복사하기만 하면 됩니다.logicalSize
데이터를 저장할 수 있습니다.
한다면removeIndex == logicalSize-1
, 즉, 마지막 요소를 제거해야 하며, 이는 해당 마지막 요소의 자체 assign으로 저하되지만 문제가 되지 않습니다.
유지순서
memmove(array + removeIndex, array + removeIndex + 1, (--logicalSize - removeIndex)*sizeof(*array));
좀 더 복잡한데요, 왜냐면 이제 우리가 전화를 해야 하니까요.memmove()
요소의 이동을 수행하지만 여전히 원라이너입니다.다시 말하지만, 이것은 또한logicalSize
데이터를 저장할 수 있습니다.
무언가를 제거할 때마다 메모리를 다시 할당하고 싶지는 않을 것입니다.데크의 대략적인 크기를 알고 있는 경우 배열에 적합한 크기를 선택하고 목록의 현재 끝에 있는 포인터를 유지합니다.이것은 스택입니다.
데크의 크기를 모르고 크기가 계속 변할 수도 있고 정말 커질 수도 있다고 생각한다면 좀 더 복잡한 작업을 수행하고 링크드 리스트를 구현해야 할 것입니다.
C에서는 배열을 선언하는 두 가지 간단한 방법이 있습니다.
스택에서 정적 배열로
int myArray[16]; // Static array of 16 integers
힙에서 동적으로 할당된 배열로
// Dynamically allocated array of 16 integers int* myArray = calloc(16, sizeof(int));
표준 C는 이 두 종류의 배열 크기를 조정하는 것을 허용하지 않습니다.특정 크기의 새 배열을 만든 다음 이전 배열의 내용을 새 배열로 복사하거나, 다른 추상 데이터 유형(즉, linked list, stack, queue 등)에 대해 위의 제안 중 하나를 따를 수 있습니다.
흥미롭게도 배열은 인덱스를 통해 임의로 접근할 수 있습니다.임의로 요소를 제거하면 다른 요소의 인덱스에도 영향을 미칠 수 있습니다.
int remove_element(int*from, int total, int index) {
if((total - index - 1) > 0) {
memmove(from+i, from+i+1, sizeof(int)*(total-index-1));
}
return total-1; // return the new array size
}
:memcpy
메모리가 중복되어 이 경우에는 작동하지 않습니다.
하나의 임의 요소를 제거하는 효율적인 방법 중 하나는 마지막 요소와 스왑하는 것입니다.
int remove_element(int*from, int total, int index) {
if(index != (total-1))
from[index] = from[total-1];
return total; // **DO NOT DECREASE** the total here
}
하지만 제거 후 주문이 변경됩니다.
루프 작동에서 제거가 완료된 경우 순서 변경이 처리에 영향을 미칠 수 있습니다.메모리 이동은 배열 요소를 제거하면서 순서를 유지하는 값비싼 대안 중 하나입니다.루프에 있는 동안 순서를 유지하는 또 다른 방법은 제거를 연기하는 것입니다.같은 크기의 유효성 배열로 할 수 있습니다.
int remove_element(int*from, int total, int*is_valid, int index) {
is_valid[index] = 0;
return total-1; // return the number of elements
}
희소 배열을 만듭니다.마지막으로, 스파스 배열은 순서를 바꾸어서 콤팩트(그들 사이에 유효하지 않은 요소를 포함하는 두 개의 유효한 요소를 포함하지 않음)로 만들 수 있습니다.
int sparse_to_compact(int*arr, int total, int*is_valid) {
int i = 0;
int last = total - 1;
// trim the last invalid elements
for(; last >= 0 && !is_valid[last]; last--); // trim invalid elements from last
// now we keep swapping the invalid with last valid element
for(i=0; i < last; i++) {
if(is_valid[i])
continue;
arr[i] = arr[last]; // swap invalid with the last valid
last--;
for(; last >= 0 && !is_valid[last]; last--); // trim invalid elements
}
return last+1; // return the compact length of the array
}
다음 간단한 코드를 사용해 보십시오.
#include <stdio.h>
#include <conio.h>
void main(void)
{
clrscr();
int a[4], i, b;
printf("enter nos ");
for (i = 1; i <= 5; i++) {
scanf("%d", &a[i]);
}
for(i = 1; i <= 5; i++) {
printf("\n%d", a[i]);
}
printf("\nenter element you want to delete ");
scanf("%d", &b);
for (i = 1; i <= 5; i++) {
if(i == b) {
a[i] = i++;
}
printf("\n%d", a[i]);
}
getch();
}
저는 보통 이렇게 하고 항상 일을 합니다.
/해보세요/
for (i = res; i < *size-1; i++) {
arrb[i] = arrb[i + 1];
}
*size = *size - 1; /*in some ides size -- could give problems*/
언급URL : https://stackoverflow.com/questions/15821123/removing-elements-from-an-array-in-c
'programing' 카테고리의 다른 글
'System'을(를) 구현하지 않으므로 컬렉션 초기화기로 유형 '을(를) 초기화할 수 없습니다.소장품.IE 수 많은' (0) | 2023.10.19 |
---|---|
Angularjs 인수가 문자열을 얻은 함수가 아닙니다. (0) | 2023.10.19 |
URL 매개 변수를 인코딩하는 방법은 무엇입니까? (0) | 2023.10.19 |
UI SegmentedControl 선택한 세그먼트 색상 (0) | 2023.10.14 |
비교 시 변수 앞에 상수를 두는 이유는 무엇입니까? (0) | 2023.10.14 |