【问题标题】:Make a function that reads (string) input制作一个读取(字符串)输入的函数
【发布时间】:2018-01-28 18:50:48
【问题描述】:

我是编程新手,我的任务是制作一个读取名称的函数。由于某种原因,以下 'solution' 不起作用,并且输出总是带有奇怪的 chinese? 字符。什么地方出了错?

#include <stdio.h>
#include <stdlib.h>

void input(char* a);

int main()
{
    char name[8];

    input(&name);

    printf("%s", name);

    return 0;
}

void input(char* a)
{
    char buff[8];

    scanf("%s", buff);

    *a = buff;
}

【问题讨论】:

  • 你陷入了经典的菜鸟错误之一 - 试图在函数之外使用 local*a = buff; 确实 not 复制字符串!)
  • @YePhIcK 那么正确的方法是什么?也许使用双指针(void input(char** a);)?
  • 除了这里所说的一切,考虑让buff/name数组大于8。也许10-20。它可能是未来错误和问题的来源。我自己的名字比那个长:)
  • 一个 8 字节的缓冲区正在自找麻烦。 scanf 在自找麻烦。很多这不过是麻烦。使用read 可以限制从输入中读取的数据量。 scanf 可以而且会在数据放不下时爆炸。

标签: c


【解决方案1】:

我认为问题出在你的

    *a = buff;

声明,因为buff 在您的功能之外没有生命。所以它的记忆会丢失..所以尝试以这种方式使用buff是不安全的......

[ 但是正如@pablo 所指出的,*a = buff; 会做的是复制buff 的地址并将其放入分配给a 的内存中,这确实不是您想要做的。 ]

下面应该可以工作并且确实在你的函数中包含return

#include <stdio.h>
#include <stdlib.h>

void input(char* a);

int main()
{
    char name[8];

    input(&name);

    printf("%s", name);

    return 0;
}

void input(char* a)
{
   // char buff[8];

    scanf("%s", a);

  //  *a = buff;
    return;
}

另一点是检查您是否确定名称只有 8 个字符长...为什么不将其设置为 50 个字符?

【讨论】:

  • 你的第一句话不太正确(我知道这是OP的意图),但是*a = buff正在分配buff指向的地址在a指向的内存中。
  • input() 返回类型是void 类型那么为什么return 最终在input() 函数中。
  • @achal - 看看stackoverflow.com/questions/9003283/… 有一个完整的问题专门讨论这个问题是否来自 void 函数
【解决方案2】:

首先,您应该将数组传递给函数input(),而不是其地址。其次,将scanf("%s", buff) 替换为scanf("%s", a)。这会将字符串直接存储在您传递给函数的数组中。

所以,固定的代码应该是这样的:

#include <stdio.h>
#include <stdlib.h>

void input(char* a);

int main(void)
{
    char name[8];

    input(name);

    printf("%s\n", name);

    return 0;
}

void input(char* a)
{
    scanf("%s", a);
}

您的代码不起作用的原因是,您尝试将本地数组buff 的地址分配给您传递给函数的数组的第一个元素。这甚至不应该编译,否则编译器必须发出警告!如果您的编译器允许它在没有任何这些的情况下通过,那将是一场灾难。

最后,main 函数应声明为int main(void)int main(int argc, char **argv)

【讨论】:

  • 我的编译器实际上会发出警告。老实说,我从未见过 main(void)概念,包括在许多书籍和网上。
  • @atru int main(void) 是 3 种可能的“主要”组合之一。如果您的编译器对此发出警告,则说明您的编译器有问题。你用的是哪个编译器?
  • @Pablo 我明白了,我只是质疑 int main(void) 的必要性,它优于 int main()。第三个不使用参数也没有多大意义。不幸的是clang,但我很确定我也只有在gcc上有警告..
  • int foo();int bar(void) 的区别在于你可以将参数传递给foo,而bar 编译器不会让你传递参数。
【解决方案3】:

*a = buff; 不会将buff 复制到a。使用strcpy()

strcpy(a,buff);

完整代码:

void input(char* a);
int main()
{
        char name[8];
        //input(&name);/** no need to pass & bcz name itself represents address */
        input(name);
        printf("[%s]", name);
        return 0;
}
void input(char* a) {
        char buff[8];
        scanf("%s", buff);
        //*a = buff; /* not valid **/
        strcpy(a,buff);
}

【讨论】:

    【解决方案4】:

    这个函数有问题:

    void input(char* a)
    {
        char buff[8];
    
        scanf("%s", buff);
    
        *a = buff;
    }
    

    buff 是局部变量,仅在 input() 运行时有效,所以 返回这个变量是错误的。

    *a = buff; 也是错误的。 *aa[0] 相同,表示它是一个 charbuffchar 的数组,因此您正在分配一个指向数组的指针 charchar 变量。这听起来不对,它是把苹果放进去 橘子盒。实际上发生的事情是您正在分配地址 在a 指向的内存中,由buff 指向。 你的编译器应该已经警告你了,不要忽略 编译器警告,它们是为了帮助你,而不是惹恼你,

    void input(char *a)
    {
        scanf("%s", a);
    }
    

    应该是正确的函数。

    在做

    char name[8];
    
    input(&name);
    

    错了,虽然name&amp;name的地址会一样,但是 他们会有不同的类型。 name 衰减成一个指针,所以它是一个 char*。但是&amp;name 是指向char 数组的指针,这是一种不同的类型。 编译器应该给你这样的警告:

    警告:从不兼容的指针类型传递 bar 的参数 1
    注意:预期为char *,但参数类型为char (*)[8]

    正确的调用是:

    input(name);
    

    不过,通常存在一个大问题:您只声明了 8 个空格 缓冲。如果名称超过 7 个字符,您将有一个缓冲区 溢出。我建议不要使用scanf,而是使用fgets,因为 在这里,您可以更好地控制输入和内存边界。

    char name[30];
    fgets(name, sizeof(name), stdin);
    name[strcspn(name, "\n")] = 0; // removing possible newline
    

    scanf 并不总是易于使用。名称可以很长并且可以包含空格。 特别是对于初学者来说,这可能很棘手。 fgets 更容易使用。

    【讨论】:

      【解决方案5】:

      您不需要传递name 的地址,因为它是一个字符数组。当您在input() 中进行复制时,您应该使用strcpy。以下代码有效:

      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      
      void input(char* a);
      
      int main()
      {
        char name[8];
      
        input(name);
      
        printf("%s", name);
      
        return 0;
      }
      
      void input(char* a)
      {
        char buff[8];
      
        scanf("%s", buff);
      
        strcpy(a, buff);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-03-26
        • 1970-01-01
        • 1970-01-01
        • 2018-07-21
        • 2017-12-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多