2010-01-15 79 views
19

来自Java背景我正在学习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

C字符串不像Java字符串。它们基本上是字符数组。

由于strToLower返回一个字符,所以您会收到错误。 char是C中的一个整数形式。您将它分配给一个char [],它是一个指针。因此“将整数转换为指针”。

您的strToLower对其进行了所有更改,没有理由返回任何内容,尤其是不包含字符。你应该“返回”void或char *。

在对strToLower的调用中,也不需要赋值,你实质上只是传递了cString1的内存地址。根据我的经验,C中的字符串是学习任何来自Java/C#背景C的人最难的部分。人们可以相处内存分配(因为即使在Java中,您也经常分配数组)。如果您最终的目标是C++而不是C,那么您可能更倾向于将注意力放在C字符串上,确保您理解基本知识,并使用STL中的C++字符串。

+0

(+1)这增加了值autopulated的答案 – 2010-01-15 19:08:50

+0

这不**直接**解决您的问题的主题,但它 - 一个间接的解决方案:D以消除编译器警告汽车的答案更加贴切:D – 2010-01-15 19:15:33

+0

好的,在这里澄清答案。 – Uri 2010-01-15 19:45:17

4

用strtolower的返回类型应该是char*没有char (或者它应该返回什么都没有,因为它不重新分配的字符串)

+0

(+1,几乎-1 = D)你的意思是改变返回类型.....它返回char *,但是这与返回类型冲突... – 2010-01-15 19:06:39

+0

已修复。谢谢我不是很清楚:) – James 2010-01-15 19:08:52

1
  • 1)不要使用gets!您正在引入缓冲区溢出漏洞。改为使用fgets(..., stdin)

  • 2)在strToLower中,您将返回char而不是char-阵列。或者将char*返回为建议自动填充,或者只是返回void,因为无论如何您都要修改输入。其结果是,只写

 

strToLower(cString1); 
strToLower(cString2); 
  • 3)比较不区分大小写字符串,你可以使用strcasecmp(Linux的& Mac)或stricmp(Windows)中。
0

你不需要这两个assigments:

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

您在就地修改字符串。

警告是因为你正在返回一个字符,并分配到一个char [](这相当于为char *)

-1
char cString1[] 

这是一个数组,即指向一个范围的第一元件相同数据类型的元素。请注意,您不是按值传递数组,而是按指针传递数组。

char strToLower(...) 

但是,这会返回一个字符。所以,你的任务

cString1 = strToLower(cString1); 

对赋值运算符的每一面不同类型..你实际上分配“字符”(排序整数)到一个数组,其解析为一个简单的指针。由于C++的隐式转换规则有效,但的结果是垃圾,进一​​步访问数组会导致未定义的行为。

解决方法是使strToLower返回char*

0

您正在返回字符,而不是char *,它是指向数组的第一个字符的指针。

如果您想要返回一个新的字符数组而不是进行就地修改,您可以要求已经分配的指针(char *)作为参数或未初始化的指针。在这最后一种情况下,您必须为新字符串分配适当数量的字符,并记住在通过值ALWAYS传递的C参数中,因此必须在由函数内部分配数组的情况下使用char **作为参数。当然,调用者必须稍后释放该指针。

0

strToLower应该返回一个char *而不是char。像这样的事情会做。

char *strToLower(char *cString) 
2

正如其他人已经指出,在一种情况下,你在试图返回cString(这是这方面的一个char *值 - 指针)从被声明为返回一个char的功能(这是一个整数) 。在另一种情况下,您可以做相反的事情:您将char返回值分配给char *指针。这是触发警告的原因。您当然需要声明您的返回值为char *,而不是char。注意,从语言的角度来看,这些分配实际上是约束违规。他们是“错误”),因为混合C中的指针和整数是非法的(除了整数常数零)。您的编译器在这方面太过宽容,并将这些违规报告为“警告”。

我还想指出的是,在几个答案中,您可能会注意到相对奇怪的建议,从您的函数返回void,因为您正在就地修改字符串。虽然它肯定会起作用(因为你实际上是在就地修改字符串),但从函数返回相同的值没有任何问题。事实上,在适用的情况下,在C语言中这是一种相当标准的做法(请参阅strcpy等标准函数),因为如果您选择使用函数调用,它可以“调用”函数调用,并且如果您不要使用“链接”。

也就是说,在您的实施compareString看起来完成多余的任务(即使他们不会破坏任何东西)。我想无论是摆脱他们

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)); 
} 

(这是当你的char *回报会来方便)。请记住,这样的“链接”函数调用有时很难通过分步调试器进行调试。

作为一个额外的,未经实践的笔记,我会说,以这种破坏性的方式实现字符串比较功能(它修改输入字符串)可能不是最好的主意。在我看来,非破坏性的功能将具有更大的价值。除了将输入字符串显式转换为小写外,通常更好的办法是实现一个自定义逐个字符的不区分大小写的字符串比较函数,并使用它来代替调用标准strcmp