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

Do I add +1 to memory allocation in function after removing newline character in main?

提问人:Shar'Dama Ka 提问时间:1/26/2021 最后编辑:Shar'Dama Ka 更新时间:1/27/2021 访问量:419

问:

如果我提示用户提供文件名作为输入,然后检查并删除换行符,在分配内存时我是否仍然需要添加换行符,因为使用 strlen 并且它计算没有最后一个字符的字符?+1strlen(filename)

或者没有必要,因为我删除了它?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);
C 函数 malloc strlen

评论

0赞 Vlad from Moscow 1/26/2021
如果要复制指针文件名指向的字符串,则应编写 char *file = malloc(strlen(filename) + 1);
4赞 paddy 1/26/2021
目前尚不清楚您是否在询问在删除换行符之前是否采用了字符串长度。您从不调用该函数,因此不清楚其目的是什么。基本上,这是令人困惑的。请记住这一点:如果通过以 null 结尾字符串来“删除”字符,则后续调用 将返回字符串的新长度。如果需要为字符串分配内存,则必须足以存储字符串及其 null 终止符。因此,如果您打算使用以 null 结尾的字符串,则必须将 1 添加到任何长度上。wczytaj_macierzstrlen
0赞 Nate Eldredge 1/26/2021
需要一个最小的可重现示例。但也要记住,返回的字符串不能保证以换行符结尾,因此无论长度是否存在,您最好正确处理长度。fgets
0赞 Shar'Dama Ka 1/26/2021
我试图使它最小化,正如上一篇文章中的人所说的那样,当我复制整个代码时(当时它不是一个很长的程序),所以我试图只给出手头问题的最重要的部分,猜得太少了。对不起@paddy,我编辑了我的帖子并添加了函数调用,但我只是调用给出参数的函数,第一个是文件名,另外两个是矩阵维度,也是由用户给出的,通过使用 main 中的 scanf。但我想你回答了我的问题,如果我理解正确的话,我仍然需要添加一个字符。
4赞 paddy 1/26/2021
好的,感谢您的编辑。现在你只是在泄漏内存。为什么不首先呢?并制作参数,因此其目的很明显。fopen (filename, "r");const char*

答:

0赞 Arthur Bacci 1/27/2021 #1

这回答了你的问题吗?

#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", filename, 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;
}

1赞 Steve Summit 1/27/2021 #2

为字符串分配内存时,必须始终分配比字符串长度多一个字节。该额外字节用于终止字符。'\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