问题描述
如果我提示用户提供文件名作为输入,然后检查并删除换行符,在分配内存 i 函数时,我是否仍然需要将 +1
添加到 strlen(filename)
,因为使用了 strlen 和事实它计算没有最后一个字符的字符?
或者因为我在 main()
中删除了它而没有必要?
我已经读到不添加 +1 会为字符串分配很少的内存并导致问题,但我读到了关于此事的矛盾内容,希望得到一些澄清。
double** wczytaj_macierz (char* filename,int x,int y)
{
char *file = malloc(strlen(filename) + 1);
sprintf(file,"%s",filename);
FILE *fin = fopen (file,"r");
...
rest of the code
...
int main(void)
char filename[BUFSIZ];
{
printf("\nPlease enter filename,max %d characters.\n",sizeof(filename));
if (fgets(filename,sizeof(filename),stdin) != NULL)
{
if ((p = strchr(filename,'\n')) != NULL)
{
*p = '\0';
}
}
wczytaj_macierz (filename,x,y);
解决方法
当你为一个字符串分配内存时,你必须总是分配比字符串长度多一个字节。该额外字节用于终止 '\0'
字符。
如果您有一个字符串恰好以换行符 \n
结尾,并且您删除该字符,您显然会将字符串缩短一个字符,这意味着您将需要少一个字节的内存来存储它。但与往常一样,存储它仍然需要为 \0
提供空间。
举个例子:
char string[] = "test\n";
int stringlen = strlen(string); // length = 5
char *copy1 = malloc(stringlen + 1); // allocates 6 bytes
strcpy(copy1,string); // this works
char *p = strchr(string,'\n'); // find the \n
if(p != NULL) *p = '\0'; // strip it off
printf("string is now: \"%s\"\n",string);
stringlen = strlen(string); // length = 4
char *copy2 = malloc(stringlen + 1); // allocates 5 bytes
strcpy(copy2,string); // this works also
现在,如果你写了这样的代码:
char string[] = "test\n";
int stringlen = strlen(string);
char *p = strchr(string,'\n');
if(p != NULL) *p = '\0';
printf("string is now: \"%s\"\n",string);
char *copy = malloc(stringlen); // don't have to add 1,// since I just stripped off \n
strcpy(copy,string);
看起来您可以不添加 + 1
。但是任何时候你必须添加注释来解释一些不存在的代码,特别是如果你必须写的注释比它替换的代码更长,这通常表明你已经得到太聪明了,你应该只留下代码。而且,事实上,即使它一开始看起来可以工作,以这种方式编写代码将是非常危险的,因为如果你最终得到一个不以 \n
结尾,这意味着没有什么可剥离的,代码将停止正常工作。
这是否回答了您的问题:?
#include <stdio.h>
#include <string.h>
int main()
{
char filename[10];
printf("\nPlease enter filename,max %d characters.\n",sizeof(filename));
if (fgets(filename,sizeof(filename),stdin) != NULL)
{
printf("%s %d\n",filename,strlen(filename));
if (filename[strlen(filename) - 1] == '\n')
{
filename[strlen(filename) - 1] = '\0'; // Here lies \n
}
printf("%s %d\n",strlen(filename));
}
// If filename was "file\n\0",filename[strlen(filename) - 1] == '\n'
// Now with filename[strlen(filename) - 1] = '\0'
// filename is "file\0\0" that is "file\0".
// strlen("file\n") == 5
// strlen("file") = 4
// strlen(filename) was 5 and now it is 4
return 0;
}