This code is an attempt to test whether or not a string is a palindrome. It reads a string of characters, pushing each character onto a stack as it is read and simultaneously adding it to a queue. Then, it uses basic stack and queue operations to determine if the string is a palindrome.
The program blows up with the aforementioned error(s) when it hits:
inStack.push(inString[i]);
inQueue.push(inString[i]);
and I don't understand why, or how to fix it. The research I have done looking into this error as it applies to my case hasn't been fruitful. I'm fairly new to c++ so forgive me if I'm overlooking something stupid.
The code is as follows:
#include <iostream>
#include <stack>
#include <queue>
#include <string>
using namespace std;
int main()
{
stack <string> inStack;
queue <string> inQueue;
string inString; //user input
int inLength; //loop counter variable
bool isPalindrome(false);
cout<<"Enter a word to see if it is a palindrome: ";
cin>>inString;
if (inString.size() > 0)
{
for (int i = 0; i <= inLength; i++)
{
inStack.push(inString[i]); //put string chars onto stack
inQueue.push(inString[i]); //add string chars to queue
}
isPalindrome = true;
while (isPalindrome && (!inStack.empty()) && (!inQueue.empty()))
{
if (inStack.top() != inQueue.front())
{
isPalindrome = false;
}
else
{
inStack.pop();
inQueue.pop();
}
}
}
if(isPalindrome == false)
{
cout<<"It is not a palindrome."<<endl;
}
else
{
cout<<"It is indeed a palindrome."<<endl;
}
return 0;
}
There are three main errors in your code.
You are pushing characters onto a stack and a queue that are defined to hold strings. The string constructor cannot implicitly convert from char to string, since there is no constructor that takes a char. You probably meant to define them as:
stack<char> inStack;
queue<char> inQueue;
You didn't set inLength; I suggest adding something like
inLength = inString.size();
after your if (inString.size() > 0) { to fix that.
Most important, you use i <= inLength (in your for loop condition), which won't work; you should use <, since pushing inString[inString.size()] is actually pushing one character beyond what you enter, which will always result in isPalindrome == false since your stack and queue will have an invalid (random garbage) character at the corresponding top and front.
These three changes appear to be enough to fix your project.
A simpler solution to give you an example of how C++ iterators can be used to reduce the amount of code you have to write for these kinds of things:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<char> left, right; // left-to-right and right-to-left lists
cout<<"Enter a word to see if it is a palindrome: ";
string inString; //user input
cin>>inString;
if(!inString.empty()){
// add characters left to right
left.insert(left.end(), inString.begin(), inString.end());
// add characters in reverse order, right to left
right.insert(right.end(), inString.rbegin(), inString.rend());
// compare the two vectors
if(left == right)
cout<<"It is indeed a palindrome."<<endl;
else
cout<<"It is not a palindrome."<<endl;
}
}
You forgot to assign to inLength the actual length of the string and get a outside i gets very big, bigger than it should be and you probably get a segmentation fault.
Try after reading the string to assign the value properly.
inLength = inString.size();
I hope this helps you.
Related
I've been given a programming task that involves taking away certain letters in a string. I was trying out different ways to do this when I found the public member function string find. To put it short I was testing out the function via this program :
#include <iostream>
#include <string>
using namespace std;
int main()
{
string Word = "Applejuice";
cout<<Word.find("e")<<endl;
return 0;
}
So when I put in a letter such as "e" I get the number 4 which confuses me because I thought the function will count all the letters in that specific word such as apple juice. Also, when I use a letter that is not used in that word I get numbers like 18446744073709551615 for example when I put in X for e in the code above.
Could someone explain why this is happening, please?
string.find() will return the position of the first character of the first match.
If no matches were found, the function returns string::npos.
Therefore the number (18446744073709551615) you are getting is the string::npos
If you want to search for an only a single character in the string you can use the following code
#include <iostream>
#include <string>
using namespace std;
// Function that return count of the given
// character in the string
int count(string s, char c)
{
// Count variable
int res = 0;
for (int i=0;i<s.length();i++)
// checking character in string
if (s[i] == c)
res++;
return res;
}
// Driver code
int main()
{
string str= "Applejuice";
char c = 'e';
cout << count(str, c) << endl;
return 0;
}
If you want to avoid some random large values as output i.e. string::npos you can just add check for it like following:
if(Word.find("e") != string::npos)
{
...
}
Method find from class string return the position of the first character of the first match. Return type of find is size_t and since size_t is unsigned integral so if no match were found return string::nopos so you should compare the outputof find with string::nopos.
if(Word.find("e") != string::nopos)
{
...
}
The execution of my code crashes when it gets to the "atoi" function, but I cannot understand why.
The code is supposed to read a matrix from a .csv file, considering:
- the first row (so till the first '\n') and saving each element (separated by a ',') in a vector of ints; - the rest of the matrix, by looking at each element and creating a specific object if the number read is 1 or 2.
I don't get any exception while debugging the program, it just crashes during the execution (and using the system ("PAUSE") I could figure out it was the atoi function which didn't work properly).
Can you help me understand what is going wrong?
Thank you very much.
Ps: I also attached all the libraries I'm loading... maybe it can help :)
#include <fstream>
#include <stdio.h>
#include <sstream>
#define nullptr 0
#include <string>
#include "classi.h"
#include <cstdlib>
#include <stdlib.h>
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char *argv[]) {
ifstream file("problem.csv");
unsigned int N = 0;
unsigned int M = 0;
char c; //modificato char * c;
unsigned int i=0,j=0, k=0, n_iter, j_temp =0;
std::vector<car> v_row;
std::vector<car> v_col_temp;
std::vector<int> iter; // location where I want to save the ints corresponding to the elements of the first row of the .csv file //
std::string iterazioni; //location where I want to save the first row as a string and then cut it into pieces (iteraz) and then convert (atoi --> iter)
std::string iteraz;
while(!file.eof()){
std::getline(file,iterazioni,'\n');
stringstream it(iterazioni);
while (it.good()) {
std::getline(it,iteraz, ',');
iter[k] = atoi(iteraz.c_str());
if(iter[k]<0){
cout<<"Errore: negative #of iterations"<<endl;
break;
}
iter.push_back(0);
k++;
}
iter.pop_back();
file.get(c);
if (c=='1'){
blue_car b(i,j);
if (v_col_temp[i].get_next() != nullptr)
v_col_temp[i].insert_tail(&b);
else
v_col_temp[i].insert_head(&b);
}
if (c=='2'){
red_car r(i,j);
if (v_row[i].get_next() != nullptr)
v_row[i].insert_tail(&r);
else
v_row[i].insert_head(&r);
}
if (c==',') {
j++;
if (i == 0)
j_temp++;
}
if (c=='\n'){
car p;
v_row.push_back(p);
v_col_temp.push_back(p);
i++;
if (j != j_temp) {
std ::cout<<"errore input non valido: numero righe/colonne non coerente"<<endl;
}
j=0;
}
else if ((c!='\n') && (c!=',') && (c!='0') && (c!='1') && (c!='2'))
std ::cout<<"errore input non valido"<<endl;
};
n_iter = k-1;
M=i;
N=j+1;
...
Your program crashes because you failed to initialize the contents of the iter vector.
std::vector<int> iter; // location where I want to save the ints corresponding to the elements of the first row of the .csv file //
You declare and construct this vector. The vector is empty at this point, and it has no elements.
At some point later:
iter[k] = atoi(iteraz.c_str());
The initial value of k is 0, so this attempts to assign the return value from atoi() to iter[0].
The problem is, of course, there is no iter[0]. The iter vector is still empty, at this point.
Additional comments, which is sadly true for at least 50% of these kinds of questions on stackoverflow.com:
1) "using namespace std"; is a bad practice, that should be avoided
2) Do not use system("pause") as well, as you referenced in your question.
I am in need of some help with this program. I am in my first ever programming class and have run into wall trying to getting my program to work. I have included what I have written so far but still it doesn't compile. It is giving the error: argument list for class template "std::vector" is missing.
Here is the question:
When you read a long document, there is a good chance that many words occur multiple times. Instead of storing each word, it may be beneficial to only store unique words, and to represent the document as a vector of pointers to the unique words. Write a program that implements this strategy. Read a word at a time from cin. Keep a vector <char *> of words. If the new word is not present in this vector, allocate memory, copy the word into it, and append a pointer to the new memory. If the word is already present, then append a pointer to the existing word.
Below is code snippet:
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
/* Create a vector of char pointers to hold the individual words.
Create a string input to hold the next input through cin. */
int main() {
vector words;
string input;
/* Keep the while loop running using cin as the condition to read an entire document.
This will end when a document has reached its end. */
while (cin >> input) {
/* For every word read as a string, convert the word into a c-string by allocating
a new character array with the proper size and using c_str and strcpy to copy
an identical c-string into the memory heap. */
char* temp = new char[input.length() + 1];
strcpy(temp, input.c_str());
/* Next, check if the word is already in the words array. Use a boolean variable
that updates if the word is found. Compare words by using the strcmp function;
when they are equal, strcmp equals 0. */
bool already_present = false;
for (int i = 0; i < words.size(); i++) {
if (strcmp(temp, words[i]) == 0) {
already_present = true;
}
}
/* If the word is already present, delete the allocated memory.
Otherwise, push the pointer into the words vector. */
if (already_present) {
delete temp;
} else {
words.push_back(temp);
}
}
}
I hope below code snippet could be helpful:
#include <string>
#include <iostream>
#include <string.h> // String.h for strcmp()
#include <vector> // Vector Header file is added
using namespace std;
int main() {
vector <char *> words; // vector of char *
string input;
while (cin >> input) {
char *temp = new char[input.length() + 1];
strcpy(temp, input.c_str());
bool already_present = false;
for (unsigned int i = 0; i < words.size(); i++) {
if (strcmp(temp, words[i]) == 0) {
already_present = true;
}
}
if (already_present) {
delete temp;
} else {
words.push_back(temp);
}
}
/* Print the desired output */
for(unsigned int i=0; i<words.size(); i++) {
cout << words[i] << endl;
}
return 0;
}
Any doubt, comments most welcome.
EDIT: After reading your comments, I came to the conclusion that you use Microsoft Visual Stdio. See, the reason you were getting warning is that strcpy() is potentially unsafe because it can lead to buffer overflow if you try to copy a string to a buffer that is not large enough to contain it.
Consider a code snippet for a moment:
char foo[10]; /* a buffer able to hold 9 chars (plus the null) */
char bar[] = "A string longer than 9 chars";
strcpy( foo, bar ); /* compiles ok, but VERY BAD because you have a buffer overflow
and are corrupting memory. */
strcpy_s() is safer because you have to explicitly specify the size of the target buffer, so the function will not overflow:
strcpy_s( foo, 10, bar ); /* strcpy_s will not write more than 10 characters */
The limitations of this strcpy_s() is that, it is non-standard and MS specific. Therefore if you write code to use it, your code will not be portable any more.
I'm attempting to take an input from the command line and then convert it to lower case. To do this, I've written:
istream& operator>>(istream& is, Card& c)
{
static map<string,Card::Rank> mr = createmr();
static map<string,Card::Suit> ms = createms();
string srank, c1, ssuit;
if (is >> srank >> c1 >> ssuit)
{
if (c1 == "of")
{
string nsrank;
string nssuit;
for(unsigned int i = 0; i < srank.length(); i++) {
char temp = srank[i];
nsrank[i] = tolower(srank[i]);
}
It fails on the second iteration of that for loop (more precisely, it fails on nsrank[i] = tolower(srank[i]);). The error that is displayed is "string substring out of range" but I don't understand how this could be the case as there are definitely still characters left in the string.
To give an example:
If I enter "Ace of Spades" then it will iterate through the first time (when i=0) and transfer the 'a' fine. However, it then goes back through with i equaling 1 (which should refer to the 'c') but instead it tells me the substring is out of range (even though the assignment to the char temp works fine). During debugging, "nsrank" claims a size of 15 so I don't see how that could be out of range either....
The problem is that nsrank is an empty string, so accessing with operator[]....
If pos is not greater than the string length, the function never
throws exceptions (no-throw guarantee). Otherwise, it causes undefined
behavior.
This one worked for me: http://ideone.com/3LcYqv
#include <iostream>
using namespace std;
int main() {
string srank="Ace of Spades";
string nsrank;
nsrank.resize(srank.length());
for(unsigned int i = 0; i < srank.length(); i++) {
char temp = srank[i];
nsrank[i] = tolower(srank[i]);
}
cout << nsrank << endl;
return 0;
}
The key is the resize to make nsrank the same size as srank.
Edit: Added compact solution
From many places, among them from this answer
#include <algorithm>
#include <string>
string srank="Ace of Spades";
string nsrank=srank;
std::transform(nsrank.begin(), nsrank.end(),nsrank.begin(), ::toupper);
resize nsrank to match size of srank before entering the loop
In the following code, is it possible that I take multiple input, do some calculation (like the last character) and print at the end .. and then again take input till 5 times?
#include <iostream>
using namespace std;
int main ()
{
char name;
int i=0;
while(i != 5){
while(!(name != '<' || name != '>')){
cin>>name;
//do some calculation with the inputs
//cout<<name;
}
i++;
cout<<name;
//print the result of calculation this loop
}
}
For some reason, I am not allowed to use string, or array, or break, and no library other than iostream. Is it possible using loops? What are alternatives?
EDIT:: In above code, I want to determine what was last input. If I enter asdf> then i get >>>>>. I want it to print > and go back in the loop and ask me for another shot.
After the inner while terminates name holds either < or > and is not reset prior to the next encounter of the inner while, which terminates immediately as name is still either < or >. Just reset name prior to the inner while or slight restructure:
while (cin >> name && !(name != '<' || name != '>'))
{
}
The solution is to reset the name variable right before this line:
while (!(name != '<' || name != '>')) {
What you need to do would be this:
name = 0;
Also, I'd recommend initializing the variable before entering the first while loop.
Edit:
Alternatively, you can use '\0' instead of 0. It makes no difference internally though. The code would only make more sense to most inexperienced users.
Looks like you want to make a pointer to a character. This will behave just like an array without actually being an array, and requires nothing but #include <iostream> for the input and output.
char* name;
You could also try using a vector of characters, but this is the long way around and would break the "nothing but <iostream> rule:
#include <vector>
#include <iostream>
using namespace std;
vector<char> CharVec;
vector<char>::iterator it;
int main ()
{
char input;
int i=0;
while(i != 5){
if(input != '<'){ //this should be if, not while
CharVec.push_back(input);
}
i++;
}
//move print to outside the character entering loop
it = CharVec.begin();
while(it != CharVec.end())
{
cout << *it;
it++;
}
}