2010-01-15 4 views
19

자바 배경에서 배우기 C를 배우고 있습니다. 그러나 막연한 컴파일러 오류 메시지가 점점 더 실망하게됩니다. 내 코드는 다음과 같습니다.할당은 캐스트없이 정수에서 포인터를 만듭니다.

/* 
* PURPOSE 
*  Do case-insensetive string comparison. 
*/ 
#include <stdio.h> 
#include <string.h> 
#include <ctype.h> 

int compareString(char cString1[], char cString2[]); 
char strToLower(char cString[]); 

int main() { 
    // Declarations 
    char cString1[50], cString2[50]; 
    int isEqual; 

    // Input 
    puts("Enter string 1: "); 
    gets(cString1); 
    puts("Enter string 2: "); 
    gets(cString2); 

    // Call 
    isEqual = compareString(cString1, cString2); 
    if (isEqual == 0) 
     printf("Equal!\n"); 
    else 
     printf("Not equal!\n"); 

    return 0; 
} 

// WATCH OUT 
//  This method *will* modify its input arrays. 
int compareString(char cString1[], char cString2[]) { 
    // To lowercase 
    cString1 = strToLower(cString1); 
    cString2 = strToLower(cString2); 

    // Do regular strcmp 
    return strcmp(cString1, cString2); 
} 

// WATCH OUT 
//  This method *will* modify its input arrays. 
char strToLower(char cString[]) { 
    // Declarations 
    int iTeller; 

    for (iTeller = 0; cString[iTeller] != '\0'; iTeller++) 
     cString[iTeller] = (char)tolower(cString[iTeller]); 

    return cString; 
} 

두 개의 경고가 생성됩니다.

  • 할당은 캐스트
    • cString1 =하여 strtolower (cString1)없이 정수의 포인터를 만든다;
    • cString2 = strToLower (cString2);
  • 반환 캐스트
    • 반환 CString을하지 않고 포인터의 정수를 만든다;

누군가이 경고를 설명 할 수 있습니까?

답변

36

문자열은 Java 문자열과 같지 않습니다. 본질적으로 문자 배열입니다.

strToLower가 char을 반환하기 때문에 오류가 발생합니다. char는 C로 된 정수형입니다. char 인 포인터에 할당합니다. 따라서 "정수를 포인터로 변환".

strToLower가 모든 변경 작업을 수행하므로 아무 것도 반환하지 않아도됩니다. 특히 char이 아닙니다. void 나 char *를 "return"해야합니다.

strToLower를 호출 할 때 할당 할 필요가 없습니다. 기본적으로 cString1의 메모리 주소를 전달하는 것입니다.

내 경험상 C의 문자열은 Java/C# 배경에서 C로 돌아 오는 사람을 배울 수있는 가장 어려운 부분입니다. Java에서도 배열을 할당하기 때문에 메모리 할당이 가능합니다. 궁극적 인 목적이 C가 아닌 C++ 인 경우 C 문자열에 집중하지 않고 기본 사항을 이해하고 STL의 C++ 문자열 만 사용하는 것이 좋습니다.

+0

(+1)이 값은 자동 채우기의 대답 –

+0

을 추가합니다. ** 직접 ** 귀하의 질문에 대한 주제를 직접적으로 다루지는 않습니다 - 간접적 인 해결책 : D 컴파일러 경고 자동 응답을 없애기 위해 더 적합합니다 : D –

+0

좋아, 여기서 답을 명확히했다. – Uri

4

하여 strtolower의 반환 유형은 char*해야하지 char (또는 전혀 아무것도 돌려주지해야한다, 그렇지 않기 때문에 재 할당 문자열)

+0

(+1, 거의 -1 = D) 반환 유형을 바꾸는 것이 무엇을 의미합니까 ..... 이것은 반환 유형과 충돌하지만 char *를 반환합니다 ... –

+0

수정 됨. 고마워요. 나는 그것에 대해 아주 분명하지 않았습니다 :) – James

1
  • 1) gets를 사용하지 마십시오! 버퍼 오버 플로우 취약점이 발생했습니다. 대신 fgets(..., stdin)을 사용하십시오.

  • 2) strToLower에서 char- 배열 대신 char을 반환합니다. 자동 입력으로 제안 된 char*을 반환하거나 입력을 수정하고 있으므로 void 만 반환하십시오.그 결과, 단지

 

strToLower(cString1); 
strToLower(cString2); 
  • 3) 대소 문자를 구분하지 문자열을 비교하기 위해 쓰기, 당신은 사용할 수 있습니다 strcasecmp (리눅스 & Mac) 또는 stricmp (Windows)를 참조하십시오.
0

당신은이 두 assigments 필요하지 않습니다 : 당신이 장소에 문자열을 수정하는

cString1 = strToLower(cString1); 
cString2 = strToLower(cString2); 

. 만약 즉 범위의 첫 번째 요소의 포인터 숯불을 반환하고

-1
char cString1[] 

이 배열이다 (CHAR *와 동일하다) 숯불 []로 지정되기 때문에

경고는 같은 데이터 유형의 요소들. 배열 by-value하지만 by-pointer는 전달하지 않습니다.

char strToLower(...) 

그러나 이것은 char를 반환합니다. 그래서 과제

cString1 = strToLower(cString1); 

이 할당 연산자의 양쪽에 서로 다른 종류가 있습니다 .. 당신은 실제로 간단한 포인터로 확인 배열에 '문자'(정수의 종류)를 지정하고 있습니다. C++의 암시 적 변환 규칙으로 인해이 방법이 작동하지만 쓰레기이며 배열에 더 액세스하면 정의되지 않은 동작이 발생합니다.

해결책은 strToLowerchar*이되도록하는 것입니다.

0

배열의 첫 번째 문자를 가리키는 포인터 인 char *가 아니라 char을 반환합니다.

현재 위치 수정을 수행하는 대신 새 문자 배열을 반환하려면 매개 변수 또는 초기화되지 않은 포인터로 이미 할당 된 포인터 (char *)를 요청할 수 있습니다. 이 마지막 경우에는 새 문자열에 적절한 수의 문자를 할당해야하며 항상 값에 의해 전달되는 C 매개 변수에서이를 기억해야합니다. 따라서 함수에 의해 내부적으로 할당 된 배열의 경우 매개 변수로 char **를 사용해야합니다. 물론 호출자는 나중에 해당 포인터를 해제해야합니다.

0

strToLower는 char 대신 char *를 반환해야합니다. 이 같은 것이 할 것입니다. 다른 사람으로

char *strToLower(char *cString) 
2

이미 (이 컨텍스트에서 char * 값이다 - 포인터) cString를 반환하려고 한 경우, 언급 char을 반환 선언 된 함수에서가 (정수이다) . 다른 경우에는 역순으로 수행합니다. char 반환 값을 char * 포인터에 할당합니다. 이것이 경고를 유발하는 것입니다. 반환 값을 char이 아닌 char *으로 선언해야합니다.

참고 이러한 지정은 사실 언어의 관점에서이라는 제약 위반 인 입니다.그것들은 "에러"입니다.) 왜냐하면 정수와 정수를 제외하고 C에서 포인터와 정수를 혼합하는 것은 불법이기 때문입니다. 컴파일러는 이와 관련하여 너무 용서하고 이러한 위반을 단순한 "경고"로보고합니다.

몇 가지 대답에서 문자열을 현재 위치에서 수정하기 때문에 몇 가지 대답에서 함수에서 void을 반환하는 비교적 이상한 제안을 볼 수 있습니다. (실제로 문자열을 제자리에서 수정하고 있기 때문에) 확실히 작동하지만, 함수에서 같은 값을 반환하는 데는 아무런 문제가 없습니다. 사실, 적용 할 수있는 곳에서는 C 언어로 다소 표준적인 연습을하고 있습니다 (strcpy과 같은 표준 함수를 살펴보십시오). 사용을 선택하면 함수 호출의 "연결"이 가능하기 때문에 실제로는 아무 것도 들지 않습니다. "연결"을 사용하지 마십시오.

그렇다면 compareString 구현의 과제는 나에게 불필요한 것처럼 보입니다 (아무 것도 부수 지 않지만). 나는 (당신의 char * 반환 편리하게 올 것이다 때이다) 그들도

int compareString(char cString1[], char cString2[]) { 
    // To lowercase 
    strToLower(cString1); 
    strToLower(cString2); 

    // Do regular strcmp 
    return strcmp(cString1, cString2); 
} 

제거 또는 "체인"을 사용하고

int compareString(char cString1[], char cString2[]) { 
    return strcmp(strToLower(cString1), strToLower(cString2)); 
} 

을 할 것입니다. 이러한 "연결"함수 호출은 단계별 디버거로 디버깅하기가 어렵다는 점을 명심하십시오.

덧붙여 말하자면, 이처럼 파괴적인 방식으로 문자열 비교 기능을 구현하면 (입력 문자열을으로 수정하는 것이 가장 좋은 방법 일 수 있습니다). 비파괴적인 기능은 내 의견으로는 훨씬 더 큰 가치가 있습니다. 입력 문자열을 소문자로 명시 적으로 변환하는 대신, 대/소문자를 구분하지 않는 문자열 비교 함수를 구현하여 표준 strcmp 대신이 함수를 사용하는 것이 좋습니다.

관련 문제