【问题标题】:strlen does not return the right lengthstrlen 没有返回正确的长度
【发布时间】:2015-04-08 14:22:58
【问题描述】:

我目前正在使用strlen 方法来计算这个字符串的长度:

56 69 56 4F 74 65 63 68 32 00 2C 00 00 27 6F 23 84 0E 32 50 41 59 2E 53 59 53 2E 44 44 46 30 31 A5 11 BF 0C 0E 61 0C 4F 07 A0 00 00 00 04 10 10 87 01 01

主要问题是遇到 00 时它总是停止,我认为它与 '\0' 混淆了!所以我想知道这种方法是否有替代品,或者你有什么可以解决这个问题的建议。

P.S:我不确定问题是否重复我搜索了相同的问题但找不到令人满意的答案!

编辑:

我的代码:

unsigned char Response[269]={0x00};
unsigned char Response_PPSE[269];


for(i=0;i<=strlen(Response);i++)
sprintf(Response_PPSE+(2*i),"%02X",Response[i]);

strlen 只计算这个字节的长度: 56 69 56 4F 74 65 63 68 32 00

【问题讨论】:

  • 你能告诉我们你的代码吗?
  • 这是一串数字(例如"56 69 56 4F 74 ..."),还是一个char数组,值为0
  • “我认为它与'\0' 混淆了!”没有混乱。它们是同一个东西,一个 ASCII 0 字符。
  • 如果您不想在第一个 0 处停止(这是 strlen() 所做的,以及字符串的长度 表示,在 C 中),如何您是否希望知道何时到达字符串的末尾?
  • 虽然这个问题很幼稚,但我无法想象人们为什么对它反对。这是一个新用户的认真问题。

标签: c strlen


【解决方案1】:
unsigned char Response[269]={0x00};

这会将Response 初始化为由 269 个相同值组成的序列,每个值都为零。请注意,0x000'\0' 都是同一个东西。

strlen(Response)

这实际上是无效的,尽管一些编译器可能允许这样做。 strlen 需要 char* 类型的参数; Responseunsigned char 的数组,转换为unsigned char* 类型的指针。类型不兼容,并且没有隐式转换。您应该收到编译时警告(如果收到,请在您的问题中包含警告)。

如果我们把Response的定义改成:

char Response[269] = {0x00};

然后strlen 调用变为有效——并将返回0strlen 扫描第一个 '\0' 空字符 -- 你已经用空字符填充了 Response

在你的问题的顶部,你说你有一个字符串:

56 69 56 4F 74 65 63 68 32 00 2C 00 00 27 6F 23 84 0E 32 50 41 59 2E 53 59 53 2E 44 44 46 30 31 A5 11 BF 0C 0E 61 0C 4F 07 A0 00 00 00 04 10 10 87 01 01

这与您向我们展示的代码无关。这也是模棱两可的;它是一串十六进制数字和空格:"56 69 56 ...",还是类似于"\x56\x69\x56..."?如果56 69 序列旨在表示您的数组的内容,请更新您的问题以显示创建它的实际代码。

最后:

for(i=0;i<=strlen(Response);i++)
sprintf(Response_PPSE+(2*i),"%02X",Response[i]);

在循环的每次迭代中调用strlen 可能效率很低。 strlen 每次都必须扫描整个字符串以确定其长度。一旦你解决了其他问题,你应该在循环之前调用一次strlen并使用存储的值。

然而,你可能一开始就不想使用strlenstrlen 应用于 字符串。 “字符串”是由空字符(0'\0'0x00)终止的字符序列。您似乎有一个 unsigned 字符序列,其中 0x00 是有效值,而不是终止符。与其使用strlen 来计算数组的长度,不如通过其他方式跟踪长度。

【讨论】:

  • 感谢您的回答!我一定会按照你说的去做,我会与你保持联系以获得结果:)
  • 好吧,我已经将 unsigned char 更改为 char ,但仍然有同样的问题。而上面提到的字符串我就是这样写的,以便向您展示它在哪里停止!
  • @SaraSara:如果我们不知道它实际上是什么样子,那么知道它停在哪里也无济于事。 56 69 56 4F 74 ... 不是字符串的表示形式。请更新您的问题,向我们展示创建字符串的实际代码。如果您的数组包含值为0x560x690x56 等的字节,那么strlen 在遇到第一个0x00 时当然​​会停止; 0x00'\0' 完全一样。
  • 字符串是通过电子支付终端的非接触式接口从卡片创建的!
  • @SaraSara:请参阅我更新答案的最后一段。
【解决方案2】:

00'\0' 是同一个东西。

看起来你可以在一个数据数组中获取数组的长度而不是字符串的长度。 strlen 将扫描数组直到第一个空终止符。任意数组没有等价物,因此您需要自己跟踪它。

【讨论】:

    【解决方案3】:

    到目前为止,我看到的其他答案都围绕着这里的真正问题。这就是你需要了解你正在处理什么样的字符串

    按照历史惯例,C 将字符串表示为 null 终止 字符数组。这是strlen 所期望的那种字符串。但是您的“字符串”包含空字节。所以它不是一个以 null 结尾的字符串,strlen 不会做你想做的事。

    更重要的是,strlen 非常危险,不应该在现代代码中使用。使用 strlen 很容易导致安全漏洞,如果您的程序使用 strlen 来检查通过网络接收的响应,那么您的程序可能会被利用来实现拒绝或服务甚至远程代码执行。

    更安全的选择是strnlen如果你给它正确的大小限制。很难更准确地确定正确的解决方案,因为在您的示例中,正确答案始终是 269,因此实际上没有可测量的可变长度字符串。

    【讨论】:

    • "更重要的是,strlen 非常危险 ..."——我不同意。 strlen 是完全安全的 如果 你可以保证参数指向一个有效的空终止字符串。如果输入是以保证空终止的方式接收的(例如,fgets),它甚至可以是输入数据。
    【解决方案4】:

    你的意思是数组的长度而不是响应的长度,所以你想要 sizeof(Response) 而不是 strlen(Response) - 大概你知道响应是 269 字节长,因为这是卡协议定义的。

    您还需要 Response_PPSE 为 2*269+1 字节长,否则您的 printf 语句将在数组末尾运行。并且您需要设置 Response_PPSE[2*269]=0 以使其成为有效的以空字符结尾的字符串。

    【讨论】:

      【解决方案5】:

      在我创建的应用程序中,我使用以下方法创建了一个自定义“strlen”方法,以便正确计算长度,即使我的数据中间有空字节:

      -我们需要使用除了包含数据的 char *,还有 malloc 的大小。 -我将以下参数传递给方法:第一个参数是char * str,第二个参数是malloc的大小。

      - 方法以相反的方式工作,从 MAX 内存地址(str + 第二个参数的内存地址)到第一个内存大小,while 循环递减最大内存地址,直到达到第一个内存地址,但是这个 while 循环将中断,以防万一到达第一个非 NULL/0 字符。

      -最后我们返回char *的最后一个MAX内存地址和第一个内存地址的差,+1。

      这是我的代码:

      size_t utils_strlen(const char * str, int max) {
          const char * maxs;
          maxs = str + max;
      
          while(str<maxs) {
            if(*maxs!=0) break;
            maxs--;
          }
      
          return(maxs-str)+1;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-10-01
        • 1970-01-01
        • 2012-11-23
        • 2011-05-08
        • 2021-05-28
        • 1970-01-01
        • 2015-12-06
        • 1970-01-01
        相关资源
        最近更新 更多