【问题标题】:Returning String Literal from a function to Another [duplicate]将字符串文字从函数返回到另一个[重复]
【发布时间】:2019-06-07 05:02:28
【问题描述】:

我真的很努力想弄清楚如何将字符串从一个函数返回给另一个函数。请帮我解决这个问题。

从这个函数返回密码作为字符串:

char* password(void) {
  const maxPassword = 15;
  char password[maxPassword + 1];
  int charPos = 0;
  char ch;

  printf(
      "\n\n\n\tPassword(max 15 Characters/no numeric value or special char is allowed):\t");
  while (1) {
    ch = getch();
    if (ch == 13)    // Pressing ENTER
      break;
    else if (ch == 32 || ch == 9)    //Pressing SPACE OR TAB
      continue;
    else if (ch == 8) {    //Pressing BACKSPACE
      if (charPos > 0) {
        charPos--;
        password[charPos] = '\0';
        printf("\b \b");
      }
    } else {
      if (charPos < maxPassword) {
        password[charPos] = ch;
        charPos++;
        printf("*");
      } else {
        printf(
            "You have entered more than 15 Characters First %d character will be considered",
            maxPassword);
        break;
      }
    }
  }    //while block ends here
  password[charPos] = '\0';
  return password;

}

到这个功能(但它不打印):

void newuser(void) {
  int i;
  FILE *sname, *sid;
  struct newuser u1;
  sname = fopen("susername.txt", "w");
  if (sname == NULL) {
    printf("ERROR! TRY AGAIN");
    exit(0);
  }
  printf("\n\n\n\tYourName:(Eg.Manas)\t"); //user name input program starts here
  scanf("%s", &u1.UserName);
  for (i = 0; i < strlen(u1.UserName); i++)
    putc(u1.UserName[i], sname);
  fclose(sname);

//sid=fopen("sid.txt","w");
  printf("\n\n\n\tUserId:(Eg.54321)\t"); //User Id input starts here
  scanf("%d", &u1.UserId);

  printf("%s", password());
}

【问题讨论】:

  • 您基本上是将地址返回给函数结束时超出范围的局部变量。 malloc 或使其成为 static。另请注意,您返回的不是字符串文字。
  • 此代码中没有返回字符串文字。文字是由其值命名的事物,例如 3 表示 3 或 "abc" 表示由“a”、“b”和“c”组成的字符串。函数试图返回 password 的东西是 char 的数组,而不是字符串文字。
  • 旁白:else if (ch == ' ' || ch == '\t')else if (ch == 32 || ch == 9) //Pressing SPACE OR TAB 哪个更容易编码/阅读?

标签: c string


【解决方案1】:

因为char password[maxPassword+1];的生命周期在password函数中,函数完成后自动从内存中删除。

在函数内部定义的未声明为静态的变量是自动的。有一个关键字可以显式声明这样的变量——auto——但它几乎从未使用过。自动变量(和函数参数)通常存储在堆栈中。堆栈通常使用链接器定位。动态存储区的末端通常用于堆栈。

为了解决这个问题,你有一些选择

  1. 您可以从密码函数的参数中获取此变量,然后对其进行更改。

    void password(char password*)

  2. 使用malloc的C动态内存分配

    char *password = malloc(maxPassword+1)

    如果将此方法与printf("%s", password()); 一起使用,则会通过丢失指向已分配内存的指针来故意泄漏内存。可以说,只要指针“a”超出范围,即 function_which_allocates() 在没有释放“a”的情况下返回时,就会发生泄漏。
    你应该使用free() 来释放内存。

char* passwd = password(); printf("%s", passwd); free(passwd); passwd = NULL;

【讨论】:

  • 问题在于对象的生命周期,而不是其标识符的范围。生命周期是在程序执行期间对象存在。范围是在源代码中标识符可见的地方。对象可能在代码执行期间存在其标识符不可见的情况。
  • @EricPostpischil 是的,谢谢。
  • 这是一种方法,但是他不必返回任何东西,所以可以简单地void password(char *password)
【解决方案2】:

char password[maxPassword+1] 是函数的局部变量,您需要像 char *password = malloc(maxPassword+1) 那样为其分配内存或使用全局变量。

还将const maxPassword=15 更改为int maxPassword=15,并将ch=getch() 更改为ch=getchar()

一般来说,我建议阅读一本关于 C 的书,因为您似乎在猜测,而 C 对您没有任何帮助。

【讨论】:

  • ch=getch()ch=getchar() 是使用标准库的一个很好的举措,但 OP 可能需要 getch() 功能,这与 getchar() 不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-30
  • 2023-03-17
  • 2013-04-14
  • 1970-01-01
  • 2016-12-17
  • 1970-01-01
相关资源
最近更新 更多