在C中,我有以下函数:
//Get Readability: Coleman-Liau Index Formula: ((0.0588 * Average # of letters per 100 words) - (0.296 * Average # of sentences per 100 words) - 15.8)
string get_readability(float avg_letters, float avg_sentences)
{
//Store as int so that it rounds the resulting index number
int index = (0.0588 * avg_letters) - (0.296 * avg_sentences) - 15.8;
//printf("Index: %i\n", index);//debug
//Return the grade level
if (index < 1)
{
return "Before Grade 1";
}
else if (index > 16)
{
return "Grade 16+";
}
else
{
//Create char array for result in order to concat the index number
char result[8] = "Grade ";
char grade[2];
sprintf(grade, "%i", index);//Convert int to string
strcat(result, grade);
//Convert char array to string in order to return results
string result_str = result;
return result_str;
}
}
当我调用它并将其存储在一个变量中时,它是正确的,我可以立即打印出来,没有任何问题:
//Get reading level
//string reading_level = get_readability(letter_avg, sentence_avg);
string reading_level = get_readability(464.29f, 28.57f);
//printf("%i letters\n%i words\n%i sentences\n%f letter avg\n%f sentence avg\n", letter_count, word_count, sentence_count, letter_avg, sentence_avg);//debug
printf("%s\n", reading_level);
但是如果我在设置变量和打印变量之间执行多个printf语句,那么变量将更改为“”,并且只打印一个空行。
//Get reading level
//string reading_level = get_readability(letter_avg, sentence_avg);
string reading_level = get_readability(464.29f, 28.57f);
//printf("%i letters\n%i words\n%i sentences\n%f letter avg\n%f sentence avg\n", letter_count, word_count, sentence_count, letter_avg, sentence_avg);//debug
printf("\n");
printf("\n");
printf("\n");
printf("%s\n", reading_level);
查找这个问题,似乎问题可能是当函数返回result_str
时,它返回了指向该变量的指针,并且在调用printf几次之后,它被重写了。但是我真的不明白这是怎么发生的,因为我没有用 * 传递任何东西。
1条答案
按热度按时间mgdq6dx11#
你的问题是
首先,
string
类型是CS50所特有的;它不是标准C语言的一部分。C没有实际的 string 数据类型。其次,CS50
string
类型也不是一个实际的 string 数据类型-它是一个 pointer 类型的typedef名称(别名):C语言中的字符串只是一个包含零值终止符的字符值序列-字符串
"hello"
表示为序列{'h', 'e', 'l', 'l', 'o', 0}
。字符串 * 存储 * 在字符类型的数组中,但字符数组也可以存储 * 非 * 字符串的序列(没有0值终止符,或者有多个0值字节)。除非它是
sizeof
、_Alignof
或一元&
运算符的操作数,或者是用于在声明中初始化字符数组的字符串文字,否则类型为“T
的N元素数组”的 expression 将被转换,或“decay”,指向类型为“指向T
的指针”的表达式,表达式的值将是数组第一个元素的地址。当你将数组表达式作为参数传递给函数时,比如上面的转换规则将
arr
替换为指针表达式,这样函数调用看起来更像而函数接收的是指针,而不是数组。这适用于所有数组类型,而不仅仅是字符数组。
所以当你写的时候
你将
result
数组的第一个元素的 * 指针 * 存储到result_str
,而不是它的内容,并通过扩展将该地址返回给调用者。第三,
result
数组是get_readability
的本地数组,一旦函数退出,* 就不再存在 *。数组占用的内存仍然存在,但现在可供其他函数使用。只要在get_readability
之后没有调用任何其他函数,内存就保持不变,代码看起来像预期的那样工作,但是一旦调用printf( "\n" );
,内存就会被覆盖。这里有两条路可走。
第一种(IMO首选)方法是将目标缓冲区作为参数传递给
get_readability
(将string
的任何示例替换为char *
,因为string
在CS50环境之外无法工作):你会称之为
同样,我们返回
result
指针只是为了方便;您还可以执行以下操作:第二个(不太受欢迎的)选项是在
get_readability
中动态分配内存,并返回一个指针:并称之为
此方法的缺点:
free
库函数显式地释放分配的内存;的东西,那么你就失去了对那个动态分配的缓冲区的任何引用,它会一直挂起,直到程序退出。
你可以做一些像
这样的事情,但它不会给你带来那么多好处,而且你很可能会被维护你代码的任何人谋杀。