C언어 strcmp함수 한글입력과 영어입력 차이 질문드립니다....

asd137485의 이미지

안녕하세요 c언어 열공하고있는 초보 코린이입니다.. ㅎㅎ
c언어 문법서를 풀다가 발견한 문제점인데.. 바로 본론으로 들어가자면 strcmp함수에 2명의 한글or영어 이름을 입력해서 이름이 같은지 판별하는 문제입니다.

-주어진 문제:
프로그램 사용자로부터 이름과 나이를 다음의 형식에 맞춰서 하나의 문자열로 입력받는다.
ex)"이정선 29" "한수정 7" "오선주 17"
이름은 세 글자가 아닐 수도 있고 영문으로 입력될 수도 있다. 단, 이름과 나이 사이에만 공백이 삽입되어야 한다. 이러한 형식으로 이름과 나이의 동일 여부를 각각 판단하여 출력하는 프로그램을 작성해보자.

- 코드를 이렇게 짜봤는데..

#include
#include
#include

int main(void) {
int i, j, k = 0;
char str1[100]; // 첫 번째 이름과 나이를 입력받을 메모리 공간
char str2[100]; // 두 번째 이름과 나이를 입력받을 메모리 공간
char name1[50]; // 첫 번째 이름을 입력받을 메모리 공간
char name2[50]; // 두 번째 이름을 입력받을 메모리 공간
int age1[3]; //첫 번째 나이를 입력받을 메모리 공간
int age2[3]; //두 번째 나이를 입력받을 메모리 공간

printf("첫 번째이름과 나이를 입력하시오.ex)홍길동 32 :");
fgets(str1, sizeof(str1), stdin);
str1[strlen(str1) - 1] = 0;
printf("두 번째이름과 나이를 입력하시오.ex)홍길동 32 :");
fgets(str2, sizeof(str2), stdin);
str2[strlen(str2) - 1] = 0;

for (i = 0; str1[i] != ' '; i++) {
name1[i] = str1[i]; //띄어쓰기를 기준으로 입력받은 이름을 전달함
}
j = i; //j값은 띄어쓰기가 위치한 값

for (i = j + 1; str1[i] != '\0'; i++) {
age1[k] = str1[i]; //띄어쓰기 이후 입력받은 나이를 전달함
k++;
}
k = 0;

for (i = 0; str2[i] != ' '; i++) {
name2[i] = str2[i]; ///띄어쓰기를 기준으로 입력받은 이름을 전달함
}
j = i; //j값은 띄어쓰기가 위치한 값

for (i = j + 1; str2[i] != '\0'; i++) {
age2[k] = str2[i]; //띄어쓰기 이후 입력받은 나이를 전달함
k++;
}

if (!strcmp(name1, name2))
printf("두 사람의 이름은 동일합니다.\n");
else
printf("두 사람의 이름은 동일하지 않습니다.\n");

if (atoi(&age1)==atoi(&age2))
printf("두 사람의 나이는 동일합니다.\n");
else
printf("두 사람의 나이는 동일하지 않습니다.\n");

return 0;
}

아직 제 수준에서 부족함을 느낍니다..(코드가 깔끔하지 않은 점 일단 죄송합니다!) 구글링도 해보고 논리적 비약을 찾으려고 노력도 해봤는데 영어로 입력할 때는 이름 동일여부가 판단되고 한글로 이름을 입력하면 이름 동일 여부가 판단 안되는게 제 수준에서 한계를 느껴 도움을 청합니다..ㅜ

익명 사용자의 이미지

    char age1[3]; // int --> char 로 변경 (문자로 입력을 받으므로)
    char age2[3];
...........................................................
    for (i = 0; str1[i] != ' '; i++) {
        name1[i] = str1[i];
    }
    name1[i] = '\0';  // 스트링값은 마지막이 '\0' 문자로 끝나야함
..........................................................
    if (atoi(age1) == atoi(age2))  // &age1 --> age1 로 변경 (배열이름은 포인터와 같으므로)
        printf("두 사람의 나이는 동일합니다.\n");
    else
        printf("두 사람의 나이는 동일하지 않습니다.\n");
asd137485의 이미지

스트링값 마지막에 '\0' 문자를 안 붙여서 그런 오류가 생긴거였군요..! 그런데.. 영어로 입력할 때(스트링 값 마지막에'\0'안 붙인 상태에서)는 이름의 동일 유무는 정상적으로 판별이 되었는데, 한글로 입력할 때만 이런 오류(?)가 생기는 논리적이유를 알 수 있을까요...?

김정균의 이미지

그건 race condition 에 의해서 그런 결과가 나온거지, 영어/한글에 따라 다르게 나온 것은 아닙니다. C 의 경우 자료형이 자유롭기 때문에 한글, 영어 데이터의 자료형이 달라지지는 않습니다. '\0' 마킹을 안하고 실행할 경우, 실행 될 때 변수에 할당된 메모리의 상태에 따라 결과가 다르게 나올 뿐 입니다. 님의 경우에는 영어로 테스트를 했을 때 재수가 좋게 메모리 상태가 깨끗한 부분을 할당 받았다고 보셔야 겠죠.

해당 변수들을 0으로 memset 을 하시고 하셨다면 동일한 결과를 보실 수 있습니다. 결국 이 작업이 스트링 마지막에 '\0' 을 넣어주는 것과 동일한 효과를 보는 것이니까요.

asd137485의 이미지

한/영에 따라 달라지는 것이 아니라, 결국에는 '\0'마킹을 안해서 메모리의 상태에 따라 달라지는 거였군요.. 계속 마음에 걸려서 답답했는데 덕분에 해결됐습니다. 공부할 수록 더 공부해야 한다고 느껴지네요.. 어리숙한 질문에도 친절하게 답변해주셔서 감사합니다..!

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.