게시판

검색 결과: 118

 

그림 45-1~4번까지 보면서 strtok 함수의 동작을 제대로 이해해야 합니다.

strtok 함수가 마지막 문자열까지 탐색하면 ptr은 반드시 NULL이 됩니다. 따라서 로직 진입, 로직 중간, 로직 종료에서 종료 처리가 필요합니다.

종료일 때 ptr이 NULL이 될 때는 중간 로직 실행을 하지 말아야 합니다.

로직 종료일 때 처리하는 부분은 UNIT 45.7의 심사문제 해설을 보면 다음과 같은 예시 코드를 제시하고 있습니다.

if (ptr != NULL && strcmp(ptr, "the") == 0)    // ptr이 NULL이 아니면서 ptr이 the일 때
    count++;                                   // count를 1 증가시킴

UNIT 45.7을 통과했었다면 해당 부분을 다시 한 번 복습하세요.

무작정 키보드 타이핑하고 실행하는 반복하지 말고, 손코딩하세요.

로직을 제대로 못 짜는 상황입니다. 물론, strcat으로 해결하는 방식은 일반적인 해법은 아니지만, 한다면 할 수 있겠지요.

malloc으로 공간을 할당하고 작업하려면 memset으로 초기화도 해야 합니다.
UNIT 35 복습하세요.

malloc으로 31바이트를 할당하고, 정확하게 31바이트 쓰기를 한다면 초기화를 하지 않습니다. 효율성을 위해서죠. 그러나 31바이트를 할당했으나 5바이트만 쓸지, 10바이트만 쓸지 모른다면 나머지 공간은 쓰레기 값으로 채워지니까 이런 경우에는 반드시 memset으로 초기화해야 합니다.

공간을 모두 없앤 문자열을 새로 만든다면 로직부터 손코딩으로 제대로 작성하고 코딩하세요. 자료구조나 알고리즘에서는 로직 구성이 더 중요하고, 코딩은 그걸 실천하는 도구일 뿐입니다.

이 문제에서는 입력 데이터의 크기가 정해져 있고, 공백을 제거하면 입력 데이터보다 작은 크기일 가능성이 크고, 최대 크기도 입력 데이터의 크기를 넘지 않을 겁니다. 그렇다면 굳이 malloc으로 공간을 할당할 필요가 있을까, 그냥 같은 크기의 배열을 하나 더 선언하면 되지 않을까. 포인터를 불필요하게 쓰는 것은 아닌가 같은 효율성 관점에서의 검토를 해야 합니다.

적절한 코드 작성이 더 중요합니다. 길벗 출판사의 <자바 코딩의 기술> 같은 코딩의 기술 시리즈를 참고하세요.

 

답변 감사합니다. 위에서 strcat(result, ptr)를 먼저 선언하지 않고 반복문 내에서 첫 행으로 입력하면 NULL이 입력이 되지 않는다는 걸 깨달았네요. 감사합니다~

 while (ptr != NULL)

    {

        strcat(result, ptr);

        ptr = strtok(NULL, " ");


        

    }


다만 이렇게 해도 프로그램은 정상 작동합니다만 결과값이 정상적으로 출력이 안되는데, 이유를 여쭤봐도 될까요?


 

답변 감사합니다. 위에서 strcat(result, ptr)를 먼저 선언하지 않고 반복문 내에서 첫 행으로 입력하면 NULL이 입력이 되지 않는다는 걸 깨달았네요. 감사합니다~

 while (ptr != NULL)

    {

        strcat(result, ptr);

        ptr = strtok(NULL, " ");


        

    }


다만 이렇게 해도 프로그램은 정상 작동합니다만 결과값이 정상적으로 출력이 안되는데, 이유를 여쭤봐도 될까요? 

, 임 진우님이 작성
 

우선

문의한 코드는 삭제합니다.


이런식으로 정답은 맞췄습니다만 제가 생각한 방식이 왜 안되는 건지 알고 싶습니다.


다음은 제가 짠 코드 전문입니다.


#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<stdbool.h>


int main()

{

    char a[31];


    scanf("%[^\n]s",a);


    char* result = malloc(sizeof(char) * 31);

    char* ptr = strtok(a, " ");


    strcpy(result, ptr);


    while (ptr != NULL)

    {

        ptr = strtok(NULL, " ");


        strcat(result, ptr);

    }


    int length = strlen(result);

    bool isok = true;

    for (int i = 0; i < length / 2; i++)

    {

        if (result[i] != result[length - i - 1])

            isok = false;

        break;

    }


    printf("%d", isok);

    return 0;

}


저는 공백을 없애기 위해 제시된 문자열을 공백 단위로 끊어 포인터배열에 저장한 뒤 메모리를 할당한 저장할포인터배열에 카피 후 자르는포인터배열이 NULL이 될 때까지 반복하며 자를 때마다 저장할포인터배열에 strcat을 이용하여 계속 이어붙이기를 해 결과적으로 공백이 없는 문자열을 얻고, 이 문자열로 회문확인처리를 하면 된다고 생각하였으나, strcat부분에서 메모리를 잘못 참조하였을 때 발생하는 0xC0000005: 0x0000000000000000 위치를 읽는 동안 액세스 위반이 발생했습니다. 라는 오류메세지가 떴습니다.


strcat을 사용 할 때 최종문자열이 메모리를 할당받은 포인터배열이라면 이어붙이기가 가능하다고 나와있는데, 무엇이 문제여서 저런 오류가 발생했는지 알고 싶습니다.

(도장_ 관리자님이 수정함 - 원문 제출일: 2020년 7월 21일, 화요일, 오전 10:32)

 

Visual Studio에서 ptr의 값을 보면 0x00000000인데요.

하단 로컬 창을 보면 ptr 값이 NULL이라는 뜻입니다.

입력 값으로 hello를 넣으면 공백으로 자를 게 없으니 ptr 값은 NULL이 됩니다.

NULL은 읽을 수 없으니까 액세스 위반이 발생합니다.

strtok 함수는 더 이상 자를 게 없을 때 마지막에는 NULL을 반환합니다.

항상 마지막에는 ptr이 NULL 일 수 밖에 없습니다.

따라서 이런 로직을 짤 때는 ptr이 NULL이 아니라는 조건을 반드시 검사한 다음에 해야 합니다.

strcat 함수는 아무 죄가 없습니다. NULL을 붙이려고 하기 때문이고, 액세스 위반은 무조건 포인터를 잘못 사용한 것입니다. 메모리 접근을 잘못했거나 범위를 벗어났거나 등의 문제가 발생했기 때문입니다.


, Sung HeeJun님이 작성
 

네 마지막 if문만 살렸습니다.

, 도장_ 관리자님이 작성
 

입력

rb  ce cbr
일 때도 1이 출력되어야 합니다.

문의한 코드는 0이 출력되기 때문에 심사를 통과하지 못합니다.


, 정 Cel님이 작성
 

감사합니다!! 

그러면 if문 2개를 다 while로 바꿔서 while문 2개로 만드셨다는 말씀이시죠??

, Sung HeeJun님이 작성
 

for 안의 if 두 개를 while로 바꾸고 continue;를 삭제했습니다.

, 정 Cel님이 작성
 

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

#include <string.h>

#include <stdbool.h>


int main()

{

    char s1[31];

    scanf("%[^\n]s", s1);

    

    bool isPalindrome = true;

    int length = strlen(s1);

    

    int num1 = 0, num2 =0;

    

    for (int i = 0; i < length / 2; i++)


{

if (s1[i + num1] == ' ')

{

num1++;

continue; //공백 여러개일때 다시 확인

}


if (s1[length - 1 - i - num2] == ' ')

{

num2++;

continue;

}


if (s1[i + num1] != s1[length - 1 - i - num2])

{

isPalindrome = false;

break;

}


}

    

    printf("%d\n", isPalindrome);

    

    return 0;

}


if 문에서 공백이 있는지 체크 후 continue를 사용해서 공백이 연속해서 있어도 계속 확인할 수 있게끔 만들었는데 , 심사를 통과하지 못하고 있습니다ㅠㅠ디버깅했을때는 1로 잘 나오는데 어느 부분이 틀렸는지 알려주시면 감사하겠습니다!!