【问题标题】:Memory allocation of pointer working for fixed variable assigned string but not for user input string指针的内存分配适用于固定变量分配的字符串,但不适用于用户输入字符串
【发布时间】:2020-09-11 05:35:40
【问题描述】:

给定程序正在处理代码中固定的字符串,例如

char str[100] = "With fixed string this code works"
// Output of the program is "fixed string this code works"

但是一旦我使用str 输入

scanf("%s", &str);

似乎发现内存分配错误,因为在给出输入后代码返回错误值。

完整代码如下

int main (void) {
    char str[100];
    char *p = (char *)malloc(sizeof(char) * str[100]);
    printf("Enter something: ");
    scanf("%s", &str);
    *p = str;
    p = strchr(str, ' ');
    puts(p + 1);

    // Check for the first space in given input string if found then 
    while (*p++)
        if (*p == ' ' && *++p)
            printf("%s", *p);

    printf ("\n\n");

    return 0;
}

不确定在使用scanf 函数输入字符串时动态内存分配是否需要任何其他分配过程

【问题讨论】:

  • 打开所有编译器警告并阅读它们。你应该得到不少。
  • 只是检查一下,您是否尝试从用户那里获取一个字符串,然后打印出第一个空格之后的所有字符?
  • @CodeWash 是的,正是我想做的事情
  • @user7254101 赋值后 p = strchr(str, ' '); p 等于 NULL。
  • 你认为你传递给malloc()的值是什么?请仔细记下 Craig Estey 的回答:您正在传递 在 str[100] 找到的值,我猜这不是您打算做的

标签: c scanf dynamic-memory-allocation fgets c-strings


【解决方案1】:

您的malloc 有错误:

char *p = (char *)malloc(sizeof(char)*str[100]);

让我们先简化一下。


不要投射malloc(参见:Do I cast the result of malloc?):

char *p = malloc(sizeof(char)*str[100]);

sizeof(char)(根据定义)在所有架构上总是为1,无论它占用多少位,所以我们可以消除它:

char *p = malloc(str[100]);

现在我们有了:

char str[100];
char *p = malloc(str[100]);

您有未定义的行为。 str 没有值(即未初始化),并且您传递的是数组末尾过去之一的元素,因此您有未定义的行为。

因此,传递给malloc 的长度参数是随机的。

【讨论】:

    【解决方案2】:

    Scanf %s 只读取一个字符串直到第一个空格然后停止,这可能是导致您出现问题的原因。无论如何,我都会避免 scanf ,这很危险,如果您不熟悉它可能会导致问题。您可以尝试 fgets 从 stdin 读取。看看这是否符合您的要求:

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    #define MAX_LENGTH 100
    
    int main (void) 
    {
        char *str = (char *) malloc (sizeof(char) * MAX_LENGTH + 1);
        bzero(str, MAX_LENGTH + 1);
    
        printf("Enter something: ");
        fgets(str, MAX_LENGTH, stdin);
    
        // Remove the newline
        if ((strlen(str) > 0) && (str[strlen (str) - 1] == '\n'))
        {
            str[strlen (str) - 1] = '\0';
        }
    
        char *p = strchr(str, ' ');
    
        if (p != NULL)
        {
            // Pointing to the space, which we will skip
            p++;
            printf ("%s\n\n", p);
        }
        return 0;
    }
    

    【讨论】:

    • 无需分配内存,无需清除此内存,bzero 是 BSD 特定且已过时,测试 fgets() 是否返回 NULL,如果有则使用 str[strcspn(str, "\n")] = '\0'; 去除换行符.
    【解决方案3】:

    你有四个问题:


    第一:用scanf,应该是这样的:

    scanf("%s",str);
    

    因为str 是一个地址。还要确保scanf 将扫描来自stdin 的字符串,直到它找到空格或换行并且你不想要什么。所以你最好使用fgets(str, 100, stdin);。


    第二个:用malloc,应该是这样的:

    malloc(sizeof(char)*100)
    

    因为str[100] 没有特定值。


    第三:你不应该改变使用malloc分配的内存地址

    malloc函数在堆中分配内存并返回分配的内存地址,所以你不应该这样做p = strchr(str, ' ');因为strchr将返回第一次出现空间的地址(@返回的地址987654335@ 将丢失)。


    第四个:释放使用malloc分配的内存

    您应该使用free 函数释放使用malloc 分配的内存,该函数获取分配的内存地址。

    你的代码应该是这样的:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    
    int main (void) {
        char str[100];
        char *p = malloc(sizeof(char)*100); //Do NOT cast the return of malloc
        printf("Enter something: ");
        fgets(str, 100, stdin); //Use fgets to include the spaces between words 
        strcpy(p, str);//use stcpy to Not change the address of memory allocated
    
        //p = strchr(str, ' '); -->This step will change the address
        //of memory allocated using malloc
        //puts (p + 1);
        /*Instead you can do this*/
        char *c = strchr(str, ' ');
        puts(c+1);
    
        // Check for the first space in given input string if found then 
        char *mem =p;
        while (*p++)
          if (*p == ' ' && *++p)
            printf ("%s", p);
    
        printf ("\n\n");
        free(mem);
    
        return 0;
    }
    

    【讨论】:

    • 它现在为每个检测到的空白打印几个余数。但我的意图是在找到第一个空格后只打印字符串的其余部分
    • 我认为删除while循环后可以实现您想要的,不是吗? :)
    • 将while (*p++) 替换为if(*p++) 使它发挥了我想要的功能。谢谢老兄:)
    • @user7254101 一点也不;)。还可以考虑使用free 函数释放使用malloc 分配的内存。我更新了答案:D。
    猜你喜欢
    • 2017-01-06
    • 1970-01-01
    • 1970-01-01
    • 2013-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-13
    • 2023-01-11
    相关资源
    最近更新 更多