Stack Corruption on Program Termination? - c++

I'm am writing a program for a homework assignment, and can't quite understand what I am doing wrong. The program takes some text input, and outputs it in pig latin, and while the program now achieves this, there is stack corruption on program termination, with VS mentioning "Run-Time Check Failure #2 - Stack around the variable 'token' was corrupted."
I suspect that this is due to going past the boundaries of the pointer somehow, but I don't entirely understand pointers at the current moment, so most things I found don't really make sense, and I'm trying to understand, not just fix what I did wrong.
Attached is the function using the variable that is causing all the trouble (edited to include full program, due to me realizing that some important bits were left out).
int main(void)
{
char text[] = "";
char seps[] = " \t\n";
char *token = NULL;
char *next_token = NULL;
bool cont = true;
bool valid = false;
char contResp;
cout << "Enter a sentence to be translated: ";
do
{
cin.getline(text, 200);
cout << endl << text << endl;
token = strtok_s(text, seps, &next_token);
while (token != NULL)
{
if (token != NULL)
{
printLatinWord(token);
token = strtok_s(NULL, seps, &next_token);
}
}
cout << endl << endl << "Do you want to enter another sentence (y/n)? ";
valid = false;
while (!valid)
{
cin >> contResp;
contResp = tolower(contResp);
if (contResp == 'y')
{
valid = true;
cin.ignore();
cout << "Enter a sentence to be translated: ";
}
else if (contResp == 'n')
{
valid = true;
cont = false;
}
else
{
cout << "Invalid response. Please try again.";
cout << endl << endl << "Do you want to enter another sentence (y/n)? ";
}
}
}
while (cont);
system("pause");
return 0;
}
void printLatinWord(char *token)
{
string text = "";
char *first = token;
token++;
while (*token != '\0')
{
text += *token;
token++;
}
text += *first;
text += "ay ";
cout << text;
}
I am not sure how to get this problem sorted out, but if I could get some help as well as a simple explanation of what I did wrong, I would greatly appreciate it, as pointer arithmetic is mostly gibberish to me.
Thanks in advance!

char text[] = "";
This creates a 1-byte array to hold a '\0' character (NUL terminator). It’s the same as:
char text[1];
text[0] = '\0';
cin.getline(text, 200);
This writes up to 200 chars — 199 chars plus the NUL terminator — into the 1-char array.
Obvious solution: make the array 200 chars long.
char text[200] = "";
Alternatively, use a std::string for text instead of a char array, and use getline(cin, text); for unlimited line length.

Related

Does anyone have any idea how to make so the mask of the password is delayed by a second or two before it replace the password with '*'?

here is some fragment of my code. Can anyone help me? On how to make so the mask of the password is delayed by a second or two before it replaces the password with '*'?
struct adminInfo
{
string adminID;
string adminName;
string adminPassword;
};
void create_admin (adminInfo ad [], int &count)
{
char pass = 0;
const char BACKSPACE = 127;
const char RETURN = 10;
cout << " **************************************" << endl;
cout << " REGISTER ADMINISTRATOR" << endl;
cout << " **************************************" << endl;
cout << " Enter admin registration number (ID) : "; cin >> ws;
getline (cin, ad[count].adminID);
cout << " Enter admin full name : "; cin >> ws;
getline (cin, ad[count].adminName);
cout << " Please create your password : ";// cin >> ws;
//getline (cin, ad[count].adminPassword)
while ((pass=getch(void)) != RETURN)
{
if (pass == BACKSPACE)
{
if (ad[count].adminPassword.length() != 0)
{
cout << "\b \b";
ad[count].adminPassword.resize(ad[count].adminPassword.length() - 1);
}
}
else
{
ad[count].adminPassword += pass;
cout << "*";
}
}
count++;
}
Side note: Should std::endl always be used?
Also it might be easier for me to answer if I knew what libraries you were using. For the sake of simplicity I will presume you use the standard C++ library iostream for cout etc conio.h for getch() string for string and namespace std.
If you don't mind the last character being seen, you could literally just wait for the user input like this:
while ((pass = getch()) != RETURN) {
/* Making length variable so I don't have to call length() function multiple times and it looks cleaner */
int length = ad[count].adminPassword.length()
/* Using bigger than zero just to make it more explicit */
if (length > 0) {
/* Change last character to asterisk */
cout << "\b \b*";
}
if (pass == BACKSPACE) {
if (length > 0) {
cout << "\b \b";
ad[count].adminPassword.resize(length - 1);
}
} else {
ad[count].adminPassword += pass;
/* Instead of asterisk as that is now changed at every keypress after first input */
cout << pass;
}
}
If you wish to actually wait you could just include <windows.h> (or unix equivalent) and use Sleep(milliseconds) function like this in the else statement:
cout << pass;
ad[count].adminPassword += pass;
Sleep(Time in milliseconds)
cout << "\b \b*";
But this will wait the time in milliseconds to print out the next value and will give a pretty confusing and questionable output if you type above 3 wpm.
This is the best that I could think of, I'm not that knoweledgeable about C++ so sorry if I could not answer your question well enough.
I'm presuming you could do something with multithreading to make it wait while taking input. But as I said I do not know much about C++ so I will leave that to someone smarter than me ;D.

C++ Need some advices with Pig Latin string

I need to write a sentence in Pig Latin form and I am almost done it successfuly except for 1 case and I almost give up
for example :
If my word starts at a\e\o\u\i the word will look like easy -> easyway , apple -> appleway
and if it doesnt start with a letter that I wrote above
it will look like that: box -> oxbay , king -> ingkay
I succeed with the bolded part but in the first part with a\e\o\u\i letter at the beginning , I dont know where to put the w before and need some help with it
This is my code , thanks in advance
#include <iostream>
//Since those are used in ALL function of program, it wont hurt to set it to global
//Else it is considered EVIL to declare global variables
const int maxLine = 100;
char phraseLine[maxLine] = { '\0' };
void pigLatinString();
using namespace std;
void main()
{
// Displayed heading of program
cout << "* You will be prompted to enter a string of *" << endl;
cout << "* words. The string will be converted into *" << endl;
cout << "* Pig Latin and the results displayed. *" << endl;
cout << "* Enter as many strings as you would like. *" << endl;
//prompt the user for a group of words or press enter to quit
cout << "Please enter a word or group of words. (Press enter to quit)\n";
cin.getline(phraseLine, 100, '\n');
cout << endl;
// This is the main loop. Continue executing until the user hits 'enter' to quit.
while (phraseLine[0] != '\0')
{
// Display the word (s) entered by the user
cout << "You entered the following: " << phraseLine << endl;
// Display the word (s) in Pig Latin
cout << "The same phrase in Pig latin is: ";
pigLatinString();
cout << endl;
//prompt the user for a group of words or press enter to quit
cout << "Please enter a word or group of words. (Press enter to quit)\n";
cin.getline(phraseLine, 100, '\n');
}
return;
}
void pigLatinString() //phraseLine is a cstring for the word, maxline is max length of line
{ //variable declarations
char tempConsonant[10];
tempConsonant[0] = '\0';
int numberOfConsonants = 0;
char previousCharacter = ' ';
char currentCharacter = ' ';
bool isInWord = 0;
// for loop checking each index to the end of whatever is typed in
for (int i = 0; i < maxLine; i++)
{
//checking for the end of the phraseline
if (phraseLine[i] == '\0')
{//checking to see if it's in the word
if (isInWord)
{//checking to see that there wasn't a space ahead of the word and then sending the cstring + ay to the console
if (previousCharacter != ' ')
cout << tempConsonant << "ay" << endl;
}
return;
}
// this covers the end of the word condition
if (isInWord)
{// covers the condition of index [i] being the space at the end of the word
if (phraseLine[i] == ' ')
{
// spits out pig latin word, gets you out of the word, flushes the temp consonants array and resets the # of consonants to 0
cout << tempConsonant << "ay";
isInWord = 0;
tempConsonant[0] = '\0';
numberOfConsonants = 0;
}
cout << phraseLine[i] ;
}
else
{//this covers for the first vowel that makes the switch
if (phraseLine[i] != ' ')
{// sets the c string to what is in the phraseline at the time and makes it capitalized
char currentCharacter = phraseLine[i];
currentCharacter = toupper(currentCharacter);
// this takes care of the condition that currentCharacter is not a vowel
if ((currentCharacter != 'A') && (currentCharacter != 'E') &&
(currentCharacter != 'I') && (currentCharacter != 'O') && (currentCharacter != 'U'))
//this sets the array to temporarily hold the consonants for display before the 'ay'
{//this sets the null operator at the end of the c string and looks for the next consonant
tempConsonant[numberOfConsonants] = phraseLine[i];
tempConsonant[numberOfConsonants + 1] = '\0';
numberOfConsonants++;
}
else
{// this sets the boolean isInWord to true and displays the phraseline
isInWord = 1;
cout << phraseLine[i];
}
}
else
{
cout << phraseLine[i] ;
}
}
previousCharacter = phraseLine[i];
}
return;
}
You have two conditions to consider. if your word starts with a vowel, just add "way" to the end of the word, else move the first letter and add "ay" to the end.
This is a task that can be made a lot simpler by using std::string instead of C-strings. This is because you are now no longer concerned with exceeding your length or losing the null character. It also allows easier access to the Standard Library algorithms.
#include <algorithm>
#include <iostream>
#include <string>
std::string make_pig_latin(const std::string& word) {
std::string vowels("aeiou");
std::string newWord(word);
if (newWord.find_first_not_of(vowels) == 0) {
// Word starts with a consanant
std::rotate(newWord.begin(), newWord.begin() + 1, newWord.end());
newWord += "ay";
} else {
newWord += "way";
}
return newWord;
}
int main() {
std::cout << make_pig_latin("apple") << '\n'
<< make_pig_latin("box") << '\n'
<< make_pig_latin("king") << '\n'
<< make_pig_latin("easy") << '\n';
}
The function above highlights how you can go about structuring your conversion. You just need to know if your word starts with a vowel or not, and take the appropriate action.
Output:
appleway
oxbay
ingkay
easyway
I did not get the impression that you have to care about words like 'phone'.
Looking through your code, you should try to do a better job at separating your concerns. Pig Latin is easier done one word at a time, but you have string splitting code and a lot of "not Pig Latin" code in your Pig Latin function. Your main can handle getting input. You should probably have a separate function to break the line up into individual words, using std::vector to hold the words would be best since it can grow on demand and doesn't have to know a specific capacity up front. You then iterate through your array of words and translate them individually. Depending on what your actual requirements are, it's possible that you don't even have to store the translated words, just print them directly to the screen.
Here's the same program, but now it can separate words. Note how the pig latin function doesn't have to change (much, I added upper-case vowels just because I didn't want to bothered converting words) in order for the added functionality to be added.
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>
std::string make_pig_latin(const std::string& word) {
std::string vowels("aeiouAEIOU");
std::string newWord(word);
if (newWord.find_first_not_of(vowels) == 0) {
// Word starts with a consanant
std::rotate(newWord.begin(), newWord.begin() + 1, newWord.end());
newWord += "ay";
} else {
newWord += "way";
}
return newWord;
}
int main() {
std::string phrase(
"A sentence where I say words like apple box easy king and ignore "
"punctuation");
std::istringstream sin(phrase);
std::vector<std::string> words(std::istream_iterator<std::string>(sin), {});
for (auto i : words) {
std::cout << make_pig_latin(i) << ' ';
}
}
Output:
Away entencesay hereway Iway aysay ordsway ikelay appleway oxbay easyway ingkay andway ignoreway unctuationpay

C++ How to check if string starts with char from input

So I want to make a console application that asks you one letter, and a word, and to see if word starts with that letter.
cout<<"Player 1: "<<endl;
cin>> letter;
cin>> word1;
std::string s(word1);
if (s.find(letter) == 0){
std::cout << "String starts with "<< letter<< endl;
}
You need to access first element of the string:
std::string someString = "foo"; // for example purposes
char someChar = 'f';
if (someString[0] == someChar)
std::cout << "First character of this string is " << someChar << "!";
Be careful though, if you fail to read string, you can try to access the first element (with index 0) but it may not exist. Do it like this:
if (someString.length() > 0)
{
// string is not empty. You can use also !someString.empty()
}

Checking string to int error without loops/conditionals

I'm doing a problem on HR and cant figure out how to check for error without using conditional statements. How is this done in C++?
// if string is int output it, else output "Bad string"
// need to do this without any loops/conditionals
int main(){
string S;
char *end;
long x;
cin >> S;
const char *cstr = S.c_str();
x = strtol(cstr,&end,10);
if (*end == '\0')
cout << x;
else
cout << "Bad string";
return 0;
}
Should I be using something besides strtol?
stoi is indeed what you'll want to use.
Given an input in string S one possible way to handle it would be:
try {
cout << stoi(S) << " is a number\n";
} catch(const invalid_argument& /*e*/) {
cout << S << " is not a number\n";
}
Live Example
The violation here is that stoi is only required to cosume the leading numeric part of the string not ensure that the entire string is an int. So "t3st" will fail cause it's not led by a number, but "7est" will succeed returning a 7. There are a handful of ways to ensure that the entire string is consumed, but they all require an if-check.
One way would be:
char const *m[2] = { "Bad string", S.c_str() };
cout << m[*end == '\0'];

Program Closes, cin not working?

char iCharSelect()
{
//CHARACTER CHOICE
cout
<< "\n\n\n Choose Your Stoner:\n\n"
<< "\n 1 = Chris\n"
<< "\n 2 = James\n"
<< "\n 3 = Hunter\n"
<< "\n 4 = Antonio (Alt. Route)\n"
<< "\n\n Enter Character Number: ";
int iChar = INITIALIZED;
cin >> iChar;
//CHARACTER NAME STRING
string sCharName;
//CHARACTER CHECK
if (iChar == 1){sCharName = "Chris";}
else if (iChar == 2){sCharName = "James";}
else if (iChar == 3){sCharName = "Hunter";}
else if (iChar == 4){sCharName = "Antonio";}
else {
cout << "\n\n\n\tYOU GET NOTHING!!";
system("PAUSE>NUL");
//PROGRAM CLOSES HERE-------------------------------------
cout << iChar;
system("PAUSE>NUL");
}
char *chCharName = &sCharName[0];
return *chCharName; }
What am I doing wrong? The program closes at the marked point in the code and trying to print iChar yields nothing..?
I think you should do:
if (ichar == '1')
same for 2,3..
The way you do it, is ask if the char inserted hascii is equal to 1/2.. It does not equal, so you get to the last "if" statement.
You are returning a pointer return *chCharName; but you've labeled the function as char. One of your problems is that you need to label the function to return char*
char* iCharSelect()
The main issue with your code is that you do not set chCharName if none of those conditions in the if() statement are true. If this is the case, you will attempt to return the first character of an empty string, which leads to undefined behavior.
In addition, the end of the function uses pointers when there is no need to use pointers.
A reasonable implementation would look like this:
if ( sCharName.empty())
return '\0';
return sCharName[0];