被strcmp困惑

时间:2016-07-10 15:50:08

标签: c string strcmp

我有一个非常简单的函数来将表示位串的3字符串转换为十进制数:

int bin3_to_dec(char *bin) {
  int result;

  result=0;
  printf("string: %s\n", bin);
  printf("c0: %c\n", bin[0]);
  printf("c1: %c\n", bin[1]);
  printf("c2: %c\n", bin[2]);

  if ((strcmp(&bin[0], "1") == 0))
    result += 4;
  if ((strcmp(&bin[1], "1") == 0))
    result += 2;
  if ((strcmp(&bin[2], "1") == 0))
    result += 1;
  printf("result: %d\n", result);
  return result;
}

当我运行程序并为此函数提供字符串111时,它应该计算7.而不是它输出:

string: 111
c0: 1
c1: 1
c2: 1
result: 1

为什么不计算正确的值?为什么只有第三个条件成功通过?

7 个答案:

答案 0 :(得分:5)

你的字符串http://localhost/Login/?returnUrl=http://localhost/%23location1等于" 111"真的由四个字符组成 - 即' 1',' 1',' 1',' \ 0'其中第4个字符的值为零,它终止(即结束)字符串。

所以bin是字符串&bin[0]

"111"是字符串&bin[1]

"11"是字符串&bin[2]

所以你的代码实际上做的是:

"1"

只有最后一次比较结果为真,因此 if ((strcmp("111", "1") == 0)) result += 4; if ((strcmp("11", "1") == 0)) result += 2; if ((strcmp("1", "1") == 0)) result += 1; 变为1

答案 1 :(得分:2)

& bin [0]实际上是指向从第0个索引开始的字符数组的指针,即111.因此,您的第一个比较失败。同样的第二个。但是在你的第三次比较中,& bin [2]是从第二个索引开始的字符数组的指针,它是1,因此它将结果加1。所以要使你的代码工作:

你可以检查if(bin[0] == '1') //在这里你比较bin [0]处的字符,它等于1,所以这里条件得到满足。

答案 2 :(得分:1)

if (bin[0] == '1') result += 4;
if (bin[1] == '1') result += 2;
if (bin[2] == '1') result += 1;

请注意& bin [0]与bin

相同

bin [0]是第一个元素

& bin [0]是指向第一个元素的指针,就像bin

一样

答案 3 :(得分:1)

C在遇到空值(即\ 0)之前不检测字符串的结尾。当您将“111”传递给函数时,实际上是将指针传递给一个如下所示的内存块:“111 \ 0”。因此,当您将bin [0]的地址传递给strcmp()时,strcmp将对完整的字符串“111”进行操作。将bin [1]的地址传递给strcmp()时,strcmp对字符串“11”进行操作。只有当你将bin [2]的地址传递给strcmp()时才会得到你期望的行为,因为在这种情况下,内存中的下一个字符是空的。

答案 4 :(得分:1)

您是否尝试将&bin[1](例如)打印为字符串,而不是单个字符?因为strcmp()将会看到它们。

在您执行此操作时,strcmp(&bin[0], "1")显然始终为非零,因为&bin[0]是完整的输入字符串,并且(在我们的示例中)"111"完全不像{{1} }}。字符串一直运行到null终止符。

您可以使用直接字符比较("1"),将字符复制到自己的以空字符结尾的字符串,或者(从属到左侧)破坏性地工作并插入空字符(bin[0] == '1' )在你感兴趣的角色之后。但是你无法将字符串的中间值作为单个字符进行比较。

答案 5 :(得分:-1)

正如其他人所说,你会混淆这些字符串。其中三个是字符串,但java中的字符串是一个字符数组。所以当你的意思是使用& bin [0]的字符串“1”时,你实际上是在比较“111”。为什么?指向字符数组的指针会在此数组中生成一个字符串,该字符串从指针显示的位置开始并持续到结尾。

因此,当你指向第一个字母时,你得到“111”,当你指向第二个字母时,你得到“11”,当你指向最后一个字符时,你得到“1”,这就是为什么你的总和为1。你可以尝试将字符串“1111”作为参数传递,你可以看到你的结果是0的intead为1.

答案 6 :(得分:-1)

您的代码似乎对strcmp()的函数调用感到困惑,这是不需要的,并且对于字符串文字"1"和任何“子字符串”之间的任何比较,它将始终返回非零值在您的代码(&bin[0]&bin[1])中指出,除了one-printable-member-string &bin[2],如果还是"1"。让我们来看看。

正如您在函数原型中正确编写的那样,指向字符数组的第一个元素的指针正在通过值传递给您的调用函数并复制为其参数。这是由指向的数组填充的内存部分的“机制”,如果其“上限”已知,则由被调用的函数可见。 有两种方法可以知道其上限:

  1. char数组大小作为附加参数传递给函数,或
  2. 调用函数中空终止char数组,因此调用函数可以将其解释为字符串,这是您的选择。 被调用函数可以使用strlen()来确定字符串长度(大小),或者逐步执行它,递增计数器,直到达到空字符,并从计数器读取大小。
  3. 如果调用函数已经接收到数组为'0''1'字符的以空字符结尾的字符串,则第二个看起来更实用。

    允许被调用函数(在本例中为int)的返回数据类型的存储容量所允许的最多字符,以澄清问题并简化代码。 调用函数应该防止溢出。

    被调用的函数应该只将每个数组成员的ASCII值与 '1'进行比较,如果相等则转换。 为此,不需要strcmp

    请根据您的帖子查看此演示代码中的评论:

    #include <stdio.h>
    #include <string.h>
    #define BPB 8   //bits per byte
    
    int bin_to_dec(char *bin)            //called function 
    {
      int result=0;  
      int l = (int)strlen(bin);
      for (int i = 0; i < l; i++){
          printf("c%d: %c\n", i, bin[i]);
          if(bin[i] == '1')               //compare value of the i-th element
              result += 1<<(l - i - 1);   //convert to power-of-two and add to the result
          }
      return result;
    }
    
    int main(int argc, char *argv[])      //calling function
    {  
       size_t siz = BPB*sizeof (int); //size for each char to represent one bit
       char s[siz + 1];               //characters, each representing one bit + terminating '\0'
    
       if((argc < 2)||(argc > 2))     //fail-safe check for correct count of arguments
           return 1;
       size_t len = strlen(argv[1]) ; //get length of the input string
       if ( len > siz )               //check against too long input which would cause overflow
           return 2; 
       strncpy(s, argv[1], len);
       s[len] = '\0';                 //appending the terminating null-character
       for(int i = 0; i < (int)len; i++)
           if((s[i] < '0')||(s[i] > '1')) //fool-proof check against 'off-limit' input
               return 3;
    
       printf("decimal: %d\n", bin_to_dec(s));
       return 0;
    }