我读过的关于 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
}
通过测试和调试,我设法弄清楚:
- 我的函数在本地符合规范,参数
string
保存输入的字符串。 - 我在 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
的值。最好使用 puts
或 printf("%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.
这是我在 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/