【问题标题】:Simple String Program in C - Not able to print the stringC中的简单字符串程序 - 无法打印字符串
【发布时间】:2014-01-21 22:16:38
【问题描述】:

我无法打印字符串。需要一些关于我做错了什么的帮助,以及在这些情况下最好的方法的一些见解。

#include<stdio.h>
#include<string.h>

void getName(char *name);

int main()
{
    char name[256];
    getName(name);
    printf("Name = %s\n", name);
    return 0;
}

void getName(char *name)
{
    char line[256];
    printf("Please enter your name! \n");
    gets(line);
    name = (char *) malloc(strlen(line));
    strcpy(name, line);
}

【问题讨论】:

标签: c string


【解决方案1】:

我做错了什么

其他人已经指出了一些错误,但还没有人给出正确的解决方案

您的代码天生就容易受到缓冲区溢出的影响。 gets() 函数不允许您指定缓冲区大小,因此如果输入超过 256 个字符,这将超出数组的范围。这很糟糕。

你应该做的是

  1. 不要为此使用单独的函数(因为在这种特殊情况下它没有任何好处),并且
  2. 在您的阵列上调用fgets()

#include <stdio.h>

int main()
{
    char name[256];
    fgets(name, sizeof name, stdin);
    printf("Name = %s\n", name);
    return 0;
}

此外,如果您考虑过动态内存分配:

  1. Do not cast. It's a deadly sin.

  2. 检查malloc()的返回值。

  3. 您将仍然想要跟踪缓冲区大小;这样的功能怎么样?


#define NAME_LENGTH 256

char *getName(void)
{
    char *buf = malloc(NAME_LENGTH);
    if (buf == NULL) {
        return NULL;
    }

    fgets(buf, NAME_LENGTH, stdin);
    return buf;
}

但是,正如我在 cmets 中提到的,在这种情况下,您根本不需要动态内存分配。

【讨论】:

  • 在推荐从gets() 切换到fgets() 时,最好指出当fgets() 读取整个输入行时,它不会丢弃'\n'在末尾。处理 '\n' 是微不足道的,是的,但你必须先知道它在那里。而且您不能指望仍在使用gets() 的人在不警告他们的情况下意识到差异。
【解决方案2】:

你不需要这样做,把它注释掉:

name = (char *) malloc(strlen(line));

您已经传入name 的缓冲区。您不需要分配第二个缓冲区。

此外,您没有在分配中添加 1 来说明空终止符,但这无论如何都无关紧要,因为无论哪种方式都不需要分配。

实际上,您可以将gets 直接转换为name 并去掉line 中间人。

【讨论】:

  • 如果我想动态分配内存怎么办?
【解决方案3】:

您的getname() 过于复杂 - 它只需要:

void getName(char *name)
{
    printf("Please enter your name! \n");
    gets(name);
}

请注意,gets 被广泛认为是unsafe function to use,您应该尝试养成改用fgets 的习惯。

【讨论】:

  • 不,它必须是fgets(name, size, stdin);(其中size 是缓冲区的大小)。 gets() 函数很危险且已弃用。
  • 永远不要使用gets()。用户 fgets() 代替。它非常不安全。见人得到。
  • PaulR 你的宝宝刚刚踩到了雷区。
  • @anansharm 然后char *line = malloc(SOME_SIZE); fgets(line, SOME_SIZE, stdin);。但在这种情况下,您实际上并不需要动态内存分配。
  • 通常您会在 main() 中动态分配并将指针传递给 getname。然后,当不再需要指针时,由 main 最终释放指针。
【解决方案4】:

我知道指针对于初学者来说可能很复杂。所以,忘记指针。您希望以下代码应该如何运行?

void change(int a)
{
   a = 10;
}

int main()
{
    int a = 20;
    change (a);
    printf("%d", a);  // It prints 20
}

(如果您确实理解了上面的代码,请继续阅读。否则,请阅读有关函数和变量范围的内容。)

您的代码具有基本相同的结构,只是您有一个 char *name,而不是 int a。请注意,您在此处有两个不同的 name 标识符。一个是 getName 的参数,另一个是 main 中定义的常量指针(数组标识符)。更改函数的参数值不会更改调用者参数的值。

【讨论】:

  • 然而,这不是 OP 的问题。问题是指针 is 在函数内发生了变化,所以gets() 不会写入原始数组而是写入其他地方。
  • 是的,这是 OP 的问题。并且 a 的值也在函数内发生了变化:)
  • 这仍然不是问题。而且我知道函数是如何工作的,不要教我 C。请阅读问题。
  • 哦,讽刺。好像我不知道发生了什么以及应该改变什么以使程序正常工作。
  • 1- 明白我是根据您的评论而不是您的知识来回答的。 2-我使用一个简单的示例作为类比来指出 OP 在提供的代码中所犯的重要错误。该示例解释了为什么在 getName 中动态分配的指针“name”不能被 main 中调用的 printf 函数访问。它还解释了为什么数组地址没有更改为动态分配的内存。我相信这些是 OP 代码中的主要问题。现在您有 2 个选择:1-争论为什么它们不是 OP 的问题。 2-否决我的答案。吹牛不是其中之一。
猜你喜欢
  • 1970-01-01
  • 2016-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-25
  • 1970-01-01
  • 2015-11-16
相关资源
最近更新 更多