尝试将新值分配给指向字符的指针数组时 C++ 崩溃
C++ crashing when attempting to assign a new value to a pointer array pointing to chars
所以我希望通过简单地将 32 添加到 char 的值来将大写字符转换为小写,这实际上给出了它的小写等价物。
在主体中我声明了指针数组并分配了 3 个单词:
int main()
{
char *dictionary[10];
dictionary[0] = "aUto";
dictionary[1] = "caR";
dictionary[2] = "Door";
int arrayCount = 3;
upperCase(dictionary, &arrayCount);
}
在我尝试转换的函数中:
void upperCase(char *dictionary[], int *arrayCount)
{
cout << "In upperCase\n";
for (int i = 0; i < 3; i++)
for (int k = 0; dictionary[i][k] != '[=11=]'; k++)
{
if (dictionary[i][k] < 97 && dictionary[i][k] > 64) // If capital is less than the value of 'a' (97)
{
dictionary[i][k] += 32;
}
else
cout << "Not a capital\n";
}
}
程序在字典[i][k] += 32处崩溃;
我试图替换字符串中的字符(由数组元素指向)。即使先转换字母也行不通。
例如:字典[i][k] = 'a';
仍然使我的程序崩溃。
运行 windows
上的 Eclipse C++
大部分内容现在可能已包含在评论中。刚看了。是的。我还没来得及忙就忙起来了 post。无论如何,这里是问题的分解:
char *dictionary[10];
这很酷。
dictionary[0] = "aUto";
这不酷。 "aUto" 是一个 string literal。一串常量值。如何存储取决于编译器。你可以读它,但你不应该指望能够写它。 Treat 就好像被定义为 const char *
,因为就语言而言,它是 const char *
。
为什么这不酷是因为 OP 将 const char *
分配给了 char *
。将指向常量的指针分配给指向非常量的指针应该至少会产生警告。最好在编译器中调高警告级别以尽早发现此类错误。在 g++ 和类似语言中,我喜欢 -Wall
、-Wextra
和 -pedantic
的副顺序。在 MSVC 中,导航 Properties->C/C++->General 并使用 Warning Level。 EnableAllWarnings 看起来是个不错的起点。
现在常量值由非常量指针引用,编译器不知道下一位可能是致命的。
dictionary[i][k] += 32;
尝试将32加到一个字符上,这部分没问题,然后将结果存储到一个不可写的位置。这是不允许的,但尝试不可能的事情的确切处理取决于编译器。你有一个程序崩溃,这对编译器来说非常好。该程序本可以保留 运行,破坏一些其他内存 space,然后死掉,让您不知道实际发生了什么以及要调试什么。
如何使这些字符串不是常量:
- 使用 std::string rather than char *. In C++ this is by far the better option. And while you're at it, use std::vector 代替数组。
- 但这闻起来像作业,你可能不被允许使用 std::string。在这种情况下,分配存储并将字符串文字复制到存储中,以便它们有真正的、可修改的内存支持它们。
编码风格注意事项:
不要使用像 97 这样的数值,而是使用字符 'a'。它的工作原理相同,您的意图更容易确定。最好省去所有麻烦并使用 std::tolower。
还有一个巧妙的技巧,您可以使用 std::transform、std::string 和 std::tolower 来删除大部分 upperCase 函数。稍微试验一下,您就会发现它。
更正(我似乎总是在这个问题上发现自己):使用 tolower,而不是 std::tolower,因为 std::tolower 的语言环境过载使得你想要哪个 std::tolower 变得模棱两可。
这个:
for (int i = 0; i < 3; i++)
有点傻。你传入了 arrayCount。如果您更改数组中的项目数,您不妨使用它并避免混淆
for (int i = 0; i < *arrayCount; i++)
如果您被允许使用 C++,那么您可以改为:
- 使用STL
- 使用向量,对于这些类型的事情通常更容易处理
- 使用 Stringstream(或一般的流)
虽然这只是一个想法。但是您的代码肯定看起来更像是 C 问题(宁愿使用 malloc 分配动态内存)而不是 C++ 问题。
此外,您确定 dictionary[i][k] += 32
操作真的按照您认为的方式进行吗?通常在这些类型的代码中崩溃意味着您的指针指向 unallocated/invalid 位置。
所以我希望通过简单地将 32 添加到 char 的值来将大写字符转换为小写,这实际上给出了它的小写等价物。
在主体中我声明了指针数组并分配了 3 个单词:
int main()
{
char *dictionary[10];
dictionary[0] = "aUto";
dictionary[1] = "caR";
dictionary[2] = "Door";
int arrayCount = 3;
upperCase(dictionary, &arrayCount);
}
在我尝试转换的函数中:
void upperCase(char *dictionary[], int *arrayCount)
{
cout << "In upperCase\n";
for (int i = 0; i < 3; i++)
for (int k = 0; dictionary[i][k] != '[=11=]'; k++)
{
if (dictionary[i][k] < 97 && dictionary[i][k] > 64) // If capital is less than the value of 'a' (97)
{
dictionary[i][k] += 32;
}
else
cout << "Not a capital\n";
}
}
程序在字典[i][k] += 32处崩溃; 我试图替换字符串中的字符(由数组元素指向)。即使先转换字母也行不通。 例如:字典[i][k] = 'a'; 仍然使我的程序崩溃。 运行 windows
上的 Eclipse C++大部分内容现在可能已包含在评论中。刚看了。是的。我还没来得及忙就忙起来了 post。无论如何,这里是问题的分解:
char *dictionary[10];
这很酷。
dictionary[0] = "aUto";
这不酷。 "aUto" 是一个 string literal。一串常量值。如何存储取决于编译器。你可以读它,但你不应该指望能够写它。 Treat 就好像被定义为 const char *
,因为就语言而言,它是 const char *
。
为什么这不酷是因为 OP 将 const char *
分配给了 char *
。将指向常量的指针分配给指向非常量的指针应该至少会产生警告。最好在编译器中调高警告级别以尽早发现此类错误。在 g++ 和类似语言中,我喜欢 -Wall
、-Wextra
和 -pedantic
的副顺序。在 MSVC 中,导航 Properties->C/C++->General 并使用 Warning Level。 EnableAllWarnings 看起来是个不错的起点。
现在常量值由非常量指针引用,编译器不知道下一位可能是致命的。
dictionary[i][k] += 32;
尝试将32加到一个字符上,这部分没问题,然后将结果存储到一个不可写的位置。这是不允许的,但尝试不可能的事情的确切处理取决于编译器。你有一个程序崩溃,这对编译器来说非常好。该程序本可以保留 运行,破坏一些其他内存 space,然后死掉,让您不知道实际发生了什么以及要调试什么。
如何使这些字符串不是常量:
- 使用 std::string rather than char *. In C++ this is by far the better option. And while you're at it, use std::vector 代替数组。
- 但这闻起来像作业,你可能不被允许使用 std::string。在这种情况下,分配存储并将字符串文字复制到存储中,以便它们有真正的、可修改的内存支持它们。
编码风格注意事项:
不要使用像 97 这样的数值,而是使用字符 'a'。它的工作原理相同,您的意图更容易确定。最好省去所有麻烦并使用 std::tolower。
还有一个巧妙的技巧,您可以使用 std::transform、std::string 和 std::tolower 来删除大部分 upperCase 函数。稍微试验一下,您就会发现它。 更正(我似乎总是在这个问题上发现自己):使用 tolower,而不是 std::tolower,因为 std::tolower 的语言环境过载使得你想要哪个 std::tolower 变得模棱两可。
这个:
for (int i = 0; i < 3; i++)
有点傻。你传入了 arrayCount。如果您更改数组中的项目数,您不妨使用它并避免混淆
for (int i = 0; i < *arrayCount; i++)
如果您被允许使用 C++,那么您可以改为:
- 使用STL
- 使用向量,对于这些类型的事情通常更容易处理
- 使用 Stringstream(或一般的流)
虽然这只是一个想法。但是您的代码肯定看起来更像是 C 问题(宁愿使用 malloc 分配动态内存)而不是 C++ 问题。
此外,您确定 dictionary[i][k] += 32
操作真的按照您认为的方式进行吗?通常在这些类型的代码中崩溃意味着您的指针指向 unallocated/invalid 位置。