我有一个功能有两个问题,一个非常阻碍,另一个不是这样。
我正在学习C的过程中,以下(为了便于阅读而减少)主要和findWord函数应该将随机选择的单词存储到wordToGuess'来自.txt文件。
findWord将单词存储到指针' wordToGuess'很好,但我似乎无法从函数中提取它以在主要中使用它。我试着让这个功能成为一个无效的功能。并直接修改wordToGuess'在函数内,并使它成为一个char *返回单词然后被主要使用,无济于事。在任何一种情况下int * wordLength都没有问题,这让我觉得这个问题可能源于对指针或内存分配的潜在误解。
另一个不那么重要的问题是free(wordToFind)以某种方式崩溃整个事情,但我并没有对这个问题感到困惑。
感谢您的帮助。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#define MIN 0
#define MAX 10
#define WORDSIZE 40
char* findWord(char *wordToGuess , int *wordLength);
int main(int argc , char *argv[])
{
int *wordLength = NULL , lengthWord = 0;
char *wordToGuess = NULL ;
srand(time(NULL)); // For rand() in findWord
wordLength = &lengthWord;
printf("\n1: %s\n" , findWord(wordToGuess , wordLength); // Sole purpose of this tester printf is to verify findWord function
return 0;
}
char* findWord(char *wordToGuess , int *wordLength)
{
int wordNumber = 0 , i = 0;
char word[WORDSIZE] = {0};
FILE *wordFile = NULL;
wordFile = fopen("words.txt" , "r");
if(wordFile != NULL)
{
wordNumber = (rand() % (MAX - MIN + 1)) + MIN; // Random number to choose word form words.txt
for(i = 0 ; i < wordNumber ; i++)
{
while(fgetc(wordFile) != '\n'); // Move the cursor to line 'wordNumber'
}
fgets(word , WORDSIZE , wordFile); // Get word from that line
}
*wordLength = strlen(word);
wordToGuess = malloc(*wordLength * sizeof(char));
if(wordToGuess == NULL)
exit(0);
wordToGuess = word;
fclose(wordFile);
// free(wordToGuess);
return wordToGuess;
}
答案 0 :(得分:3)
您的代码存在许多问题。首先,C通过值传递参数,这意味着在将参数传递给函数时会复制它们。所以在一个函数中,你所拥有的只是一个副本,修改副本当然不会修改原文。
C没有通过引用传递 ,但可以使用指针进行模拟。在您的情况下,您必须将指针传递给指针。这可以使用地址运算符&
来完成。当然,您必须修改函数才能将指针指针作为其第一个参数。
在某种程度上,你现在正在使用wordLength
参数, 但是 将它声明为调用函数中的指针,以及指向NULL
的指针,这意味着在函数内取消引用它将导致undefined behavior。
所以有点正确的代码就像是
char* findWord(char **wordToGuess , int *wordLength);
int main()
{
int wordLength = 0;
char *wordToGuess = NULL;
printf("%s\n", findWord(&wordToGuess, &wordLength));
// Note use of address-of operator
}
然后在findWord
函数中,你当然必须取消引用指向字符串的指针,例如
*wordToGuess = malloc(...);
findWord
函数中还有其他错误,就像你重新分配指针而不是复制它一样,这会让你松开你分配的原始指针,并且使其指向局部变量,并在函数返回后无效。而是复制到内存。
findWord
函数中的另一个主要问题是您将一个字节分配给little。请记住,字符串包含的字符数比strlen
报告的字符多一个,这就是字符串终止符'\0'
。分配内存时,必须为此字符添加空间。
答案 1 :(得分:2)
分配时
wordToGuess = word;
你覆盖分配内存的句柄并有效地丢失它。更糟糕的是,一旦从函数返回,就会使wordToGuess
指向超出范围的本地数组。
您为返回的字符串分配内存的想法很好,但您必须复制字符串的内容,而不是字符串地址:
strcpy(wordToGuess, word);
您必须为终止空字符分配一个超过strlen
的字符,该字符也将与strcpy
一起复制。
如果您的系统有strdup
,您可以一次性使用它进行分配和复制。
答案 2 :(得分:2)
首先为字符串分配内存
wordToGuess = malloc(*wordLength * sizeof(char));
然后你立即覆盖指针
wordToGuess = word;
这意味着:
1)wordToGuess现在指向一个函数返回
时无效的缓冲区
2)分配的内存现在是孤立的
你可能想要strcpy
你还必须为尾随'\ 0'分配内存,所以malloc( 1 + *wordLength )
请注意sizeof(char)
每个定义为1
答案 3 :(得分:2)
这不是内存分配问题。 您已使用{0}初始化数组,并尝试使用“=”运算符进行分配。
C中的数组值 NOT 可修改,因此您不能只说:
wordToGuess = word;
您可以更改数组的内容,但不能通过执行类似pointer_a = pointer_b的操作,而是使用strcpy,在您的情况下:
strcpy(wordToGuess, word);
或 strcpy_s ,它提供相同的结果,但如果正确指定目标缓冲区的大小,则不会导致缓冲区溢出。
答案 4 :(得分:1)
Yout在这里有两个重要问题
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#define MIN 0
#define MAX 10
#define WORDSIZE 40
char* findWord(int *wordLength);
int main(int argc , char *argv[])
{
int lengthWord = 0;
char *wordToGuess;
srand(time(NULL)); // For rand() in findWord
wordToGuess = findWord(&lengthWord);
if (wordToGuess != NULL)
{
printf("\n1: %s\n" , wordToGuess); // Sole purpose of this tester printf is to verify findWord function
free(wordToGuess); // you should release resources.
}
return 0;
}
char* findWord(int *wordLength) // You don't need to pass wordToGuess as a parameter.
{
int wordNumber = 0 , i = 0;
char word[WORDSIZE] = {0};
char *wordToGuess;
FILE *wordFile = NULL;
wordFile = fopen("words.txt" , "r");
if(wordFile != NULL)
{
wordNumber = (rand() % (MAX - MIN + 1)) + MIN; // Random number to choose word form words.txt
for(i = 0 ; i < wordNumber ; i++)
{
while(fgetc(wordFile) != '\n'); // Move the cursor to line 'wordNumber'
}
fgets(word , WORDSIZE , wordFile); // Get word from that line
}
*wordLength = strlen(word);
//wordToGuess = malloc(*wordLength * sizeof(char)); // this is wrong
wordToGuess = malloc(*wordLength + 1); // sizeof(char) equals 1 always
if(wordToGuess == NULL)
exit(0);
// wordToGuess = word; this line is wrong, it should be
memcpy(wordToGuess, word, *wordLength);
wordToGuess[*wordLength] = '\0';
fclose(wordFile);
// free(wordToGuess);
return wordToGuess;
}
您应该始终为null
终止字节分配空间,并且您应该了解指针是如何工作的,因为很明显您不会从wordToGuess = word;
了解它们。