在 main 中删除换行符后,我是否在函数中的内存分配中添加 +1?

问题描述

如果我提示用户提供文件名作为输入,然后检查并删除换行符,在分配内存 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;
}