这个脚本在哪里出错?

时间:2010-08-14 21:40:16

标签: c

  #include <string.h>
  #include <stdio.h>

  char *string = "<aa>RRRR|<aa>SSS|";
  char *cmp = "<aa>";
  char *p1;
  int nlen;

  main()
  {
    while ( p1 = strstr(string, "<aa>")  ) {
    nlen = 0;
    p1 = p1 + 4;
    while ( ( *p1 != '|' ) && ( *p1 != '\0') ) { p1 = p1 + 1; nlen++; };
    p1 = p1 - nlen;
    string = p1 + 1;
    char rr[200];
    strncpy(rr,p1,nlen);
    printf("%s\n", rr);
    }
  }

错误答案:

RRRR
SSSR

2 个答案:

答案 0 :(得分:4)

你缺少一个空字符来终止字符串。来自维基百科关于strncpy的文章。

  

strncpy准确写入给定的字节数,或者只是复制字符串的开头(如果它太长),或者在副本的末尾添加零来填充缓冲区。它被引入C库以处理诸如目录条目之类的结构中的固定长度名称字段。尽管它的名称不是strcpy的有界版本,它不能保证结果是以空字符结尾的字符串。该函数的名称具有误导性,因为strncat和snprintf分别是strcat和sprintf的有界版本。

添加空字符会使您的程序正常工作:

strncpy(rr, p1, nlen);
*(rr+nlen) = '\0';   // this line
printf("%s\n", rr);

我认为您的代码可能存在缓冲区溢出的风险,因为nlen理论上可能大于200.虽然这不是您问题中程序的问题,因为输入字符串太短了。 / p>

您可能还想查看可用于复制包含空字符的字符串的strncat

  

标准C库中一个总是追加一个空字节的替代方法是使用带有最初空字符串的strncat作为目标。

答案 1 :(得分:0)

#include <string.h>
#include <stdio.h>

main()
{
  char *string = "<aa>RRRR|<aa>SSS|"; /*make a copy below because string is const*/
  char *cmp = "<aa>";
  size_t cl = strlen(cmp); /* for shorter code below */

  char *s=strcpy(malloc(strlen(string)+1),string),*t, /* need test malloc-return */
       *last=strstr(s,cmp);
  if( !last ) return free(s),1;
  while( strstr(last+cl,cmp) )
    last=strstr(last+cl,cmp);
  for(t=strtok(s,"|");t;t=strtok(0,"|")); /* set all '|' to '\0' here */
  t=s;
  while( t<=last )
  {
    if( !strncmp(t,cmp,cl) )
      puts(t+cl);
    ++t;
  }
  return free(s),0;
}