我编写了一个程序,该程序应该接受一个字符串,然后返回一个只包含原始字母的字符串,但它不起作用,无法弄清楚原因。有人能帮助我吗?
#include<stdio.h>
char *only_letters(char *s1ptr, char *s2ptr)
{
while(*s1ptr)
{
if((*s1ptr >= 'a' && *s1ptr <= 'z') || (*s1ptr >= 'A' && *s1ptr <= 'Z'))
{
*s2ptr = *s1ptr;
s2ptr++;
}
s1ptr++;
}
*s2ptr = '\0';
return s2ptr;
}
int main()
{
char *s1ptr, *s2ptr;
printf("\n Write a string:\n");
scanf("%s", s1ptr);
printf("\n%s\n", *only_letters(s1ptr, s2ptr));
return 0;
}
答案 0 :(得分:4)
你有3个问题。
s1ptr
和s2ptr
是两个未分配的数组,会导致未定义的行为。
您正在将s2ptr
增加到值为\0
的点。返回后,您将拥有一个只有\0
的字符串。
要显示字符串,您必须在没有*
的情况下传递它(不要取消引用它)。
试试这个
char *only_letters(char *s1ptr, char *s2ptr_)
{
char *s2ptr = s2ptr_;
while(*s1ptr)
{
if((*s1ptr >= 'a' && *s1ptr <= 'z') || (*s1ptr >= 'A' && *s1ptr <= 'Z'))
{
*s2ptr = *s1ptr;
s2ptr++;
}
s1ptr++;
}
*s2ptr = '\0';
return s2ptr_;
}
int main()
{
char s1ptr[256]; // Long enough
char s2ptr[256]; // Long enough
printf("\n Write a string:\n");
scanf("%s", s1ptr);
printf("\n%s\n", only_letters(s1ptr, s2ptr));
}
答案 1 :(得分:3)
您遇到了未定义的行为,因为s1ptr
没有指向有效位置,因此scanf
失败。
尝试将变量声明为
char s1ptr[64], s2ptr[64]; //or whatever length suits you
另外,请注意
printf("\n%s\n", *only_letters(s1ptr, s2ptr));
将尝试取消引用only_letters
返回的内容(char*
,取消引用为char
),但您尝试将其作为字符串读取(通过%s
)。删除解引用运算符。
答案 2 :(得分:1)
这是非常难看的C风格代码,容易出错。虽然代码中的错误已由早期的鸟类修复,但这是C ++的方法:
std::string only_letters (std::string input) {
auto it = std::remove_if(input.begin(),input.end(),
[](const char x) {return !std::isalpha(static_cast<unsigned char>(x));});
input.erase(it,input.end());
return input;
}
int main () {
std::string input;
std::cout << "Write a string:\n";
std::cin >> input;
std::cout << only_letters(input);
}
答案 3 :(得分:0)
除了您使用无效指针这一事实外,您还使用了错误的格式说明符:
printf("\n%s\n", *only_letters(s1ptr, s2ptr));
由于only_letter
返回char*
,因此取消引用其结果会产生char
。
您的格式表示期望指向零终止字符序列(“%s”)的指针,因此printf
将解释您作为指针传递给它的char
。
在您的情况下,您将返回指向最终'\0'
字符的指针,并且零恰好被解释为空指针,打印为“(null)”。
在开始之前,您需要保存结果指针的初始值。
可能完整且未经测试的修复:
char *only_letters(char *s1ptr, char *s2ptr)
{
char* result = s2ptr;
while(*s1ptr)
{
if((*s1ptr >= 'a' && *s1ptr <= 'z') || (*s1ptr >= 'A' && *s1ptr <= 'Z'))
{
*s2ptr = *s1ptr;
s2ptr++;
}
s1ptr++;
}
*s2ptr = '\0';
return result;
}
int main()
{
char s1ptr[1024], s2ptr[1024];
printf("\n Write a string:\n");
scanf("%s", s1ptr);
printf("\n%s\n", only_letters(s1ptr, s2ptr));
return 0;
}
答案 4 :(得分:0)
您的代码至少有三个缺陷。第一个是函数定义
char *only_letters(char *s1ptr, char *s2ptr)
{
while(*s1ptr)
{
if((*s1ptr >= 'a' && *s1ptr <= 'z') || (*s1ptr >= 'A' && *s1ptr <= 'Z'))
{
*s2ptr = *s1ptr;
s2ptr++;
}
s1ptr++;
}
*s2ptr = '\0';
return s2ptr;
}
该函数返回指向终止零的指针
*s2ptr = '\0';
return s2ptr;
有效代码可以采用以下方式
char * only_letters( const char *s1ptr, char *s2ptr )
{
char *p = s2ptr;
while ( *s1ptr )
{
if ( ( *s1ptr >= 'a' && *s1ptr <= 'z' ) || ( *s1ptr >= 'A' && *s1ptr <= 'Z' ) )
{
*p++ = *s1ptr;
}
s1ptr++;
}
*p = '\0';
return s2ptr;
}
至于我,那我就把这个函数写成
char * only_letters( const char *s1ptr, char *s2ptr )
{
char *p = s2ptr;
while ( *s1ptr )
{
if ( isalpha( *s1ptr ) )
{
*p++ = *s1ptr;
}
s1ptr++;
}
*p = '\0';
return s2ptr;
}
第二个缺陷是你没有在你要写数据的地方分配内存。
int main()
{
char *s1ptr, *s2ptr;
//...
有效代码可能看起来像
int main()
{
const size_t N = 20;
char s1ptr[N], s2ptr[N];
考虑到而不是
printf("\n%s\n", *only_letters(s1ptr, s2ptr));
必须有
printf("\n%s\n", only_letters(s1ptr, s2ptr));
第三个缺陷是使用函数scanf
来读取字符串。此函数可以覆盖不属于该数组的内存。
scanf("%s", s1ptr);
最好使用函数fgets
例如
fgets( s1ptr, N, stdin );
最后,如果程序是用C语言编写的,则main应定义为
int main( void )
如果是偶然的:)它是一个C ++程序,那么你应该使用标准的C ++流而不是C流和相应的C ++函数而不是C函数。
此外,您可以使用标准算法std::copy_if
来仅在目标字符串中复制字母字符。