使用我自己的strcopy函数时变空

时间:2015-08-18 10:38:42

标签: c strcpy

HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost = new HttpPost("http://xx.xx.xx.xx/login.asmx/login");
        httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        HttpResponse response = httpclient.execute(httppost);
        String responseBody = EntityUtils.toString(response.getEntity());


        //saving the file as a xml
        FileOutputStream fOut = openFileOutput("loginData.xml",MODE_WORLD_READABLE);
        OutputStreamWriter osw = new OutputStreamWriter(fOut);
        osw.write(responseBody);
        osw.flush();
        osw.close();

        //reading the file as xml
        FileInputStream fIn = openFileInput("loginData.xml");
        InputStreamReader isr = new InputStreamReader(fIn);
        char[] inputBuffer = new char[responseBody.length()];
        isr.read(inputBuffer);
        String readString = new String(inputBuffer);



        //getting the xml Value as per child node form the saved xml
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        //InputStream is = new ByteArrayInputStream(responseBody.getBytes("UTF-8"));
        InputStream is = new ByteArrayInputStream(readString.getBytes("UTF-8"));
        Document doc = db.parse(is);

        /*DocumentBuilder builder=DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document doc=builder.parse(fIn, null);*/
        NodeList root=doc.getElementsByTagName("root");




        for (int i=0;i<root.getLength();i++) {
            loginStatus = "" + ((Element)root.item(i)).getAttribute("status");
        }


            if(loginStatus.equalsIgnoreCase("Y"))
            {
                NodeList mb=doc.getElementsByTagName("mb");
                for (int i=0;i<mb.getLength();i++) {
                    setMbcode("" + ((Element)mb.item(i)).getAttribute("mbcode"));
                    setMbname("" + ((Element)mb.item(i)).getAttribute("mbname"));
                    branchid  = "" + ((Element)mb.item(i)).getAttribute("branchid");
                    pwd       = "" + ((Element)mb.item(i)).getAttribute("pwd");

                }

任何人都可以解释我的strcopy功能有什么问题吗?但是,如果在void strcopy(char *src, char *dst) { int len = strlen(src) - 1; dst = (char*)malloc(len); while(*src){ *dst = *src; src++; dst++; } *dst = '\0'; } int main() { char *src = "hello"; char *dst = ""; strcopy(src, dst); printf("strcpy:%s\n", dst); return 0; } Output: strcpy: malloc,我的输出正确无误。困惑,因为malloc只在堆中分配内存吗?

6 个答案:

答案 0 :(得分:5)

在你的情况下,

  strcopy(src, dst);

dst本身是按值传递的。您无法在函数内部分配内存,并希望在调用函数中反映

如果您希望将内存分配到dst内的strcopy(),则需要

  • 将指针传递给dst
  • 或者您也可以return从您的函数中新分配的dst并将其收集回调用者中的dst

    但是,请记住,当您自己分配内存时,free()是您的责任。

否则,您可以将内存分配给调用者(dst)函数内的main(),然后将已分配的dst传递给您的函数以执行复制作业。恕我直言,这种方法与库函数strcpy()更相似,因为API本身不处理目标的内存分配。

注意::那就是代码

 int len = strlen(src) - 1;

您正面临逻辑错误。它应该是

 int len = strlen(src) + 1;

也可以累积终止空值。

答案 1 :(得分:4)

那里有一些问题:

  1. strcopy

    中执行此操作时
    dst = (char*)malloc(len);
    

    您使用新指针覆盖 dst参数中的指针。这对于main中的dst变量 at all 没有任何影响,因为它的,而不是对它的引用,被传递到strcopy。很自然地,当您打印出main&#39; dst所指向的字符串时,它会保持不变,仍然是""

  2. 您没有为副本分配足够的内存。你已经完成了:

    int len = strlen(src) - 1;
    dst = (char*)malloc(len);
    

    分配两个字节太少。您需要+ 1,而不是- 1:源字符串中的字符数(strlen(src)一个用于终止空字符。

    < / LI>
  3. 您正在分配永不释放的内存。

    请记住,它是这样编写的:

      

    As Ye malloc,Thee free

  4. #2可以使用+ 1代替- 1轻松修复。

    #1以多种方式修复:

    1. 您可以让strcopy为副本分配内存,然后不要通过dst,并让它返回它分配的指针。它的文档会说它调用了预期释放的分配。 E.g:

      char * strcopy(char *src) {
        int len = strlen(src) + 1;
        char * dst = (char*)malloc(len);
        for (p = dst; *src; ++p, ++src) {
          *p = *src;
        }
        *p = '\0';
        return dst;
      }
      int main() {
        char *src = "hello";
        char *dst = strcopy(src);
        printf("strcopy:%s\n", dst);
        free(dst);                      // <== note
        return 0;
      }
      
    2. 您可以写入内存main的{​​{1}}点,但您需要确保分配足够的内容。通常在C中,如果您将缓冲区传递给应该写入缓冲区的函数,您还会传递缓冲区的大小,以便函数知道停止的位置。

答案 2 :(得分:1)

您的代码有两个问题。

首先,您的strcopy()函数会将strlen(src) - 1个字符分配给dst,然后将strlen(src) + 1个字符复制到其中。这给出了未定义的行为。

其次,您的main()按值传递其本地dst(即字符串文字""中第一个字符的地址。更改dst的值{因此{1}}对strcopy()dst的值没有影响。这两个变量(main()main()中)具有相同名称的事实确实如此不要改变它。

答案 3 :(得分:1)

总结其他人的意见和建议,您的代码如下:

void strcopy(char *src, char **_dst) {
  int len = strlen(src) + 1;
  char *dst = malloc(len);
  *_dst= dst;
  while(*src){
    *dst = *src;
     src++; dst++;
  }
  *dst = '\0';
}
int main() {
  char *src = "hello";
  char *dst;
  strcopy(src, &dst);
  printf("strcpy:%s\n", dst);
  return 0;
}

答案 4 :(得分:1)

以下是您要找的内容:

void strcopy(char **src, char **dst) {
  int len = strlen(*src) + 1;
  *dst = (char*)malloc(len);
  int j;
  for(j=0;j<strlen(*src);j++)
  {
    dst[j] = src[j];
  }
  dst[j] = '\0';
}

int main() {
  char *src = "hello";
  char *dst = "";

  strcopy(&src, &dst);
  printf("strcpy:%s\n", dst);
  return 0;
}

答案 5 :(得分:0)

函数参数是函数的局部变量。函数处理其参数的副本。因此,函数中参数的任何更改都不会影响相应参数的原始值。

例如,函数strcopy

中的此语句
dst = (char*)malloc(len);

不会更改main中定义的参数dst

char *dst = "";

当函数应该处理已经分配的数组时,如果你想写一个名为strcopy的函数。否则,如果函数本身创建了源字符串的新副本,则该函数应该被命名为例如strdup

此外,您的函数是错误的,因为它可以尝试在源字符串为空时分配具有负内存大小的内存,因此strlen(src)等于0.并且无论如何它分配的内存少于它。必需的。

int len = strlen(src) - 1;
dst = (char*)malloc(len);

该功能可以通过以下方式定义

char * strcopy( char *dst, const char *src ) 
{
    char *p = dst;

    while ( ( *p++ = *src++ ) );

    return dst;
}

并调用

int main( void ) 
{
    char *src = "hello";
    char dst[6];

    printf( "strcpy:%s\n", strcopy( dst, src ) );

    return 0;
}

还要考虑到您不能在C(和C ++)中更改字符串文字。任何改变字符串文字的尝试都会导致程序的未定义行为。

因此,您可能不会声明变量dst,例如

char *dst = "A string literal";

并调用函数strcopy传递dst作为上述程序中的第一个参数。

如果要创建源字符串的副本,则可以按以下方式定义该函数

char * strdup( const char *src ) 
{
    char *dst = malloc( ( strlen( src ) + 1 ) * sizeof( char ) );

    if ( dst )
    {
        char *p = dst;
        while ( ( *p++ = *src++ ) );
    }

    return dst;
}

并调用

int main( void ) 
{
    char *src = "hello";
    char *dst;

    dst = strdup( src ) ;
    printf( "strcpy:%s\n", dst );

    free( dst );

    return 0;
}