如何在C语言中从char[]复制几个字符到char*中?

3

你好!

我正在尝试将char[]中的一些字符复制到char*中。我只想要从索引6到(消息长度-9)的字符。

也许代码示例可以更好地解释我的问题:

char buffer[512] = "GET /testfile.htm HTTP/1.0";
char* filename; // I want *filename to hold only "/testfile.htm"

msgLen = recv(connecting_socket, buffer, 512, 0);
strncpy(filename, buffer+5, msgLen-9);

任何回复都会很有帮助!

我认为你的意思是“strncpy(filename...”,而不是“strncpy(file”。 在你的代码中,file不是一个声明的变量。 - abelenky
5个回答

10

我猜你的意思是...

strncpy(filename, buffer+5, msgLen-9);

问题在于你没有分配任何内存来保存你要复制的字符。 "filename" 是一个指针,但它没有指向任何东西。
要么只声明
char filename[512];

或者为新名称分配一些内存(并且不要忘记free()...)

您的代码中使用strncpy()存在一些问题。

  • buffer+5指向字符串中的第六个字符(即“T”),而您说您想要反斜杠。
  • 最后一个参数是要复制的最大字节数,因此应该是msglen-13。
  • strncpy()不会对复制的字符串进行空终止处理,因此您需要手动完成。
  • 此外,从可读性的角度来看,我更喜欢

    strncpy(filename, &buffer[4], msgLen-(9 + 4));

&buffer[5]是数组中第五个位置的字符的地址。这只是个人喜好。

还值得指出的是,“recv”的结果可能是一个字节或512个字节大小。它不仅会读取一行。您确实应该循环调用recv,直到您获得要操作的完整行。


实际上,当我使用 strncpy(filename, &buffer[4], msgLen-(9 + 4));, filename 包含 "/testfile.htm H",但是当我使用 strncpy(filename, &buffer[4], msgLen-(9 + 6)); 时,它完美地工作了。 再次感谢! - Göran Lilja
@petsson - 这可能是因为你的“recv()”调用返回一个带有换行序列结尾的字符串。你应该有一种更健壮的方法来检测文件名的开始和结束。 - Roddy
是的,Roddy和我的答案都依赖于您在单个接收调用中输入套接字的确切格式。 - Mehrdad Afshari

5

首先,你应该为filename分配一个缓冲区。下一个问题是你的偏移量。

char buffer[512] = "GET /testfile.htm HTTP/1.0";
char filename[512]; // I want *filename to hold only "/testfile.htm"

msgLen = recv(connecting_socket, buffer, 512, 0);
strncpy(filename, buffer+4, msgLen-4-9); 
//the first parameter should be buffer+4, not 5. Indexes are zero based.
//the second parameter is count, not the end pointer. You should subtract
//the first 4 chars too.

同时,您应确保在字符串结尾添加一个null,因为strncpy不会这样做。

filename[msgLen-4-9] = 0;

您可以使用memcpy代替strncpy,因为您只想复制一些字节:
memcpy(filename, buffer+4, msgLen-4-9);
fileName[msgLen-4-9] = 0;

无论哪种情况,确保您验证输入。您可能会从套接字收到无效的输入。

strncpy是否也不会有空终止符?他应该在结尾加上filename[msgLen-4-8] = '\0'; - Paul Tomblin
哈哈!我刚刚在编辑问题时加入了这个注释。当我发布它时,我注意到了你的评论!真是巧合! - Mehrdad Afshari
我看到了Paul的评论,刚把它加到我的答案里...哎呀。 - Roddy

1

你的示例代码有这一行:

char* filename;

这是一个未初始化指针 - 它没有指向任何位置,并且没有被任何存储支持。您需要为它分配一些内存,例如使用 malloc()(并在完成时记得使用free()),或者在这种情况下,您可能只需将其声明为字符数组,例如:

char filename[SOME_BUFFER_SIZE];

在堆栈上声明数组的优点是,当您完成使用它时,无需显式释放它。

从根本上讲,C中的数组只是隐藏指针的语法糖,因此您通常可以将char[]视为char*


1

您尚未为文件名分配任何空间

可以将文件名的声明替换为以下内容之一:

char filename[512]

或者(可能更好的选择)为文件名留出足够的空间

filename = (char *)malloc(msgLen - 9  - 6 + 1 ); /* + 1 for the terminating null */

你不需要写(char *)malloc。只写malloc就可以了。但是指定一下也无妨 :) - Filip Ekberg
是的,我更喜欢在这些事情上表述得更明确 :) - The Archetypal Paul

0

你还没有为文件名分配任何内存空间。

它是一个指针...但在初始化之前,它指向一些随机的内存区域。

你需要为文件名分配内存。正如Roddy所说,你可以声明文件名为512字节。或者你可以:

filename = (char*)malloc(512*sizeof(char)); 

(注意:sizeof(char)不是必需的,但我认为有助于澄清所分配的确切内容)
在这个语句之后,文件名是指向已分配内存的指针,您可以自由使用它,包括从缓冲区复制数据到它。如果您仅复制了有限的区域,请确保将文件名以null结尾。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接