게시판

검색 결과: 118

 

문제를 풀이하는 방법은 여러 가지가 있을 수 있습니다.

다만, 문제를 해석한 전제가 틀리면 어떤 코드로도 심사문제를 통과할 수 없습니다. 회문 판별 문제의 예시를 보면 공백이 한 칸만 있는 경우가 아니라 두 칸인 경우도 있습니다.

cac

를 회문으로 판별해야 하지만

c   a      c

도 회문으로 판별해야 합니다.

공백 한 칸만 처리하는 코드라면 두 번째 예시를 통과할 수 없습니다.

if에서 초기식을 생략하는 것도 상관 없습니다. 상황에 따라 쓰이는 기법입니다.


, kim jungmin님이 작성
 


1)

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

#include <string.h>

#include <stdbool.h>


    int main() {

        char text[31];

        int len;

        int isPalindrome = true;


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

        len = strlen(text);


        int begin = 0;

        int end = len - 1;


        for (; begin < end; begin++, end--) {

            if (text[begin] == ' ')

                begin++;

            if (text[end] == ' ')

                end--;

            if (text[begin] != text[end]) {

                isPalindrome = false;

                break;

            }

        }


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


        return 0;

    }

==================================================================


2)

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

#include <string.h>

#include <stdbool.h>


    int main() {

        char text[31];

        int len;

        int isPalindrome = true;


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

        len = strlen(text);


        int begin = 0;

        int end = len - 1;


        for (; begin < end; begin++, end--) {

            if (text[begin] == ' ')

                continue;

            if (text[end] == ' ')

                continue;

            if (text[begin] != text[end]) {

                isPalindrome = false;

                break;

            }

        }


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


        return 0;

    }


이렇게 두 개를 작성해서 제출했을 때 틀렸다고 나왔습니다.

for 반복문 이하 두 if 조건문을 while로 바꾸니 통과가 되는데,

if조건문으로 실행을 하게 되면 혹시 코드에 문제가 있는건가요?


그리고 for 반복문 중 초기식에서 변수를 선언하지 않고 그 위에 선언해놓았는데요.

이 경우 위처럼 초기식을 생략해도 괜찮을까요?

, 조 조현기님이 작성
 

아래 질문 글을 올린 뒤, 해결을 위해 다른 코드를 작성했습니다.

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

#include <stdlib.h>

#include <stdbool.h>

#include <string.h>


int main()

{

bool ok = true;

char text[31]; // 입력값을 받을 배열

char* cat = malloc(sizeof(char) * 31); // 포인터 cat에 동적메모리 할당

memset(cat, 0, sizeof(char) * 31); // cat 초기화

scanf("%[^\n]s", text); // 입력값

char* ptr = strtok(text, " "); // " " 기준으로 문자열 자르기

char* sArr[31] = { NULL, }; // 문자열 저장할 배열 지정

int i = 0;

int length_sArr; // sArr의 길이

int length_cat; // cat의 길이

while (ptr != NULL) // 자른 문자열을 배열에 저장

{

sArr[i] = ptr;

i++;

ptr = strtok(NULL, " ");

}


length_sArr = strlen(sArr);


for (i = 0; i < length_sArr; i++) // 배열에 저장된 문자열을 붙이기

{

strcat(cat, sArr[i]);

}


length_cat = strlen(cat);


for (i = 0; i < length_cat / 2; i++) // 회문 점검

{

if (cat[i] == cat[length_cat - 1 - i])

{

ok = true;

}

else

{

ok = false;

break;

}

}

printf("%d", ok);




free(cat);

return 0;

}

visual studio 에서는 작동하는데,

심사문제에 제출했을 때는 작동하지 않아서

아래글과 더불어 이 코드도 확인부탁드려도 될까요.


, 조 조현기님이 작성
 

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

#include <stdlib.h>

#include <stdbool.h>

#include <string.h>


int main()

{

bool ok = true;

char text[31];

int length;

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

length = strlen(text);


int begin = 0;

int end = length - 1;

while (begin < end)

{

if (text[begin] == ' ')

{

begin++;

continue;

}

else if (text[end] == ' ')

{

end--;

continue;

}

else if (text[begin] == text[end - begin])

{

ok = true;

begin++;

end--;

}

else if (text[begin] != text[end - begin])

{

ok = false;

break;

}

}

printf("%d", ok);

return 0;

}


이렇게하고 실행을 해보니,

값이 0이 나오길래 

else if (text[begin] == text[end - begin])에 중단점을 설정해서

디버깅을 해보니,

text[1], text[10] 문자가 모두 'u'가 맞는데

else if 를 그냥 지나쳐서

아래 코드로 넘어가더라구요.

text[0], text[11] 문자는 같아서 코드가 실행되고,

text[1], text[10]은 문자가 같아도 코드가 실행되지 않을까요?

 

심사문제 해설의 힌트를 숙고해보면 도움이 됩니다.

이때 공백이 여러 개 연속될 수도 있다고 했으므로 인덱스를 증가, 감소시킬 때는 반복문을 사용해야 합니다. 

공백이 여러 개 올 수 있습니다. 공백의 개수를 미리 알 수 없을 때는 for, while 중에 어떤 것을 쓸까요? 모르면 UNIT 27, 28을 복습하세요.

반복문 안에서 공백이 있으면 해당 인덱스를 1씩 증가시켜 가면 됩니다.

index++을 하면 되겠지요.

뒤쪽에 공백이 있다면 반복문 안에서 인덱스를 1씩 감소시키면서 공백을 건너 뛰면 됩니다.

rindex 변수가 있다면 rindex--를 하면 되겠지요. r = right의 약자로 썼습니다.

s  t r i n   g

가 있다면 s의 위치는 index가 가리키고, g의 위치는 rindex가 가리키면 됩니다. s에서 시작해서 공백이 있을 때마다 index++을 하고, g에서 시작해서 역순으로 이동하면서 공백이 있을 때마다 rindex--를 하고, 공백이 아닌 문자가 있으면 일치하는 지 판별하면 됩니다.

str[index]와 str[rindex]가 일치하는지 판단하면 되겠지요.

모니터, 키보드, 화면을 멀리 하고, 종이와 펜으로 생각을 정리하세요. 그림으로 정리하고, 코딩을 하는 게 좋습니다.




, 홍 근하님이 작성
 

공백이 들어가면 문자열 길이의 반만큼 반복하는지, 앞에서 공백을 건너뛰면 뒤는 어떻게 건너뛰지 않게 하는지 도통 모르겠습니다.

 

컴파일러 경고를 무시하면 안 됩니다.

타입이 다르다는 뜻이고, 타입이 다르면 제대로 동작하지 않습니다.

문자열은 "로 둘러 싸고, 문자는 '로 둘러 쌉니다. str[0]의 타입은 문자열일까요? 문자일까요? C 언어는 문자열 타입이 없습니다. 문자의 배열로 처리합니다. C++이나 자바 같은 언어는 char, string처럼 문자와 문자열 타입이 따로 있습니다.

Visual Studio 2019에서는 조금 더 깐깐하게 오류를 검토합니다. Visual Studio 2016에서는 프로젝트 설정에서 오류 검토를 깐깐하게 할 수 있습니다.

프로젝트를 우클릭해서 속성으로...

경고 수준을 모든경고사용으로 지정하면 됩니다.


, 제주도 촌녀석님이 작성
 

아래는 제가 작성한 코드입니다.

#include <stdio.h>

#include <string.h>


int main()

{

    char str[31];

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

    

    int D = 1;

    

    int length = strlen(str);

    

    int begin = 0;

    int end = length - 1;

    

    while(begin < end)

    {    

        if(str[begin] == " ")

        {

begin++;

continue;

    }

        if(str[end] == " ")

        {

end--;

continue;

    }

if(str[begin] != str[end])

{

D = 0;

break;

}

   

    begin++;

    end--;

    }

    

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

    

    return 0;

}


처음과 끝을 비교하다가 공백이 나올시 continue를 진행했는데 뭐가 문제인지 모르겠네요...

공백없이 문자열만 입력하면 올바른 결과값이 나오는데 공백을 넣으면 결과가 이상하게 나오는데 원인을 모르겠어요..

 

포인터를 사용해서 의도적으로 연습하려는 것은 눈치채고 있었습니다.

다만, 어렵게 코딩하지 말고 쉽게 할 수 있는 건 쉽게 하는 게 더 중요하다는 뜻이었습니다. 포인터로 풀이하려고 하다보니 쉬운 길이 있는데, 너무 어려운 길로 가는 것 같았습니다.

나중에 디자인 패턴을 배우면 모든 코딩에 디자인 패턴을 사용하려고 해서 불필요하게 코드가 복잡해지는 문제가 발생합니다. 주니어 레벨에서 흔히 빠지는 오류입니다. 항상 적재적소를 잊지 마세요!



 

답변 감사드립니다.

 저는 절대로 주먹구구식으로 기계처럼 함수넣고 안되면 다른함수넣고 또 안되면 다른함수넣는 식으로 답이 나올때까지 반복해서 코딩을 짜는게 아닙니다. 또한 연속하여 말씀해주시는 strtok함수 NULL관련 처리는 첫 답변을 보고 추가하여 NULL관련 문제는 해결했습니다. 문제를 해결하기 위해 어떤 로직이 필요한가 생각하고, 그 로직대로 현재까지 책에서 배운 내용을 바탕으로 짜려고 합니다. 그래서 38.8심사문제 지뢰찾기를 풀 때 엉뚱하게도 NULL이 탐색되면 문자열의 탐색이 끝난다는 것을 잊어버린 채 입력된 문자열의 크기보다 가로,세로를 2줄 더해 외곽엔 NULL을 넣고 지뢰를 탐색하는 로직을 짜서 한동안 엑세스위반 경고문을 보면서 깨닫고 로직을 바꿔 해결했었습니다.

 이 문제 또한   malloc으로 할당한 최종결과배열을 NULL로 초기화하지 않는다면 입력값의 크기가 최종결과배열의 크기보다 작을때 회문판별코드에서 쓰레기값을 비교할 수 있다는 것을 캐치하지 못하여 문제를 해결하지 못했습니다. 물론 답변을 본 지금은 memset을 통하여 포인터변수로도 해결했습니다.

 문제를 해결할 때 효율성을 따진다면 배열을 써서 푸는게 맞겠으나, 저는 배운 문자열관련 함수들(str어쩌구)을 사용해서도 내가 생각한 로직대로 풀릴까 호기심이 생겨 포인터배열쪽으로 풀어보려고 했었습니다. 절대로 아무생각없이 대충 짠 코드 올려놓고 정답 알려주세요 라는 식으로 질문을 올린건 아니라는걸 알아주셨으면 합니다. 다만 초심자이기에 똑똑한 사람들은 자연스럽게 캐치할 수 있는 부분들을 머리가 좋지 않은지라 캐치하지 못해 이런 문제가 생길 뿐입니다..ㅠㅠ


 여하튼 다시한번 답변주신거 감사합니다~~