从 int 向量追加整数的字符串不会打印任何内容



背景:我刚刚完成了一个练习,其中包括使用链表制作堆栈,然后使用向量的char堆栈来执行各种功能,如将十进制数转换为二进制、十六进制和八进制,以及反转字符串。转换的最后一步涉及将字符串中的每个字符(例如,堆栈中推送的数字系统中的余数)推送以进行打印。查看下面的十进制到八进制程序以更好地理解:

Stack <int> stack; //Using a stack of char to store each remainder.
int input; //Store user input.
int remainder; //Store remainder for each step.
string converter("01234567"); //Map the octal number system.
string octal; //Store the final octal number.
do { //Ask the user to input a positive number.
cout << "Please enter a postive number to be converted to its equivalent octal number: ";
cin >> input;
} while (input <= 0);
while (input != 0) { //Creation of the octal numbers and pushing them into the stack.
remainder = input % 8; //Get the remainder of the input after dividing it by 8.
stack.push(converter[remainder]); //Add the remainder in the stack.
input = input / 8; //Get the quotient (whole number) of the input after its division by eight.
//Repeat until the quotient is less than 1 (i.e. '0' in the terms of an integer).
}
while (!stack.empty()) { //Push the contents of the stack into the string octal and clear the stack.
octal.push_back(stack.top()); //Add each octal digit last in first out.
stack.pop(); //Clear the stack.
}
//Print the octal number.
cout << "The octal number is: " << octal;

问题:我尝试使用整数向量来模仿堆栈,并尝试了上面的方法,但在下面的代码中打印字符串不会输出任何内容:

#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<int> v;

for(int i = 0; i < 10; i++) {
v.push_back(i);
}

string s;

for(int j = 0; j < v.size(); j++) {
s.push_back(v.back());
v.pop_back();
}

cout << s;

return 0;
}

注意:

我确实注意到,如果我尝试s.pushback('c');之类的东西,字符"c"会被添加到字符串中,并且可以打印出来。

此外,堆栈程序是建立在链表的模板实现之上的。所以我有四个文件:list.h、list.cpp、stack.h和stack。cpp。以及用于试验不同功能的main.cpp。

首先,要添加到字符串(s)中的char元素的值(可能)为09;假设您的平台使用ASCII表示,那么这些都不对应于可见字符。要将数值转换为它们所代表的可打印数字,需要添加值'0'

接下来,您的向量(v)在每个循环中的大小都在减小,但您也在增加j计数;因此,for循环将仅通过向量的一半;此时,递增的j将超过v.size()的值。使用while(v.size())循环,而不是:

int main()
{
std::vector<int> v;
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
std::string s;
while (v.size()) { // Will stop when v is empty
s.push_back(v.back() + '0'); // Add '0' to convert to a digit
v.pop_back(); // This removes an element and decreases .size()
}
std::cout << s << "n";
return 0;
}

std::string.push_back将一个字符作为其参数
您正在将v.back()推送到字符串中,但v.back()是一个int。
因此,它被隐式转换为char,而char没有我们想要的行为。

把它想象成ASCII表。数字0不是字符"0",而是NULL
字符"0"是48位小数。

将个位数转换为字符非常简单(标准保证在所有字符编码中都能工作):

char c = '0' + i;

所以这里是'0' + v.back()

另一个解决方案是使用std::transform,因此不需要任何循环:

#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <numeric>
int main()
{
std::vector<int> v(10);
std::iota(v.begin(), v.end(), 0);
std::string s;
std::transform(v.rbegin(), v.rend(), 
std::back_inserter(s), [&](int n) { return n + '0'; });    
v.clear();
std::cout << s << "n";
return 0;
} 

输出:

9876543210

CCD_;循环";。注意,通过给std::transform反向迭代器,迭代是向后完成的。std::back_inserter只是为lambda生成的每个字符调用s.push_back()

std::iota函数基本上是生成值0,1,2,3的快捷方式,。。。在矢量内。

主要问题是在迭代时要更改向量的大小。也就是说,j在每次迭代中递增v.size()在每次迭代因v.pop_back()而递减。因此,循环将仅被执行原始CCD_ 24的一半次数。例如,如果v.size()最初是10,那么循环将只执行5的次数。如果v.size()是一个奇数正整数,比如n,那么循环将迭代(n/2) +1整数次。

此外,假设底层平台使用ASCII,则当前添加到矢量v中的元素是不可打印(不可见)的字符。

您可以将v.push_back(i)更改为:

v.push_back(i + '0');

以验证最终字符串是否只包含一半的字符。

演示

解决方案1

您也可以使用std::vector::rbeginstd::vector::rend,如下所示:

int main()
{
std::vector<int> v;

for(int i = 0; i < 10; i++) {
v.push_back(i + '0');
}

std::string s(v.rbegin(), v.rend());
std::cout<<s<<std::endl;

return 0;
}

溶液2

您可以使用while循环或将for循环更改为如下所示:

int main()
{
std::vector<int> v;

for(int i = 0; i < 10; i++) {
v.push_back(i + '0');
}

std::string s;

//-------vvvvvvv--------->changed the condition
for(;v.size();) {  //or use while(v.size()) here
s.push_back(v.back());
v.pop_back();

}
std::cout<<s<<std::endl;

return 0;
}

最新更新