So recently i started to getting into stacks ADT in c++ and i am trying to create a small program which the user inserts a string and the output should be in reverse order
But something is going wrong with my code or i am missing something but i cant figure it out
My output so far is that i can insert the string but then it just output the couts "Reverse string" and nothing else
i tried several ways like to change the pop function but nothing changed
Thank you for any help
#include <iostream>
#include <string>
using namespace std;
class ReverseString {
public:
string str[13];
int topStack;
ReverseString() {
topStack = -1;
}
string Push() {
//char item;
string str("");
cout << "Enter a string " << endl;
cin >> str;
for (char ch : str) {
topStack++;
// str[topStack] = item;
return str;
}
}
string Pop() {
string temp= str[topStack];
for (int i = 0; i <= 13; i++) {
str[i] = temp;
//temp = str[i - 1];
cout << "Reverse String: " << str[topStack] << endl;
return temp;
}
}
};
// main function
int main() {
ReverseString str;
str.Push();
str.Pop();
return 0;
}
I am entirely new to programming so I'm sorry if I don't explain this well. For my C++ assignment I had to write an object-oriented program that reads the names from a text file (the text file is just a list of first names) and prints them to the console in alphabetical order using an array. Originally, the description of the assignment said that the file had 20 names, so I based my code around that. The program works, but now it turns out the assignment description was inaccurate and we shouldn't assume that the text file has a specific number of names. How do I convert my code from specifically reading 20 names to instead reading an undefined number of names, while still using an array?
I don't fully understand the concepts that I'm implementing so it's difficult for me to know how to change my code while still following the requirements of the assignment. Here is my code:
#include <iostream>
#include <algorithm>
#include <fstream>
#include <string>
using namespace std;
class Names
{
private:
ifstream inStudents;
string studentNames[20];
string name;
int j;
public:
Names();
~Names();
void openFile(string);
void testFile();
void readFile();
void sortNames();
void closeFile();
void display();
};
Names::Names()
{
}
Names::~Names()
{
}
void Names::openFile(string d)
{
inStudents.open(d);
}
void Names::testFile()
{
if (!inStudents)
{
cout << "File did not open" << endl;
exit(10);
}
}
void Names::readFile()
{
cout << "Reading the input file..." << endl;
int j = 0;
while (inStudents >> name && j < 20)
{
studentNames[j++] = name;
}
}
void Names::sortNames()
{
sort(studentNames, studentNames + 20);
}
void Names::closeFile()
{
inStudents.close();
}
void Names::display()
{
cout << endl << "The alphabetical list: " << endl << endl;
for (int i = 0; i<20; i++)
cout << studentNames[i] << " " << endl;
cout << endl << endl;
}
int main()
{
Names r;
r.openFile("students.txt");
r.readFile();
r.testFile();
r.sortNames();
r.display();
r.closeFile();
return 0;
}
You can use std::vector object instead of a regular array. It will look like that:
vector<string> studentNames;
Now, instead of using the following line to insert a name to a known place in the array:
studentNames[j++] = name;
use:
studentNames.push_back(name);
//or
studentNames.emplace_back(name);
The the while loop inside your readFile function, will look like this:
while (inStudents >> name)
{
studentNames.push_back(name);
}
To display it now, all you have to change in your display function is the range. The vector object include a function named size which returns you the current vector size, or in other words- the elements' count that the vector includes. It will seem like the following line:
for (int i = 0; i < studentNames.size(); i++)
I have a function for converting integers into std::string.
std::stringstream Tools::toStringConverter;
std::string Tools::tempString;
std::string Tools::intToString(int num) {
toStringConverter.str(std::string());
toStringConverter << num;
toStringConverter >> tempString;
return tempString;
}
When I try to use this method while using iterators, I get correct result
for(Button b : buttons) {
std::cout << Tools::intToString(b.id);
}
Also output is correct if I try this:
std::cout<< intToString(3);
But when I use simple for loop, I always get 0.
for(int i = 0; i < NetworkManager::MAX_PLAYERS; i++) {
std::cout << Tools::intToString(i) << " ";
}
std::string Tools::intToString(int num) {
std::stringstream toStringConverter;
toStringConverter << num;
return toStringConverter.str();
}
Don't use global variables.
Last week I got an homework to write a function: the function gets a string and a char value and should divide the string in two parts, before and after the first occurrence of the existing char.
The code worked but my teacher told me to do it again, because it is not well written code. But I don't understand how to make it better. I understand so far that defining two strings with white spaces is not good, but i get out of bounds exceptions otherwise. Since the string input changes, the string size changes everytime.
#include <iostream>
#include <string>
using namespace std;
void divide(char search, string text, string& first_part, string& sec_part)
{
bool firstc = true;
int counter = 0;
for (int i = 0; i < text.size(); i++) {
if (text.at(i) != search && firstc) {
first_part.at(i) = text.at(i);
}
else if (text.at(i) == search&& firstc == true) {
firstc = false;
sec_part.at(counter) = text.at(i);
}
else {
sec_part.at(counter) = text.at(i);
counter++;
}
}
}
int main() {
string text;
string part1=" ";
string part2=" ";
char search_char;
cout << "Please enter text? ";
getline(cin, text);
cout << "Please enter a char: ? ";
cin >> search_char;
divide(search_char,text,aprt1,part2);
cout << "First string: " << part1 <<endl;
cout << "Second string: " << part2 << endl;
system("PAUSE");
return 0;
}
I would suggest you, learn to use c++ standard functions. there are plenty utility function that can help you in programming.
void divide(const std::string& text, char search, std::string& first_part, std::string& sec_part)
{
std::string::const_iterator pos = std::find(text.begin(), text.end(), search);
first_part.append(text, 0, pos - text.begin());
sec_part.append(text, pos - text.begin());
}
int main()
{
std::string text = "thisisfirst";
char search = 'f';
std::string first;
std::string second;
divide(text, search, first, second);
}
Here I used std::find that you can read about it from here and also Iterators.
You have some other mistakes. you are passing your text by value that will do a copy every time you call your function. pass it by reference but qualify it with const that will indicate it is an input parameter not an output.
Why is your teacher right ?
The fact that you need to initialize your destination strings with empty space is terrible:
If the input string is longer, you'll get out of bound errors.
If it's shorter, you got wrong answer, because in IT and programming, "It works " is not the same as "It works".
In addition, your code does not fit the specifications. It should work all the time, independently of the current value which is stored in your output strings.
Alternative 1: your code but working
Just clear the destination strings at the beginning. Then iterate as you did, but use += or push_back() to add chars at the end of the string.
void divide(char search, string text, string& first_part, string& sec_part)
{
bool firstc = true;
first_part.clear(); // make destinations strings empty
sec_part.clear();
for (int i = 0; i < text.size(); i++) {
char c = text.at(i);
if (firstc && c != search) {
first_part += c;
}
else if (firstc && c == search) {
firstc = false;
sec_part += c;
}
else {
sec_part += c;
}
}
}
I used a temporary c instead of text.at(i) or text\[i\], in order to avoid multiple indexing But this is not really required: nowadays, optimizing compilers should produce equivalent code, whatever variant you use here.
Alternative 2: use string member functions
This alternative uses the find() function, and then constructs a string from the start until that position, and another from that position. There is a special case when the character was not found.
void divide(char search, string text, string& first_part, string& sec_part)
{
auto pos = text.find(search);
first_part = string(text, 0, pos);
if (pos== string::npos)
sec_part.clear();
else sec_part = string(text, pos, string::npos);
}
As you understand yourself these declarations
string part1=" ";
string part2=" ";
do not make sense because the entered string in the object text can essentially exceed the both initialized strings. In this case using the string method at can result in throwing an exception or the strings will have trailing spaces.
From the description of the assignment it is not clear whether the searched character should be included in one of the strings. You suppose that the character should be included in the second string.
Take into account that the parameter text should be declared as a constant reference.
Also instead of using loops it is better to use methods of the class std::string such as for example find.
The function can look the following way
#include <iostream>
#include <string>
void divide(const std::string &text, char search, std::string &first_part, std::string &sec_part)
{
std::string::size_type pos = text.find(search);
first_part = text.substr(0, pos);
if (pos == std::string::npos)
{
sec_part.clear();
}
else
{
sec_part = text.substr(pos);
}
}
int main()
{
std::string text("Hello World");
std::string first_part;
std::string sec_part;
divide(text, ' ', first_part, sec_part);
std::cout << "\"" << text << "\"\n";
std::cout << "\"" << first_part << "\"\n";
std::cout << "\"" << sec_part << "\"\n";
}
The program output is
"Hello World"
"Hello"
" World"
As you can see the separating character is included in the second string though I think that maybe it would be better to exclude it from the both strings.
An alternative and in my opinion more clear approach can look the following way
#include <iostream>
#include <string>
#include <utility>
std::pair<std::string, std::string> divide(const std::string &s, char c)
{
std::string::size_type pos = s.find(c);
return { s.substr(0, pos), pos == std::string::npos ? "" : s.substr(pos) };
}
int main()
{
std::string text("Hello World");
auto p = divide(text, ' ');
std::cout << "\"" << text << "\"\n";
std::cout << "\"" << p.first << "\"\n";
std::cout << "\"" << p.second << "\"\n";
}
Your code will only work as long the character is found within part1.length(). You need something similar to this:
void string_split_once(const char s, const string & text, string & first, string & second) {
first.clear();
second.clear();
std::size_t pos = str.find(s);
if (pos != string::npos) {
first = text.substr(0, pos);
second = text.substr(pos);
}
}
The biggest problem I see is that you are using at where you should be using push_back. See std::basic_string::push_back. at is designed to access an existing character to read or modify it. push_back appends a new character to the string.
divide could look like this :
void divide(char search, string text, string& first_part,
string& sec_part)
{
bool firstc = true;
for (int i = 0; i < text.size(); i++) {
if (text.at(i) != search && firstc) {
first_part.push_back(text.at(i));
}
else if (text.at(i) == search&& firstc == true) {
firstc = false;
sec_part.push_back(text.at(i));
}
else {
sec_part.push_back(text.at(i));
}
}
}
Since you aren't handling exceptions, consider using text[i] rather than text.at(i).
I am a beginner to C++, I have used C before but never used C++. This is one of my first programs, and it's supposed to do something really simple, however I'm unable to even pass strings between methods... When I call the method setMode with a string array, the method instance recieves an empty array, and not the one I've sent. Why is this happening?
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
#define LED_PATH "sys/class/leds/beaglebone:green:usr"
class LED{
private:
string path;
int number;
public:
LED(int number);
virtual void setMode(string mode[]);
virtual ~LED();
};
LED::LED(int number){
ostringstream fs;
this->number = number;
fs << LED_PATH << number;
this->path = string(fs.str());
cout << this->path << endl;
}
LED::~LED(){
}
void LED::setMode(string mode[]){
//Will use all fields of mode[] in the future
cout << "setMode: mode: " << mode[0].c_str() << endl;
}
int main(int argc, char* argv[]){
LED LEDs[4] = {LED(0), LED(1), LED(2), LED(3)};
string mode[argc-1];
//TODO Perform argc value safety check
for(int i=1; i<argc; i++){
mode[i] = string(argv[i]);
cout << mode[i].c_str()<<endl;
}
for(int i=0; i<4; i++){
LEDs[i].setMode(mode);
}
return 0;
}
Output:
debian#beaglebone:~/Desktop/LED_Cpp$ ./led on 1
sys/class/leds/beaglebone:green:usr0
sys/class/leds/beaglebone:green:usr1
sys/class/leds/beaglebone:green:usr2
sys/class/leds/beaglebone:green:usr3
on
1
setMode: mode:
setMode: mode:
setMode: mode:
setMode: mode:
string mode[argc-1];
This uses a proprietary GCC extension. In standard C++, a raw array's size must be known at compile time.
You need something like this instead:
if (argc < 4) {
std::cerr << "error\n";
return EXIT_FAILURE;
}
string mode[4];
Or, what would be very much preferable, use std::vector:
std::vector<std::string> mode(argc-1);
for(int i=1; i<argc; i++){
mode[i] = string(argv[i]);
cout << mode[i].c_str()<<endl;
}
This will leave mode[0] empty.
for(int i=0; i<4; i++){
LEDs[i].setMode(mode);
}
The array (or std::vector) passed to setMode will thus always be such that the first element is an empty string.
void LED::setMode(string mode[]){
This is an attempt to pass an array to a function. What happens really is that a pointer to the first element is passed and the size information is lost.
The correct way of passing a raw array including its size information would be to use a reference:
void LED::setMode(string (&mode)[4])
But as I mentioned previously, just use a std::vector and you'll be fine. When you need to modify the vector, pass it via &, else via const&:
void LED::setMode(std::vector<std::string> const& mode)
In either case, inside of the method, you currenly just access the first element:
cout << "setMode: mode: " << mode[0].c_str() << endl;
As we've established before, mode[0] is always empty. That's why nothing is printed.
You are off by one. You are writing to
mode[1]
in
for(int i=1; i<argc; i++){
mode[i] = string(argv[i]);
and you use
mode[0]
for output.