我打算用 C 语言编写一些 leetspeak 代码,但是,我不断收到如下错误:
error: incompatible integer to pointer conversion returning 'char' from a function with result type 'string' (aka 'char *') [-werror,-wint-conversion]
或者只是我的最新代码没有返回任何值。
#include <cs50.h>
#include <stdio.h>
string replace(string no_vowels);
int main(int argc, string argv[])
{
if (argc != 2)
{
printf("Error message\n");
return 1;
}
else
{
printf("This is your message: %s\n", replace(argv[1]));
}
}
string replace(string no_vowels)
{
int i = 0;
while (no_vowels[i] != '\0')
{
i++;
}
string subs = "6310";
string new_string = "";
for (int l = 0; l < i; l++)
{
if (no_vowels[l] == 'a')
{
new_string += subs[0];
}
else if (no_vowels[l] == 'e')
{
new_string += subs[1];
}
else if (no_vowels[l] == 'i')
{
new_string += subs[2];
}
else if (no_vowels[l] == 'o')
{
new_string += subs[3];
}
new_string += no_vowels[l];
}
return new_string;
}
我尝试使用应该直接替换字母的数字创建数组,尝试添加或减去值,考虑到 ASCII 表中的每个字符字符,并在 StackOverflow 上查找现有线程
PS:我正在尝试使用已导入的库进行此练习。
您无法像在 javascript 中那样使用
+=
连接 C 中的字符串。对于此赋值,您可以就地修改参数字符串并返回原始指针。
这是修改后的版本:
string replace(string no_vowels)
{
string subs = "6310";
for (int i = 0; no_vowels[i] != '\0'; i++)
{
if (no_vowels[i] == 'a')
{
no_vowels[i] = subs[0];
}
else if (no_vowels[i] == 'e')
{
no_vowels[i] = subs[1];
}
else if (no_vowels[i] == 'i')
{
no_vowels[i] = subs[2];
}
else if (no_vowels[i] == 'o')
{
no_vowels[i] = subs[3];
}
}
return no_vowels;
}
另请注意,CS50 课程中
string
typedef 的目的是隐藏实现并避免 C 新手受到指针冲击。这就像小孩子的后轮,你应该很快将它们拆下并学习真正的技能。
这是具有实际类型的修改版本:
#include <cs50.h>
#include <stdio.h>
char *replace(char *str);
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Invalid argument count\n");
return 1;
} else {
printf("This is your message: %s\n", replace(argv[1]));
return 0;
}
}
// replace vowels in place in the argument string
char *replace(char *str) {
const char *subs = "6310";
for (int i = 0; str[i] != '\0'; i++) {
if (str[i] == 'a') {
str[i] = subs[0];
} else
if (str[i] == 'e') {
str[i] = subs[1];
} else
if (str[i] == 'i') {
str[i] = subs[2];
} else
if (str[i] == 'o') {
str[i] = subs[3];
}
}
return str;
}
我将根据您的代码假设您并不打算修改输入字符串,而是返回一个包含修改内容的新字符串。
C 字符串的级别比 Python 等字符串低。 C 字符串是一个字符数组,然后是字符串长度加上 1 作为空终止符 (
'\0'
)。
您需要为
new_string
创建这样一个数组。幸运的是,您知道长度,因为您的程序不会更改原始字符串的长度。您可以分配一个新字符串,按照替换逻辑复制到其中,然后返回新字符串。
char * replace(const char *str) {
size_t len = strlen(str);
char new_string[len + 1];
for (size_t i = 0; i < len + 1; i++) {
// assign new_string[i] from str[i] as appropriate
}
// Assign the null terminator.
new_string[len] = '\0';
return new_string;
}
除了 C 还有一个问题。您返回的指针可能仍指向该数组,也可能不指向该数组。通过从函数返回指向局部变量的指针,您可以调用未定义的行为。
您需要动态分配新字符串,以便内存“比函数调用更长寿”。在使用该内存之前,您还需要检查
malloc
的返回,以防它不起作用并且没有为您分配您期望的内存。
char * replace(const char *str) {
size_t len = strlen(str);
char *new_string = malloc(len + 1);
if (new_string == NULL) return NULL;
for (size_t i = 0; i < len + 1; i++) {
// assign new_string[i] from str[i] as appropriate
}
// Assign the null terminator.
new_string[len] = '\0';
return new_string;
}
您的函数定义无效。
在这一行
string new_string = "";
您声明了一个指向字符串文字的指针。任何更改字符串文字的尝试都会导致未定义的行为。
来自 C 标准(6.4.5 字符串文字)
7 未指定这些数组是否不同,只要它们的 元素具有适当的值。 如果程序尝试 修改这样的数组,行为是未定义的。
在这样的声明中
new_string += subs[0];
使用了指针算术来改变指针
new_string
本身。因此,指针具有无效值,该值不指向函数中声明的有效对象。如果假设这样的语句被正确重写,那么这个语句
new_string += no_vowels[l];
在任何情况下都是错误的,因为从逻辑上讲,您试图覆盖 if-else 语句中已经更新的字符。
这个 while 循环
while (no_vowels[i] != '\0')
{
i++;
}
是多余的。字符串以终止零字符
'\0'
结束。因此,您可以使用这个事实创建遍历字符串的循环条件。在任何情况下,变量 i
和 l
都应具有无符号类型 size_t
,而不是有符号类型 int
。
据我所知,字母
'u'
也是一个元音。然而你忽略了它和大写元音。
无需创建新字符串。根据 C 标准,您可以更改指向 ponters 的程序参数
argv
。
来自C标准(5.1.2.2.1程序启动)
- — 参数 argc 和 argv 以及 argv 数组指向的字符串应可由程序修改,并保留它们的值 程序启动和程序终止之间最后存储的值。
该函数可以如下所示
string replace( string no_vowels )
{
string subs = "6310";
for ( char *p = no_vowels; *p != '\0'; ++p )
{
if ( *p == 'a' )
{
*p = subs[0];
}
else if ( *p == 'e' )
{
*p = subs[1];
}
else if ( *p == 'i' )
{
*p = subs[2];
}
else if ( *p == 'o' )
{
*p = subs[3];
}
}
return no_vowels;
}