문자열을 올바르게 비교하려면 어떻게합니까?


182

사용자가 단어 나 문자를 입력하고 저장 한 다음 사용자가 다시 입력 할 때까지 인쇄하여 프로그램을 종료 할 수있는 프로그램을 얻으려고합니다. 내 코드는 다음과 같습니다

#include <stdio.h>

int main()
{
    char input[40];
    char check[40];
    int i=0;
    printf("Hello!\nPlease enter a word or character:\n");
    gets(input);
    printf("I will now repeat this until you type it back to me.\n");

    while (check != input)
    {
        printf("%s\n", input);
        gets(check); 
    }

    printf("Good bye!");


    return 0;
}

문제는 사용자의 입력 (확인)이 원본 (입력)과 일치하더라도 입력 문자열을 계속 인쇄한다는 것입니다. 두 가지를 잘못 비교하고 있습니까?


13
gets( )표준에서 제거되었습니다. fgets( )대신 사용하십시오 .
Edward Karak

1
참고이 있다는 대답왜 않습니다 strcmp()자사의 입력이 동일 반환 제로 이하 같거나보다 평등, 불평등, 이상에 대한 문자열을 비교하는 방법을 설명하고,보다 크거나 같음. 모든 문자열 비교가 동일한 것은 아닙니다. 대소 문자 구분 비교는 다시 다릅니다. 다른 특수 비교 (예를 들어, 사전 순서)에는보다 전문화 된 비교기가 필요하며, 더 복잡한 비교를위한 정규식이 있습니다.
Jonathan Leffler

본질적으로 중복되는 질문 이 있습니다. 이 몇 년 전에 요청 된 문자열과 일치하는지 어떻게 확인합니까?
Jonathan Leffler 2013

이것이 귀하의 질문에 대답합니까? 값이 문자열과 일치하는지 확인하는 방법
Andreas

이 질문은 훌륭하지만 사용은 gets()끝이 없습니다. C11 이후 표준에서 제거되었습니다.-> 읽기 기능을 사용하지 않아야하는 위험한 이유는 무엇입니까?를 참조하십시오.
RobertS는

답변:


276

당신은 (유용)를 사용하여 문자열을 비교할 수 없습니다 !=또는 ==사용할 필요가 strcmp:

while (strcmp(check,input) != 0)

때문에 그 이유는 !=하고 ==만 문자열의 기본 주소를 비교합니다. 문자열 자체의 내용이 아닙니다.


10
java와 동일하며 주소와 비교할 수 있습니다.
Telerik

29
글쓰기 while (strcmp(check, input))는 충분하며 좋은 습관으로 간주됩니다.
시바


7
strncmp를 사용하는 것이 더 안전합니다! 버퍼 오버 플로우를 원하지 않습니다!
Floam

@Floam 실제로 문자열이 없지만 알려진 길이의 0이 아닌 문자로 채워진 0으로 채워진 시퀀스가 ​​있다면 그것은 올바른 주문입니다. 그러나 그것은 완전히 다른 것입니다!
중복 제거기

33

몇 가지 확인 : gets안전fgets(input, sizeof(input), stdin) 하지 않으며 버퍼 오버플로가 발생하지 않도록 대체해야합니다 .

다음으로 문자열을 비교하려면을 사용해야합니다 strcmp. 여기서 반환 값 0은 두 문자열이 일치 함을 나타냅니다. 항등 연산자 (즉, !=)를 사용하면 두 문자열의 주소가 char내부 의 개별 문자열과 비교되는 것과 비교 됩니다.

또한이 예제에서는 문제를 일으키지 않지만 fgets개행 문자를 '\n'버퍼에도 저장합니다 . gets()하지 않습니다. 사용자 입력을 fgets()문자열 리터럴과 비교하면 "abc"결코 일치하지 않을 것입니다 (버퍼가 너무 작아서 '\n'맞지 않을 경우).


"\ n"의 관계 / 문제와 문자열 리터럴을 명확하게 설명해 주시겠습니까? 파일의 문자열 (줄)을 다른 전체 파일과 비교할 때 동등한 결과를 얻지 못합니다.
무능한

@incompetent —로 파일에서 행을 읽는 경우 줄 바꿈을 유지 하기 때문에 fgets()문자열 일 수 있습니다 . 와를 비교 하면 널 바이트 종료 와 읽은 데이터의 개행 문자 의 차이로 인해 '같지 않음'이 됩니다. 따라서 줄 바꿈을해야합니다. 그렇게하는 신뢰성 한줄 방법은 관계없이 거기에 상기 버퍼 내의 데이터, 또는 개행 데이터 종료할지 여부에 제대로 작동의 장점을 갖는다. 개행을 재핑하는 다른 방법은 쉽게 충돌합니다. "abc\n"fgets()"abc""abc"buffer[strcspn(buffer, "\n")] = '\0';
Jonathan Leffler

이 답변은 코드 문제를 정확하게 해결하는 반면 가장 많이지지되고 승인 된 답변은 질문의 제목에만 답변합니다. 특히 마지막 단락을 언급하는 것은 슈퍼입니다. +1
RobertS는

11

사용하십시오 strcmp.

이것은 string.h도서관에 있으며 매우 인기가 있습니다. strcmp문자열이 같으면 0을 반환합니다. 무엇이 반환 되는지에 대한 자세한 설명은 이것을 참조하십시오 strcmp.

기본적으로 다음을 수행해야합니다.

while (strcmp(check,input) != 0)

또는

while (!strcmp(check,input))

또는

while (strcmp(check,input))

확인할 수 있습니다 ,에 대한 자습서를 strcmp.


7

이처럼 직접 배열을 비교할 수 없습니다

array1==array2

당신은 그것들을 문자별로 비교해야합니다; 이를 위해 함수를 사용하고 부울 (True : 1, False : 0) 값을 반환 할 수 있습니다. 그런 다음 while 루프의 테스트 조건에서 사용할 수 있습니다.

이 시도:

#include <stdio.h>
int checker(char input[],char check[]);
int main()
{
    char input[40];
    char check[40];
    int i=0;
    printf("Hello!\nPlease enter a word or character:\n");
    scanf("%s",input);
    printf("I will now repeat this until you type it back to me.\n");
    scanf("%s",check);

    while (!checker(input,check))
    {
        printf("%s\n", input);
        scanf("%s",check);
    }

    printf("Good bye!");

    return 0;
}

int checker(char input[],char check[])
{
    int i,result=1;
    for(i=0; input[i]!='\0' || check[i]!='\0'; i++) {
        if(input[i] != check[i]) {
            result=0;
            break;
        }
    }
    return result;
}

1
솔루션에 대한 자세한 내용을 추가해 주시겠습니까?
abarisone

예, 이것은 string.h 헤더를 사용하지 않고 strcmp 기능 및 해결을 대체합니다 @Jongware
mugetsu

2
작동하지 않습니다. 때 checker발견은 '\0'문자열 중 하나, 그것은을위한 다른 문자열을 확인하지 않습니다 '\0'. 함수는 1한 문자열이 다른 문자열의 접두사 (예 : "foo""foobar") 인 경우에도 ( "같음")을 반환합니다 .
lukasrozs

1
||대신에 사용하겠습니다 &&.
lukasrozs

3

포인터 의 개념에 오신 것을 환영합니다 . 여러 세대의 초보 프로그래머가이 개념을 이해하기 어려웠지만 유능한 프로그래머로 성장하려면 결국이 개념을 숙달해야합니다. 또한 이미 올바른 질문을하고 있습니다. 잘 됐네요

주소가 무엇입니까? 이 다이어그램을보십시오 :

----------     ----------
| 0x4000 |     | 0x4004 |
|    1   |     |    7   |
----------     ----------

다이어그램에서 정수 1은 주소 0x4000의 메모리에 저장됩니다 . 왜 주소에? 도시가 크고 많은 가족을 수용 할 수있는 것처럼 메모리가 크고 많은 정수를 저장할 수 있기 때문에. 각 정수는 집에 상주하므로 각 정수는 메모리 위치에 저장됩니다. 각 집은 주소 로 식별되므로 각 메모리 위치는 주소 로 식별됩니다.

다이어그램의 두 상자는 서로 다른 두 개의 메모리 위치를 나타냅니다. 마치 마치 집처럼 생각할 수 있습니다. 정수 1은 주소 0x4000 ( "4000 Elm St.")의 메모리 위치에 있습니다. 정수 7은 주소 0x4004 ( "4004 Elm St.")의 메모리 위치에 있습니다.

프로그램이 1과 7을 비교한다고 생각했지만 그렇지 않았습니다. 0x4000과 0x4004를 비교하고있었습니다. 이 상황이 발생하면 어떻게됩니까?

----------     ----------
| 0x4000 |     | 0x4004 |
|    1   |     |    1   |
----------     ----------

두 정수는 동일하지만 주소가 다릅니다. 프로그램이 주소를 비교합니다.


2

문자열을 비교하려고 할 때마다 각 문자와 관련하여 문자열을 비교하십시오. 이를 위해 strcmp (input1, input2)라는 내장 문자열 함수를 사용할 수 있습니다. 그리고 당신은라는 헤더 파일을 사용해야합니다#include<string.h>

이 코드를 사용해보십시오 :

#include<stdio.h> 
#include<stdlib.h> 
#include<string.h>  

int main() 
{ 
    char s[]="STACKOVERFLOW";
    char s1[200];
    printf("Enter the string to be checked\n");//enter the input string
    scanf("%s",s1);
    if(strcmp(s,s1)==0)//compare both the strings  
    {
        printf("Both the Strings match\n"); 
    } 
    else
    {
        printf("Entered String does not match\n");  
    } 
    system("pause");  
} 

0

문자열을 올바르게 비교하려면 어떻게합니까?

char input[40];
char check[40];
strcpy(input, "Hello"); // input assigned somehow
strcpy(check, "Hello"); // check assigned somehow

// insufficient
while (check != input)

// good
while (strcmp(check, input) != 0)
// or 
while (strcmp(check, input))

check != input충분하지 않은지 더 깊이 파헤쳐 보자 .

C에서 문자열 은 표준 라이브러리 사양입니다.

문자열은 첫 번째 널 문자를 포함 연속에 의해 종료 문자의 순서와입니다.
C11 §7.1.1 1

input위의 문자열 이 아닙니다 . input문자의 어레이 (40) .

의 내용은 문자열input 이 될 수 있습니다 .

대부분의 경우 배열을 식에 사용하면 첫 번째 요소의 주소로 변환됩니다.

아래는 첫 번째 요소의 각 주소 로 변환 check되고 input해당 주소가 비교됩니다.

check != input   // Compare addresses, not the contents of what addresses reference

문자열 을 비교하려면 해당 주소를 사용하고 그들이 가리키는 데이터를 확인해야합니다.
strcmp()일을한다 . §7.23.4.2

int strcmp(const char *s1, const char *s2);

strcmp기능이 가리키는 문자열을 비교 s1문자열에 의해 지적에 s2.

strcmp함수는 by s1가 가리키는 문자열이 by 가 가리키는 문자열보다 크거나 같거나 작으므로 정수보다 크거나 같거나 0보다 작은 정수를 반환합니다 s2.

코드가 문자열이 동일한 데이터인지 여부를 찾을 수있을뿐만 아니라 문자열이 다르면 더 큰지 아닌지를 찾을 수 있습니다.

문자열이 다를 경우 다음과 같습니다.

strcmp(check, input) != 0

통찰력을 얻으려면 함수 만들기를 참조하십시오.strcmp()


-2
    #include<stdio.h>
    #include<string.h>
    int main()
    {
        char s1[50],s2[50];
        printf("Enter the character of strings: ");
        gets(s1);
        printf("\nEnter different character of string to repeat: \n");
        while(strcmp(s1,s2))
        {
            printf("%s\n",s1);
            gets(s2);
        }
        return 0;
    }

이것은 원하는대로 출력을 얻을 수있는 매우 간단한 솔루션입니다.


2
gets();C11 이후 표준 C의 일부가 아닙니다.
chux-복원 Monica Monica

2
strcmp(s1,s2)s2내용이 처음에 지정되지 않았으므로 UB 입니다.
chux-복원 Monica Monica

이 스 니펫의 출력을 어떤 형태로도 제공 할 수 있다면 좋을 것입니다.
not2qubit
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.