【问题标题】:Can't enter 2 inputs from user with unknown length of char pointer无法从 char 指针长度未知的用户输入 2 个输入
【发布时间】:2020-05-02 13:48:06
【问题描述】:

我试图从用户那里获得 2 个长度未知的字符指针的输入。(处理动态分配内存)但是在使用“空格”输入第一个输入后,它不会等待用户输入第二个输入,它只读取一个单词,然后允许第二个输入。

          char *str1;
          char ch;
          printf("Enter a sentence:(Ex: Computer Engineer)");
          str1 = (char*)malloc(sizeof(char*));
          scanf(" %s", str1);
          printf("Enter a character to search(Ex: g):");
          scanf(" %c", &ch);
          char *result;
          result=mystrchr(str1,ch);
          if(result!=NULL)
            printf("%s",result);
          else
            printf("NULL");

【问题讨论】:

标签: c malloc scanf dynamic-memory-allocation


【解决方案1】:

第二个完全相同的陈述

str1 = (char*) malloc(sizeof(char*));

是多余的、不恰当的和无用的。通过这样做,您分配了str1 指向的另一个内存空间;留下之前分配的空间,因为没有 free()ing 被遗弃但存在于内存中。


char *str1;
str1 = (char*) malloc(sizeof(char*));

通过调用malloc(),您分配的内存大小与指向char 的指针大小相同,在大多数现代系统上通常为4 个字节,而不是存储像"Computer Engineer" 这样的字符串所需的空间。使用此定义,它只能存储3 字符加上自动附加的以字符串结尾的空字符(4 个字符对应 4 个字节)。

通过调用 scanf() 来输入一个长度超过 3 个字符的字符串:

scanf(" %s", str1);

程序将写入超出分配内存的范围,这会调用undefined behavior(就像你的情况很可能发生的那样)。


您需要分配足够的空间来保存提供的字符串 - 对于 f.e. "Computer Engineer" 至少需要 18 个字节(注意 sizeof(char) == 1):

char *str1 = malloc((sizeof(char) * 18);

或者:

char *str1 = malloc((sizeof(*str1) * 18);

请注意,您不能使用 %s 格式说明符输入空格分隔的单词。为此,请改用%[

scanf("%[^\n]", str1);

或者更好的使用更可靠更安全的fgets()

fgets(str1,18,stdin);

如果你想根据用户的输入来分配内存,你需要在分配之前添加另一个输入请求和变量:

int len;

printf("How many characters the string should have?");
scanf("%d",&len);

char *str1 = malloc((sizeof(*str1) * (len + 1));     // +1 element for null character.

printf("Enter a sentence:(Ex: Computer Engineer)");
fgets(str1,len,stdin);

旁注:

malloc 的返回指针不需要强制转换 -> Do I cast the result of malloc?

【讨论】:

  • 我错误地添加了多余的“str1 = (char*)malloc(sizeof(char*));”行,我不想指定输入单词的字符大小。我希望我的程序根据输入的输入动态地创建它自己的内存。
  • @NeverSAYnever 我已将您请求的内存分配的用户确定大小添加到答案中。看看吧。
【解决方案2】:

编程不仅仅是对齐代码行。 C 中的内存分配不是很复杂,但很容易用它编写错误的代码(你做过......)。

这只是错误...错误的代码:

  str1 = (char*)malloc(sizeof(char*));  // Wrong: you allocate a char array with
                                        //  the size of a char pointer: nonsense
  printf("Enter a sentence:(Ex: Computer Engineer)");  // no error here :-)
  str1 = (char*)malloc(sizeof(char*));  // Wrong: the previously allocated array is
                                        //  now leaked: you can no longer free it
  scanf(" %s", str1);                   // What if input is larger than sizeof(char*)?

现在回答您的问题:scanf 读取空白分隔标记。这是一个功能。如果你想要面向行的输入,你应该使用fgets

代码可以是:

#define SIZE 16
size_t size = SIZE;         // initial size of the allocated array
char *str1 = malloc(size);  // sizeof(char) is by definition 1
char ch[2];                 // a trick to read next non blank character

printf("Enter a sentence:(Ex: Computer Engineer)");
char *str = str1;
for(;;) {                                // loop to accept arbitrary length input
    if (NULL == fgets(str, size, stdin)) {
        perror("Input error or end of file");
        return 1;
    }
    if (strchr(str, '\n') != -1) break;   // ok we have a full line
    str1 = realloc(str1, size * 2);
    if (NULL == str1) {
        perror("Could not allocate memory");
        return 1;
    str = str1 + size - 1;                // point after currently got data
    size = size * 2;
}
printf("Enter a character to search(Ex: g):");
scanf("%1s", ch);
char *result = mystrchr(str1,ch[0]);
...

注意:代码未经测试,可能包含拼写错误...

【讨论】:

    猜你喜欢
    • 2021-08-17
    • 2017-03-18
    • 2012-01-20
    • 2016-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多