提问人:Tanya Kumari 提问时间:9/24/2023 最后编辑:chqrlieTanya Kumari 更新时间:9/24/2023 访问量:71
我正在尝试在 C 中的令牌循环中调用一个函数。我一直在段错误?
I'm trying to call a function inside of a token loop in C. I keep segfaulting?
问:
#include <stdio.h>
#include <string.h>
void pigLatinConsonant(char input[]) {
char end[] = "ay";
int length = strlen(input);
int first_vowel = -1;
for (int i = 0; i < length; i++) {
if (strchr("aeiou", input[i])) {
first_vowel = i;
break;
}
}
if (first_vowel != -1) {
char consonant_cluster[length + 1];
strncpy(consonant_cluster, input, first_vowel);
consonant_cluster[first_vowel] = '\0';
strcpy(input, input + first_vowel);
strcat(input, consonant_cluster);
}
strcat(input, end);
printf("Translated word: %s\n", input);
}
int main() {
char sentence[100];
printf("Enter a sentence: ");
fgets(sentence, sizeof(sentence), stdin);
char sentence_copy[sizeof(sentence)];
strcpy(sentence_copy, sentence);
char *token = strtok(sentence_copy, " ");
while (token != NULL) {
pigLatinConsonant(token);
token = strtok(NULL, " ");
}
return 0;
}
在这里,我尝试从循环中调用此方法,但我认为它与我的函数的构建方式有关。用户输入一个句子,它应该移动前两个字符,并将它们放在单词的末尾并添加到其中。ay
答:
对于初学者来说,您的代码与赋值没有任何共同之处
用户输入一个句子,它应该移动前两个字符, 并把它们放在单词的末尾,并在其上加上“ay”。
本声明
strcpy(input, input + first_vowel);
已调用未定义的行为。
当范围重叠时,您不能使用。strcpy
相反,您应该使用 .memmove
还有这句话
strcat(input, end);
可以覆盖原始阵列之外的内存。
您应该在函数中分配一个新的字符数组,该数组的长度比原始字符串的长度大 3 并构建在其中 一个新字符串。
如果使用可变长度数组来存储转换后的字符串,则该函数可以如下所示,如下面的演示程序所示
#include <string.h>
#include <stdio.h>
void pigLatinConsonant( const char *s )
{
const char end[] = "ay";
size_t length = strlen( s );
char pig_latin[length + sizeof( end )];
size_t i = 0;
while (i != length && strchr( "aeiou", s[i] ) == NULL ) ++i;
if (i == length)
{
strcpy( pig_latin, s );
}
else
{
strcpy( pig_latin, s + i );
strncat( pig_latin, s, i );
pig_latin[length] = '\0';
}
strcat( pig_latin, end );
printf( "Translated word: %s\n", pig_latin );
}
int main( void )
{
pigLatinConsonant( "pig" );
}
程序输出为
Translated word: igpay
评论
问题在于,它是指向原始输入字符串的指针,并且每次调用 时都会修改该字符串。该函数希望此字符串不会更改。token
pigLatinConsonant(token)
strtok()
而不是将 import 复制到 中,而是复制到一个临时字符串中,然后将其传递到 中。sentence
sentence_copy
token
word
pigLatinConsonant(word)
从手册页中可以看出:“
注意事项**:字符串 src 和 dst 不能重叠。
因此,使用左移字符串的右侧会导致 UB。
(在某些实现中,使用 开始复制,因为这样可以更快地执行。
让自己非常熟悉手册页是值得的......strcpy()
strcpy()
strcpy()
'\0'
下面显示了如何使用经过验证的标准库函数搜索第一个元音,以及如何输出字符串区域(通过仔细研究 的手册页收集了更多信息。此版本包括一个连字符,以突出显示预期的音节化。printf()
#include <stdio.h>
#include <string.h>
void piggish( char *cp ) {
size_t vowel1 = strcspn( cp, "aeiou" ); // lowercase only
if( vowel1 == 0 )
printf( "%s-ay ", cp );
else
printf( "%s-%.*say ", cp + vowel1, vowel1, cp );
}
int main( void ) {
char str[] = "when in rome do as the romans do\n";
/* Notice the '\n' that fgets() leaves in the returned buffer
* Notice the delimiters for strtok() eats that '\n'
*/
puts( str );
for( char *cp = str; ( cp = strtok( cp, " \n" ) ) != NULL; cp = NULL )
piggish( cp );
putchar( '\n' );
return 0;
}
结果:
when in rome do as the romans do
en-whay in-ay ome-ray o-day as-ay e-thay omans-ray o-day
由于输出接收到的字的段,因此不需要 提供 之外的缓冲区。printf()
全面的测试和提高鲁棒性是 OP 的一项练习。例如,处理用逗号分隔的单词。
** “Caveat”是一个拉丁词。也许扩展此代码以使用常用拉丁单词的词典,以避免将这些单词猪化。
评论