//삼위일체(수조, 지침, 메모리 분배) 이해

이전에 나는 두 가지 유형의 매개 변수 전달과 메모리 주소 도입, 지침, 그리고 전체적인 인용과 인용의 개념에 대해 토론했다.그러나 이것은 우리가 마지막으로 지침을 본 것이 아니다.포인터는 C 프로그래밍의 없어서는 안 될 부분이며, 프로그래머 컨트롤러에 생성된 변수를 제공합니다. 본 논문의 주제인 수조와 문자열을 포함한 모든 곳에서 볼 수 있습니다.
복습으로 수조는 같은 데이터 유형의 대상 집합: ints, doubles, chars 등이다. 한편, 문자열은 문자 수조이다.C 언어에는 본체 문자열 데이터 형식이 없기 때문에 언어가 실제적으로 하나의 문자열이 아니라 하나의 문자열 그룹으로 구분할 수 있도록 끝에 빈 종료자 '\0'을 추가합니다.
그러나 흥미로운 것은 문자열 데이터 형식이 없지만 C는 문자열에 전문적으로 사용되는 형식 설명자(%s)와 내장 라이브러리(string.h)가 있다는 것이다. 나는 본고에서 토론할 것이다.
여기까지 말하고 문제 진술로 넘어가자.
문제.

Implement a palindrome checker using various string functions in C.
Your program should be able to:

  • Scan for the word to be checked
  • Pass the word to a function called isPalindrome which returns an int to be interpreted in the main() whether the given word is a palindrome or not.
  • Loop indefinitely until the word ”EXIT” is used as input.
  • Store each palindrome in an array, then print all palindromes before exiting the program.

이를 위해, 나는 목표를 주요 목표에 속하는 목표와 주요 목표에 속하지 않는 목표로 나눌 것이다. 초기 변수를 신속하게 열거할 것이다. 현재 내가 필요로 하는 유일한 변수는 사용자가 입력한 char[] 문자열이다.
isPalidrome 함수
회문은 같은 내용을 뒤로 또는 앞으로 읽는 단어다.이것은 내가 isPalindrome 함수에 사용한 기초이다.목표는 문자열을 반전시켜 다른 변수에 저장한 다음 원시 변수와 비교해서 동일한지 확인하는 것이다.
또 다른 방법은 처음부터 끝까지 문자열을 비교하는 chars를 중간에서 만나는 것이다.그러나 문제 진술에서 isPalindrome은 C의 내장 문자열 함수를 사용해야 한다고 언급했기 때문에 해결 방안은 정의에 근거하기 때문에 나는 그것을 어떻게 사용하는지 토론할 것이다.
앞에서 말한 바와 같이 C에는 string.h이라는 내장된 문자열 라이브러리가 있다.이것은 문자열 조작을 처리하는 각종 함수를 포함한다. 예를 들어 strcpy은 문자열을 메모리 주소로 복사하고, strcat은 두 문자열을 연결한다.그러나 이 함수에 대해 나는 strlen만 사용하여 역방향 문자열을 만들고 strcmp을 사용하여 원시 문자열과 역방향 문자열을 비교할 것이다.
내 함수의 매개 변수는 문자열 자체로 보이지만 실제로는 문자열의 바늘을 전달한다.이것은 수조의 속성 때문에 발생한 것이다. 이 속성에서 인덱스가 없는 수조를 호출하는 것은 첫 번째 요소를 호출하는 지침과 같다.수조의 내용은 순서대로 메모리에 저장되기 때문에, 우리는 상기 지침을 추가하기만 하면 모든 수조에 접근할 수 있다.대부분의 문자열 함수는 문자열을 매개 변수의 바늘로 삼아야 하기 때문에 이 점을 지적하는 것도 중요하다.
int n1, n2;
int example[] = {1, 2, 3};

n1 = example[0];
n2 = *example; // Dereferencing example
printf("%d = %d", n1, n2); // 1 = 1

n1 = example[1];
n2 = *(example + 1); // Dereferencing example
printf("%d = %d", n1, n2); // 2 = 2
함수로 돌아가서 문자열을 반전시키기 위해 저는 먼저 char 수조를 만들었습니다. len개의 값을 포함하고 이름은 sReverse입니다. 그 중에서 lenstrlen(string)에서 얻은 문자열의 길이입니다.그곳에서 나는 원시 문자열의 순환을 설정하여 ((len - 1) - i) 네 번째 색인 중의 모든 자모를 i 네 번째 색인 sReverse에 분배했다.
// String reversal
for (i = 0; i < len; i++) {
    sReverse[i] = string[len - i - 1];
}

그러나 이것은 아직 완성되지 않았다. 왜냐하면 내가 한 것은 {'h', 'e', 'l', 'l', 'o'}과 비슷한 것을 만드는 것이지 "hello"이 아니기 때문이다. 왜냐하면 엔딩에 빈 종지부가 부족하기 때문이다.다음과 같은 행을 추가할 수 있습니다.sReverse[i] = '\0';현재 나는 이미 완성했다. 유일하게 해야 할 일은 새로운 sReverse 문자열과 원시 문자열을 비교하는 것이다.만약 그것들이 같다면 함수는 1을 진짜로 되돌려주고 그렇지 않으면 0을 되돌려준다.이 기능은 strcmp에서 쉽게 수행할 수 있습니다.
문자열 비교 또는 strcmp은 문자열을 한 글자씩 검사하고 ASCII 테이블의 값을 기준으로 비교하는 두 가지 매개변수를 적용합니다.다음은 strcmpreference입니다.

The function strcmp() compares str1 and str2, then returns [a value]:

  • less than 0 if str1 is less than str2
  • equal to 0 if str1 is equal to str2
  • greater than 0 if str1 is greater than str2

그러나 이 예에서 가장 중요한 것은 문자열이 같은지 여부이다. 그래서 나는 strcmp의 출력이 0인지 검사할 뿐이다.
이것은 나의 isPalidrome 함수의 전체 내용이다.
int isPalindrome(char string[]) {
    int len = strlen(string);
    char sReverse[len];
    int i;

    // String reversal
    for (i = 0; i < len; i++) {
        sReverse[i] = string[len - i - 1];
    }
    // Add a null-terminator at the end of the string
    sReverse[i] = '\0'; 

    // String comparison
    if (strcmp(string, sReverse) == 0) {
        return 1;
    } else {
        return 0;
    }
}
소문자 함수isPalidromestrcmp(ASCII 값으로 확장)을 사용하여 문자열을 비교하기 때문에 대문자와 소문자를 동시에 포함하는 문자열(예를 들어 "Level" 또는 "huH")은 즉시 비회문으로 간주된다. 대문자의 ASCII 값이 소문자보다 낮기 때문이다.따라서 isPalindrome을 통해 입력을 전달하기 전에 저는 먼저 입력을 표준화해야 합니다.
불행히도 이렇게 하는 내장 함수는 존재하지 않는다.다행히도, 대소문자를 바꾸거나, 문자가 무엇인지 확인하는 라이브러리 처리 문자 자체의 작업이 있다. 이것이 바로 ctype.h이다.lowercase은 실용 함수입니다. isPalindrome을 호출하기 전에 사용할 것입니다. 문자열의 대소문자를 소문자로 바꾸는 것입니다.나는 문자열의 소문자 사본을 만드는 것이 아니라 문자열 자체를 바꾸고 싶어서 문자열의 바늘로 그것을 훑어보고 tolower(*i)을 단독으로 사용하기로 결정했다. 그 중에서 i은 바늘이다.
void lowercase(char* string) {
    char* i; // String pointer
    for (i = string; *i != '\0'; i++) {
        *i = tolower(*i);
    }
}
나는 문자열의 주소를 i에 저장하고 빈 종지부에 도달할 때까지 1로 늘렸다.이것은 내가 앞서 언급한 수조 요소의 순서를 메모리에 직접 적용했기 때문에 i++을 실행함으로써 나는 문자열을 두루 훑어볼 수 있다.
주요 기능
main 함수로 넘어가서 while 순환을 계속 사용하고 종료 조건을 1로 설정하면 입력을 무기한으로 요청합니다. 이것은 내가 이전에 한 것과 유사합니다.이 예에서 나는 if-else 문장을 추가했는데, 단어 EXIT을 입력하면 이 문장은 순환을 중단할 것이다.내가 해야 할 일은 "EXIT"을 사용하여 사용자 입력을 strcmp과 비교하는 것이다.이것은 거의 주요 부분의 절반이다.
내가 실현해야 할 다음 관건은 끝날 때 회문으로 확정된 모든 단어를 인쇄하는 것이다.이것은 즉시 나에게 수조를 사용해야 한다고 알려주었다.그러나 하나의 주요 장애는 입력 스캐닝이 무기한으로 실행되기 때문에 사용자가 얼마나 많은 단어를 입력해야 하는지 모르기 때문에 고정된 크기의 그룹이 이것에 대해 작용하지 않는다는 것이다.
즉, 원소의 초기 수량만 알면 malloc 동적 분배 수조를 사용할 수 있는 또 다른 방법이 있다.이 경우 원하는 크기로 설정하고 스토리지가 가득 차면 크기를 조정할 수 있습니다.malloc을 사용하는 방법은 다음과 같습니다.
data_type ptr = malloc(initialSize * sizeof(data_type));
malloc은 데이터 형식의 바늘을 되돌려줍니다. 이 바늘은 sizeof(data_type)에 내가 원하는 원소량을 곱해서 요청한 공간을 계산합니다. 이것은 수조[0]의 바늘과 같은 작업 방식입니다.
또 다른 장애는 수조가 문자열을 저장하는 것을 감안하면 이 수조는 실제적으로 다차원적인 동적 분배 수조로 변한다. 이것은 복잡하게 들리지만 실제로는 상당히 이해하기 쉽다.이 diagram은 무슨 일이 일어났는지 이해하는데 도움이 될 것이다.

따라서 수조는 기본적으로 하나의 바늘로 하나의 바늘을 가리키고 이 바늘도 하나의 문자열을 가리킨다.이를 위해 나는 먼저 문자 포인터 그룹을 만들 것이다.
int arraySize = 100;
char **array = malloc(arraySize * sizeof(char*));
그런 다음 배열의 각 요소를 동적 할당 문자열로 설정합니다.
int stringLength = 100;
array[i] = malloc((stringLength + 1) * sizeof(char));
현재 나는 이미 설정을 해 놓았는데, 마지막 목표는 이 그룹을 채우는 것이다.strcpy을 사용합니다. 만약 isPalindrome이 사용자 입력이 답문이라고 확정한다면, 나는 strcpy을 호출하여 사용자 입력을 그룹으로 복사할 수 있습니다.
while (1) {
    // Scanning for user input

    if (strcmp(string, "EXIT") != 0) {
        lowercase(string);
        if (isPalindrome(string) == 1) {
            printf("%s is a Palidrome\n", string);

            // Storing the string
            array[i] = malloc((stringLength + 1) * sizeof(char)); 
            // +1 to account for the null-terminator
            strcpy(array[i], string); 
            // Copy the user string to the string address
            i++;
        } else {
            printf("%s is not a Palidrome\n", string);
        }
    } else {
        break;
    }
}
종료 조건이 충족되었을 때, 내가 해야 할 일은 이 그룹을 반복해서 훑어보고 요소를 인쇄하는 것이다.마지막으로 동적 분배를 처리할 때와 마찬가지로, 나는 먼저 문자열을 통해 2D 그룹을 순환해서 방출한 다음에 그룹 자체를 방출할 것이다.
결론
물론, 이 문제는 상당히 어렵다. 특히 나는 메모리 분배가 어떻게 작동하는지 거의 모르고, 지침이 어디로 향하는지 모르면 곤혹스러울 것이다.
나의 주요 문제는 malloc을 사용하여 2D 그룹을 설정하는 것이다. 주로 내가 동적 분배를 할 때 발생하는 일을 내부화할 수 없기 때문이다.내가 문법 자체를 분해하고 모든 매개 변수의 작용, 그것들과 지침의 관계, 그리고 되돌아오는 값의 용도를 연구하기 시작할 때까지는 의미가 있었다.
다른 한편, 수조와 문자열 자체는 하나의 개념으로서 나에게 있어서 받아들일 수 있다. 왜냐하면 나는 이미 그것을 사용한 경험이 있기 때문이다.그러나 전반적으로 말하자면, 물건이 걸릴 때까지 만지작거리고 시도를 통해, 내가 필요로 하는 방식으로 지침, 그룹, 메모리 분배를 어떻게 사용하는지 해결하는 데 도움을 주었다.나는 지금 이 개념들을 정확하게 사용하는 것이 얼마나 강한지 똑똑히 보았다.

좋은 웹페이지 즐겨찾기