这是我的第一次发帖问题,我确实尝试寻找解决方案,但是即使我找到了,我也不认识它。
因此,正如标题所述,问题出在此触发的异常“在lab10.exe中的0x0F26372D(ucrtbased.dll)引发异常:0xC0000005:访问冲突读取位置0xCCCCCCC4。
如果有用于此异常的处理程序,则程序可以安全地继续。”,当我进入第-> free(word)行时会发生这种情况。
当我学习malloc时,这确实发生了几次,但我忽略了它-认为还有其他问题。但是现在我发现自己做错了。
程序的重点是-编写结构“ word”。我需要输入句子并将其“切”为单词,然后将每个单词放入struct以及单词中字母的大小和单词的序数。
#include <stdio.h>
#include <string.h>
struct word {
char text_word[50];
unsigned sizee; //number of letters of the word
unsigned number; //ordinal number of the word
};
void cutting_sentence(struct word *p, char *sen) { //sen is sentence
int size_sen, i, j;
size_sen = strlen(sen) + 1; //size of sentence
p = (struct word*)malloc(size_sen * sizeof(struct word));
if (p == NULL) {
printf("\nNot enaugh memory!");
return 0;
}
strcpy(p[0].text_word, strtok(sen, " ,.!?"));
p[0].sizee = strlen(p[0].text_word);
p[0].number = 1;
printf("word:%s \t size:%u \t ordinal number of the word:%u\n",
p[0].text_word, p[0].sizee, p[0].number);
for (i = p[0].sizee - 1, j = 1;i < size_sen;++i) {
if (*(sen + i) == ' ' || *(sen + i) == '.' || *(sen + i) == ','
|| *(sen + i) == '?' || *(sen + i) == '!') {
strcpy(p[j].text_word, strtok(NULL, " ,.!?"));
p[j].sizee = strlen(p[j].text_word);
p[j].number = j + 1;
printf("word:%s \t size:%u \t ordinal number of the
word:%u\n", p[j].text_word, p[j].sizee, p[j].number);
j++;
}
}
}
int main() {
char sentence[1024];
struct word *word;
printf("Sentence: ");
gets(sentence);
cutting_sentence(&word, sentence);
free(word); //here is exception triggered
return 0;
}
答案 0 :(得分:1)
您要更改传递的指针参数的本地值,您需要在其目标位置更改内存,以便调用者发现分配的内存的位置。由于您没有这样做,因此您尝试释放存储在word
堆栈中的局部变量main()
。
要解决的第一件事是不要让变量与类型名称相同,这简直就是邪恶。
然后更改函数原型以传递双指针:
void cutting_sentence(struct word **p, char *sen);
请记住,在使用p
的地方,您现在需要使用*p
或首先分配一个本地(word *)
并在其中包含地址值。
void cutting_sentence(struct word **p, char *sen) { //sen is sentence
int size_sen, i, j;
size_sen = strlen(sen) + 1; //size of sentence
*p = (struct word*)malloc(size_sen * sizeof(struct word));
if (*p == NULL) {
printf("\nNot enaugh memory!");
return; //void cannot return a value
}
以此类推,将p
的每种用法更改为*p
。
然后
int main() {
char sentence[1024];
struct word *words;
printf("Sentence: ");
gets(sentence);
cutting_sentence(&words, sentence);
if (words != NULL)
free(words); //now valid
return 0;
}
答案 1 :(得分:0)
问题比以前讨论的多。
[正如已经指出的],您的第一个参数应为struct word **
。但是,一种更简单的方法是消除它,并将返回类型更改为struct word *
。这样可以使函数中的代码更简单(即,无需对指针进行双重引用)
虽然可以分配与输入字符串中的字符数量一样多的单词结构,但这有点不正常。
一种更好的方法(至少是惯用的,至少是惯用的)是在循环内使用realloc
。
无论哪种情况,都可以通过最后一个realloc
将数组大小调整为仅使用所需的大小。
我认为您扫描sen
以查找定界符的循环过于复杂。只需在循环中使用strtok
即可获得相同的效果,并且复杂度更低。
此外,您没有传递单词数量的 count 。一种方法是在数组中添加一个大小为零的额外元素(例如列表结尾标记)
这是重构版本,应该可以帮助您
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct word {
char text_word[50];
unsigned sizee; // number of letters of the word
unsigned number; // ordinal number of the word
};
struct word *
cutting_sentence(char *sen)
{ // sen is sentence
int curcnt = 0;
int maxcnt = 0;
char *token;
struct word *word;
struct word *words;
while (1) {
token = strtok(sen," ,.!?\n");
if (token == NULL)
break;
sen = NULL;
if (curcnt >= maxcnt) {
maxcnt += 100;
words = realloc(words,sizeof(struct word) * (maxcnt + 1));
}
word = &words[curcnt];
strcpy(word->text_word,token);
word->number = curcnt;
word->sizee = strlen(token);
++curcnt;
}
words = realloc(words,sizeof(struct word) * (curcnt + 1));
// set end-of-list
word = &words[curcnt];
word->sizee = 0;
return words;
}
int
main()
{
char sentence[1024];
struct word *words;
struct word *word;
printf("Sentence: ");
fflush(stdout);
fgets(sentence,sizeof(sentence),stdin);
words = cutting_sentence(sentence);
for (word = words; word->sizee != 0; ++word)
printf("main: number=%u sizee=%u text_word='%s'\n",
word->number,word->sizee,word->text_word);
free(words);
return 0;
}
答案 2 :(得分:0)
以下建议的代码:
stderr
发生错误的文本原因struct word
指针struct word
指针int sizee
更改为size_t sizee
是因为函数:strlen()
返回了size_t
,而不是int
int i
更改为unsigned i
,因为结构字段number
的声明被声明为unsigned
struct word
中的每个字符分配sentence
的实例,这是“过度杀伤力”。如果每个单词都只有一个字符,则最可能的单词数量是。因此,立即可以将分配的内存大小减少一半。计算单词分隔符的循环将导致分配的内存量正确。您可以轻松添加该功能。 strtok()
的方式。即在循环之前先进行调用,然后在循环结束后进行后续调用现在是建议的代码:
#include <stdio.h> // printf(), fgets(), NULL
#include <stdlib.h> // exit(), EXIT_FAILURE, malloc(), free()
#include <string.h> // strlen(), strtok()
struct word
{
char text_word[50];
size_t sizee; //number of letters of the word
unsigned number; //ordinal number of the word
};
// notice the `**p` so can access the pointer in `main()` so it can be updated
void cutting_sentence(struct word **p, char *sen)
{ //sen is sentence
size_t size_sen = strlen(sen); //size of sentence
struct word *wordptr = *p;
wordptr = malloc(size_sen * sizeof(struct word));
if ( !wordptr )
{
perror("malloc failed");
exit( EXIT_FAILURE );
}
unsigned i = 0;
char * token = strtok(sen, " ,.!?");
while( token )
{
strcpy( wordptr[i].text_word, token );
wordptr[i].sizee = strlen( token );
wordptr[i].number = i;
printf("word:%s\t Length:%lu]tordinal number of the word:%u\n",
wordptr[i].text_word,
wordptr[i].sizee,
wordptr[i].number);
token = strtok( NULL, " ,.!?");
i++;
}
}
int main( void )
{
char sentence[1024];
struct word *wordArray = NULL;
printf("Sentence: ");
if( !fgets(sentence, sizeof( sentence ), stdin ) )
{
perror( "fgets failed" );
exit( EXIT_FAILURE );
}
// remove trailing new line
sentence[ strcspn( sentence, "\n") ] = '\0';
cutting_sentence(&wordArray, sentence);
free( wordArray ); //here is exception triggered
return 0;
}
典型的代码运行结果为:
Sentence: hello my friend
word:hello Length:5 ordinal number of the word:0
word:my Length:2 ordinal number of the word:1
word:friend Length:6 ordinal number of the word:2
请注意,“短”字会导致输出不均匀。您可能要纠正它。