【问题标题】:strcmp function not working properlystrcmp 函数无法正常工作
【发布时间】:2013-11-05 17:19:41
【问题描述】:

我在结构数组books上有一个delete函数。我正在向它传递一组记录,author of book 和 name of book 和 size of the list。

现在这里鉴于list[0].author 和list[5].author 和author 都等于“Dan Brown”(相同的字符串)

void delete(struct books *list,char author[],char name[],int n)
{
    int i,a;
    a=strcmp(list[0].author,list[5].author);
    printf("%d\n",a);              // prints 0
    a=strcmp(list[0].author,author);
    printf("%d\n",a);              // prints other than 0
}    

为什么会这样?这里有什么问题?

【问题讨论】:

  • 您确定某些字符串的末尾没有'\n'?
  • list[0].author 从fgets() 函数和author 从strcpy() 获得输入
  • 要么使用调试器,要么使用 printf 全部 3 个字符串 printf("%s|%s|%s|\n", list[0].author, list[5].author, author); 应该打印 Dan Brown|Dan Brown|Dan Brown|
  • @xmpirate 使用strlen检查每个字符串的长度
  • @AlterMann - 不,strstr()。我建议使用两种方法来验证每个字符串的输入(即strlen() 和strstr())将是解决 OP 所遇到问题的一种方法。实际上,在处理字符串时,假设通常是危险的,双重检查总是一个好主意。

标签: c string structure strcmp


【解决方案1】:

来自fgets的文档:

在找到换行符、文件结尾或错误时停止读取。 保留换行符(如果有)。

这意味着fgets 将不会从读取字符串的末尾删除最后的'\n'。因此,您的字符串是:

  1. “丹·布朗”
  2. “丹·布朗”
  3. “丹·布朗\n”

他们不相等。

这是使用fgets 时非常常见的问题。这就是为什么我通常更喜欢scanf,像这样:

char buffer[BUF_LEN];
char format[16];
int scanf_result;

sprintf(format, "%%%u[^\n]", BUF_LEN);
//....
do
{
  //TODO: Ask for input
  scanf_result = scanf(format, buffer);
  switch (scanf_result)
  {
    case -1: //TODO: Print error message and exit
    case 0: //TODO: Print error mesage and break
  }
  //Discard remainings of buffered input line
  while (getchar() != '\n') {;}
} while (1); //Ugly, but plain

否则,您可以将fgets 与以下内容一起使用:

int buf_len;

//TODO: Ask for input
while (fgets(buffer, BUF_LEN, stdin) == NULL)
{
  //TODO: Check and handle error
}
buf_len = strlen(buffer);
//Remove trailing '\n', if present
if (buffer[buf_len - 1] == '\n')
{
  buffer[--buf_len] = '\0';
}

尽管它更简单,但我不喜欢第二种方法,因为strlen 会再次扫描字符串以确定其长度。在大多数情况下,这不是性能问题,我会避免它,因为我有自己的心理问题。

【讨论】:

  • 如何去除流浪\n?
  • @xmpirate str[strlen(str)-1] = '\0'
  • @Giulio Franco:+1,根据您提到的文档,如果有的话,换行符会被保留。不检查buffer[--buf_len] = '\0'; 是否真的是\n 不危险吗?我的意思是,它可能不是新线。我一直在检查它
  • @TheMask 是的,你是对的。这很危险。正如我所写,我从未真正使用过它。
  • strlen() 可以返回零:if (buffer[buf_len - 1] == '\n') -->>if (buff_len && buffer[buf_len - 1] == '\n') 不太重要:buff_len 应该是 size_t,而不是 int。
【解决方案2】:

您应该验证您的输入。有时需要不止一种方法。在这里,我使用strlen()和strstr(),因为如果长度为==,并且存在子字符串,那么字符串ARE相等。所以,在得出结论之前,尝试这样的事情来验证输入字符串是你想要的:

注意:枚举当然不是必需的,但在这里包含以增加输出示例的清晰度。

enum    {
    SAME,     //0
    NOT_SAME  //1
}

void delete(struct books *list,char author[],char name[],int n)
{
    int i,a, len1, len2;
    A = NOT_SAME;
    len1 = strlen(list[0].author);
    len2 = (list[5].author);
    if(strstr(list[0].author,list[5].author) && (len1==len2)) a = SAME;
    printf("%d\n",a);              


    a = NOT_SAME;
    len1 = strlen(list[0].author);
    len2 = (author);
    if(strstr(list[0].author,author) && (len1==len2)) a = SAME;
    printf("%d\n",a);              

}    

【讨论】:

    【解决方案3】:

    通过逐个字符打印来检查第二个字符串。

    尤其是author 字符串。

    for(i=0; i < strlen(list[0].author);i++)
    {
       if(list[0].author[i]!=author[i])
       {
         printf("this is position is not matching\n",i+1);
         //try to print characters and also print ascii characters.
         break; 
       }
    
    }
    //or simply try to use strncpy() 
    

    【讨论】:

    • 他在问为什么strcmp(list[0].author,author); 没有打印0。
    • @Kunal 这里给出的模糊答案是它们不相等,否则代码会产生 0 的结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-15
    • 2013-03-27
    • 2012-08-15
    • 1970-01-01
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多