使用字符串而不是 char 数组时程序崩溃
Posted
技术标签:
【中文标题】使用字符串而不是 char 数组时程序崩溃【英文标题】:Program crashes when using string instead of char array 【发布时间】:2017-03-19 19:00:29 【问题描述】:我正在尝试编写一个程序来输入密码等文本(显示“*”而不是用户输入的字符)。
问题是,当我使用 char 数组存储密码时,程序运行良好,但是当我使用字符串类变量实现相同目的时,我的程序在显示字符串时崩溃。
代码如下:
// *********THIS CODE WORKS FINE***********
#include <iostream>
#include<string>
#include<conio.h>
int main()
using namespace std;
int i=0;
cout<<"Enter a password,press ENTER to finish writing"<<endl;
char passw[20];
passw[i]=getch();
while(passw[i]!=13)
i++;
cout<<"*";
passw[i]=getch();
passw[i+1]='\0';
cout<<"\nPassword is "<<passw;
return 0;
现在当我将char passw[20]
替换为string passw
时:
//**********THIS CODE CRASHES!!*********
#include <iostream>
#include<string>
#include<conio.h>
int main()
using namespace std;
int i=0;
cout<<"Enter a password,press ENTER to finish writing"<<endl;
string passw;
passw=getch();
while(passw[i]!=13)
i++;
cout<<"*";
passw[i]=getch();
cout<<"\nPassword is "<<passw;
return 0;
谁能解释为什么会这样?
刚从字符串开始,我对字符串了解的太多了 :)
【问题讨论】:
std::string
不是无限的字符数组。在您可以访问 i
th 元素之前,您必须将它放在那里(passw[i]=getch()
不会放在那里)。
我该怎么做?
试试std::string::append
。
passw += getch()
使用追加来填充字符串。您仍然可以使用 getch() 来获取字符。然后将其附加到字符串的末尾并继续。
【参考方案1】:
在字符串中你可以使用字符串连接。 您可以保存您的 char 并将其添加到您的字符串变量中。
char ch;
string pass;
ch=getch();
pass=pass+ch;
【讨论】:
【参考方案2】:您正在访问的位置 (passw[i]) 尚不存在于您的 std::string 中,并且您没有将其正确存储到字符串中。你应该使用passwd.push_back(char)
的方法来存储它。
查看参考:http://en.cppreference.com/w/cpp/string/basic_string/push_back
【讨论】:
我只是想指出string::append
没有简单字符的重载。
@ErvinSzilagyi 有,您应该指定要附加的字符数 - 例如 1 (en.cppreference.com/w/cpp/string/basic_string/append)
@madduci 是的,但sting::append(char)
和string::append(size_type count, char c)
是完全不同的东西。【参考方案3】:
string
与 char 数组的工作方式不同。您可能知道char passw[20]
在您的第一个示例中创建了一个最多可容纳20 个char
s 的数组。然后可以使用operator[]
毫无问题地访问这些内容。 string
与基本数组不同,它是一个动态 数据结构,这意味着它会随着您的程序运行而随时间增长和缩小。它的内容也可以使用operator[]
访问,但是,这不会附加到字符串中,它只能用于更改已经存在的内容。
请务必注意,在 c++ 中,并非所有操作都会执行所谓的边界检查。在您的第二个示例中,您访问字符串的第 i 个字符并将一个字符写入该位置。但是,例如,如果您尝试写入一个只有 5 个空格的字符串的第 10 个字符,会发生什么?当通过operator[]
执行此操作时,程序将写入第 10 个字符所在的任何位置,即使该部分内存 实际上不是字符串的一部分。任何东西都可能存在并且会被该操作覆盖。正如您可能想象的那样,这根本是不可取的,并且可能会导致以后出现各种问题。如果幸运的话,您的程序会在写入时立即崩溃。但是,您的情况并非如此,这不是一件好事。越界写入可能会导致堆损坏(堆是内存的某个部分),这通常会在某个时间点导致崩溃。
当且仅当您知道要访问的任何索引都在字符串大小范围内时,才可以使用 operator[]
更改 string
s 字符。否则,您需要使用appropriate member function 附加到字符串。如有必要,这些将扩大字符串。
在使用动态内存时,您始终需要注意您正在访问其中的哪些部分(例如,在您的第一个示例中,如果您的密码太长,您也会写出越界)。
【讨论】:
有没有办法通过string
提前知道passw的位置?
你不需要知道任何位置,你需要知道它的大小(或者更具体地说,它的capacity)以上是关于使用字符串而不是 char 数组时程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章
可以/为啥在返回类型中使用 char * 而不是 const char * 会导致崩溃?
NSString 到 C 风格的 char 数组在第二次调用 drawRect 时崩溃