c - 如何传递对字符串的引用?

标签 c

我读过的关于 scanf、gets 和 fgets 的所有内容都表明它们是有问题的;带有空白、溢出或复杂性。我正在学习 C 类(class)简介,因为我有足够的 Java 和其他语言编程经验,因此我有信心这样做,所以我决定创建自己的函数来使用 getchar()getchar() 函数。我的代码的相关部分如下:

bool get_string (char prompt[], char* string)
{
    printf(prompt); // Prompt the user

    // Ensure string is allocated to store the null character and reset it if it has been initialized
    do { string = (char*)malloc(sizeof(char)); } while (string == NULL);

    int index = 0;
    char place = getchar();
    while (place != '\n') // Obtain all characters before endl
    {
        string = (char*)realloc(string, sizeof(string) + sizeof(char)); // Create room in the array
        if (string == NULL) return false; // Ensure realloc worked correctly
        string[index++] = place; // Place the new string in the second to last index
        place = getchar();
    }
    string[index] = '\0'; // Append the null character at the end

    return true; // Operation succeeded
}

通过测试和调试,我设法弄清楚:

  1. 我的函数在本地符合规范,参数string保存输入的字符串。
  2. 我在 main 方法中使用的 char* 指针没有被更改。调用我的输入函数后,该指针的取消引用保持与其初始值相同。

我的印象是,因为我传递了一个指向函数的指针,所以它会将参数视为引用。事实上,这就是我在类里面所教的。任何见解都会有所帮助。

如果出现以下情况,将获得奖励积分:

你可以告诉我为什么它不允许我释放 main 中的 char* 指针。 (也许是因为它尚未通过同一问题分配?)

我还做错了什么,例如多次调用 realloc?

注意:我使用 MSVC C89 编译器并定义 bool、true 和 false 预编译。

最佳答案

I was under the impression that because I was passing a pointer to the function it would treat the parameter as by reference. In fact, this is what I was taught in the class. Any insight can help.

C 中没有引用。您传递的每个参数都是按值

因此:

void foo(int a) {
  a = 21;
  // a == 21 for the rest of THIS function
}
void bar(void) {
  int x = 42;
  foo(x);
  // x == 42
}

同样适用:

static int john = 21;
static int harry = 42;
void foo(int * a) {
  a = &john;
  // a points to john for the rest of THIS function
}
void bar(void) {
  int * x = &harry;
  foo(x);
  // x still points to harry
}

如果您想通过参数更改指针,那么您需要将指针传递给该指针:

static int john = 21;
static int harry = 42;
void foo(int ** m) {
  *m = &john;
}
void bar(void) {
  int * x = &harry;
  foo(&x); // passing the address of x by value
  // x now points to john
}

What else I am doing wrong, such as calling realloc too many times?

printf(prompt);

安全问题:尝试将 "%s" 等内容作为 prompt 的值。最好使用 putsprintf("%s", Prompt)

do { string = (char*)malloc(sizeof(char)); } while (string == NULL);

这可能是一个无限循环。如果malloc失败,立即再次调用它不会改变任何东西。另外:不要强制转换 malloc 的返回值。此外,sizeof(char)定义等于1

int index = 0;

对于索引,请使用size_t

char place = getchar();

getchar 返回 int 是有原因的,即能够检查 EOF,您...

while (place != '\n')

...不,但应该!

string = (char*)realloc(string, sizeof(string) + sizeof(char));

不要转换返回值,sizeof(string) 并没有按照你想象的那样做,它是一个编译时常量(在 64 位上可能是 8系统)。

if (string == NULL) return false;

内存泄漏,因为...

If there is not enough memory, the old memory block is not freed and null pointer is returned.

[Source]


这是我在 C 中读取一行的方法:

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

char * readline(char const * const prompt) {
  char buffer[10];
  char * string = malloc(1);
  if (string == NULL) {
    return NULL;
  }
  // The accumulated length of the already read input string.
  // This could be computed using strlen, but remembering it
  // in a separate variable is better, performancewise.
  size_t accumLength = 0;
  string[0] = '\0';
  printf("%s", prompt);
  while (fgets(buffer, 10, stdin) != NULL) {
    // To see what has been read in this iteration:
    // printf("READ: |%s|\n", buffer);
    // Compute the length of the new chunk that has been read:
    size_t const newChunkLength = strlen(buffer);
    // Try to enlarge the string so that the new chunk can be appended:
    char * const newString = realloc(string, accumLength + newChunkLength + 1);
    if (newString == NULL) {
      free(string);
      return NULL;
    }
    string = newString;
    // Append the new chunk:
    strcpy(string + accumLength, buffer);
    accumLength += newChunkLength;
    // Done if the last character was a newline character
    assert(accumLength > 0);
    if (string[accumLength - 1] == '\n') {
      // NOTE: Wasting 1 char, possible solution: realloc.
      string[accumLength - 1] = '\0';
      return string;
    }
  }
  // EOF is not an error!
  if (feof(stdin)) {
    return string;
  }
  free(string);
  return NULL;
}


int main(int argc, char ** argv) {
  char const * const input = readline(">");
  printf("---\n%s\n---\n", input);
  return 0;
}

关于c - 如何传递对字符串的引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35351632/

相关文章:

c - 汇编中的 Scanf 和 printf 函数,例如 char* 和 double

c - 如何在c中使用libxml2根据属性对xml文件进行分类

c - 请教关于数组中char的问题

c - 增长(和收缩)内存池

c - 什么是 char i=0x80 以及为什么在位移时没有发生溢出

c - C 变量的内存地址

c - C中扫描语句后执行打印语句

c# - 在类似 StringBuilder 的 C 模块中增加多少缓冲区?

c - 基于字符串比较的单词翻译程序不能正常工作

c - 生成所有重复排列......C 中的非递归