how to subtract first and last letter of a string - c++

First of all i am new in programming.
I was asked to create a program that prompts the user to insert a word and then I translate it into some sort of fake language.
So i make the following:
firstLetter of the new word is the last char of the original word
secondLetter is ncy
thirdLetter is the entered word without the first and last char
fourthLetter is nan
fifthLetter is the first character of the word
e.g. user enters= dog
new word is: gncyonand
My code is this but its failing and I assume is because the string does not exist yet(the user still has to insert it). Please help:
**
#include <iostream> //for cin and cout
#include <string> //for string data
using namespace std;
int main()
{
//I add a welcome message:
std::cout << "*************************************************\n"
<< " Welcome to Nacy-latin converter program\n"
<< "*************************************************\n\n";
// I declare first string:
std:: string userWord; //the word the user imputs
std::string firstLetter= userWord.substr(-1,0); //last char of the entered word
std::string secondLetter = "ncy";
std::string thirdLetter= userWord.substr(1, userWord.length() - 1); //last char of the entered word
std::string fourthLetter = "nan"; //just nan
std::string fifthLetter= userWord.substr(0,1); ; //the first char of the userWord
//I ask the user to imput data:
cout << "Hey there!";
cout << endl<<endl;
cout << "Please enter a word with at least two letters and I will converted into Nacy-latin for you:\n";
//return data to the user:
cout<<"The word in Nancy-Latin is:" <<firstLetter << secondLetter << thirdLetter <<fourthLetter <<fifthLetter<<'\n';
// Farewell message
cout << "\nThank you for the 'Nancy-latin' converter tool!\n";
// system(“pause”);
return (0) ;
}
**

Did you use Python before? std::string does not allow negative indexes. You can use a mix of front(), back(), and substr() string methods to get individual pieces and then use the C++ class std::stringstream to build your new string.
std::stringstream ss;
ss << userWord.back() << "ncy";
ss << userWord.substr(1, userWord.size() - 2);
ss << "nan" << userWord.front();
std::cout << ss.str();
Do not forget to check user input for at least two characters.
Alternative to make new word in place.
std::swap(userWord.front(), userWord.back());
userWord.insert(1, "ncy");
userWord.insert(userWord.size() - 2, "nan");
std::cout << userWord;

Related

C++ executes blanks after class creation

I'm trying to learn C++ to help my sibling with their assignment. So I'm attempting the assignment. It's a simple program to load a dictionary test file with words, their type, and definition to an array of Word type objects. I was able to get started with a normal string array instead of an object array as requested. But as soon as I defined the Word class and the array the code builds without an issue. When I try to run the code the cursor simply blinks for a few seconds and returns to the normal terminal.
Am I doing something wrong with my Class constructor ??
#include <fstream>
#include <string>
using namespace std;
class Word {
public:
string WordEntry;
string Type;
string Definition;
//constructor
Word(string word, string type, string definition){
WordEntry=word;
Type=type;
Definition=definition;
}
};
int main(){
cout << "Test1";
Word *wordArray[318555];
int count=0;
string word, type, definition,blank;
cout << "TEST" << count << "\n";
ifstream file("dictionary2021 (1).txt");
if (file.is_open()){
cout << "File dictionary2021.txt has been opened \n";
while (!file.eof()){
getline(file,word);
getline(file,type);
getline(file,definition);
getline(file,blank);
wordArray[count]= new Word(word,type,definition);
count++;
}
file.close();
cout << "File dictionary2021.txt has " << count/3 << " entries\n";
}
cout << "TEST" << count << endl;
cout << cc;
int selection;
string input;
cout << "Function List - Please hit Enter after your selection \n";
cout << " 1. Word Search \n 2. Repetitive z search \n 3. Wild Card Search\n";
cout << "Selection:";
cin >> selection;
if(selection=1){
cout << "Enter word:\n";
cin >> input;
string str("a");
for (int i = 0; i < 12; i+3)
{
cout << "1";
if (input.compare(str)== 0)
{
cout << wordArray[i+1];
return 0;
}
cout << "2";
}
}
}```
Word* wordArray[318555]; is a huge value and we're talking about 2548440 bytes (or roughly 2.4MB). This might be too large for a single stack frame and can easily be inefficient.
What I suggest is to use std::vector to store the word array and use std::vector<>::push_back() method to insert data to it.
Note: In your code snippet your not deallocating the Word object pointers once everything is done. Either explicitly delete those pointers using delete or use a smart pointer like std::unique_ptr.

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()
}

NOTE:(getline was not the issue) C++ getline() stops working in user defined function but works in main function

NOTE: SOLVED, problem was not getline() but find function with an
Improperly filled array!
I've looked up several questions before posting my own, but I could not find an answer for my problem. This is my first question posted, but I did do some research and tried other solutions from other questions before posting my own. So I am not entirely sure this isn't a duplicate. My apologies! Thank you for understanding in advance!
I am trying to use getline() (c++) to get user input. It works fine in my main, but does not in my user defined function. I thought it might have to do with the buffer, so i used cin.ignore() as suggested in:
C++ getline method not working
and i checked:
How does getline work with cin?
to make sure I properly understood getline(). However my program still does not work correctly.
My program takes English Text as a string from user input (console input) and converts it into Morse Code and outputs result as a string (console output).
basically my problem is this:
getline works in my main function for both strings and strings with spaces ex: "This" and "This Code".
However, in my user defined function, it ONLY works for strings without spaces ex: "This".
Thanks for the help! Code snippets below!
#include <iostream>;
#include <stdio.h>;
#include <ctype.h>;
using namespace std;
string textToMorse(const string alphabet, const string morseAlphabet[]);
int main()
{
const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,?";
const string morseAlphabet[39] = {".-","-...","-.-.","-..",".","..-.","--.","....","
..",".---","-.-",".-..","--","-.","---",".--.",
"--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---",
"...--","....-",".....",
"-....","--...","---..","----.",".-.-.-","--..--","..--.."};
int userSelection;
string resultString;
cout << "TEXT TO MORSE CODE or MORSE CODE TO TEXT program" << endl << endl;
cout << "Please select an option by typing the integer shown: " << endl << endl;
cout << "Type(Selects option) 1 to decode Morse code to English text" << endl;
cout << "Type(Selects option) 2 to encode English text to Morse code" << endl;
cout << "Type(Select option) any other integer that is NOT 1 or 2 to QUIT" << endl << endl;
cin >> userSelection;
while(userSelection == 1 || userSelection == 2)
{
if(userSelection == 1)
{
resultString = textToMorse(alphabet, morseAlphabet); // function where I use
// getline() but does not work
cout << endl << "This is the Morse code decoded to English text: " << endl << endl;
cout << resultString << endl << endl << endl << endl;
}
}
return 0;
}
// does not work
string textToMorse(const string alphabet, const string morseAlphabet[])
{
string userInput;
cout << endl << "Enter English text to encode to Morse code,
with only a space between words: " << endl << endl;
cin.ignore();
getline(cin,userInput); //code works with strings without spaces,
//but breaks with others. ex: "This" works as input
//but "This code" breaks and the console seems to freeze
// then crashes out
cin.clear();
// rest of code, but program breaks before this.
string encodedEnglishText = "";
for(int i = 0; i < userInput.length(); i++)
{
userInput[i] = toupper(userInput[i]);
}
for(int i = 0; i < userInput.length(); i++)
{
encodedEnglishText += morseAlphabet[alphabet.find(userInput[i])];
encodedEnglishText += " "; // extra spacing added for output clarity
if(userInput[i] == ' ')
{
encodedEnglishText += " "; // extra spacing added for output clarity
}
}
return encodedEnglishText;
}
However if I edit my code and get the input from my main and pass it in as a parameter, it works.
#include <iostream>;
#include <stdio.h>;
#include <ctype.h>;
using namespace std;
string textToMorse(const string alphabet, const string morseAlphabet[], string userInput);
int main()
{
const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,?";
const string morseAlphabet[39] = {".-","-...","-.-.","-..",".","..-.","--.","....","
..",".---","-.-",".-..","--","-.","---",".--.",
"--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---",
"...--","....-",".....",
"-....","--...","---..","----.",".-.-.-","--..--","..--.."};
int userSelection;
string resultString;
cout << "TEXT TO MORSE CODE or MORSE CODE TO TEXT program" << endl << endl;
cout << "Please select an option by typing the integer shown: " << endl << endl;
cout << "Type(Selects option) 1 to decode Morse code to English text" << endl;
cout << "Type(Selects option) 2 to encode English text to Morse code" << endl;
cout << "Type(Select option) any other integer that is NOT 1 or 2 to QUIT" << endl << endl;
cin >> userSelection;
while(userSelection == 1 || userSelection == 2)
{
if(userSelection == 1)
{
string userInput;
cout << endl << "Enter English text to encode to Morse code,
with only a space between words: " << endl << endl;
cin.ignore();
getline(cin,userInput); //code works with both "This" and "This code"
cin.clear();
resultString = textToMorse(alphabet, morseAlphabet, userInput); //function modified
//to take one more
//parameter
cout << endl << "This is the Morse code decoded to English text: " << endl << endl;
cout << resultString << endl << endl << endl << endl;
}
}
return 0;
}
string textToMorse(const string alphabet, const string morseAlphabet[], string userInput)
{
//code, but program works.
string encodedEnglishText = "";
for(int i = 0; i < userInput.length(); i++)
{
userInput[i] = toupper(userInput[i]);
}
for(int i = 0; i < userInput.length(); i++)
{
encodedEnglishText += morseAlphabet[alphabet.find(userInput[i])];
encodedEnglishText += " "; // extra spacing added for output clarity
if(userInput[i] == ' ')
{
encodedEnglishText += " "; // extra spacing added for output clarity
}
}
return encodedEnglishText;
}
I didn't include all of the code, just the parts I felt were relevant to the question.
by works I mean:
getline successfully takes input. getline successfully assigns a string such as "this" and "this code" to the variable userInput when used in main function.
it only successfully assigns strings without spaces such as "this" when used in my user defined function. In that function, for some reason it does not work when I enter a string like "this code" or any string with a space inbetween.
note: program is not finished, as I plan to add other methods to do the reverse (as seen in code with
extra user options, but these are not yet implemented or defined, code still runs and compiles for problem I am facing.
The problem is that there is no morse code for a space.
Make a verification:
int n = alphabet.find(userInput[i]);
encodedEnglishText += (n == string::npos) ? " ": morseAlphabet[n];
Then it will work.
When you are looking for your input character in the alphabet string you won't find ' ' and std::string::find() return std::string::npos (normally -1 converted to the type std::string::size_type but the value isn't guaranteed). Using this value to index morseAlphabet won't do you much good: it is undefined behavior. This problem does not arise when you enter just one string as all characters are found in alphabet.
The proper way to deal with the situation is to look for the character and capture the result. Before using the result, you'd test the input, e.g.:
std::string::size_type pos(alphabet.find(userInput[i]));
if (pos == std::string::npos) {
// deal with the character not being part of the alphabet
}
else {
encodedEnglishText += morseAlphabet[pos];
}
Note that there are a few other things wrong with your program:
The selection of options should be inside the loop! The way it is implemented entering, e.g. 2 results in an infinite loop.
Using std::toupper() with a char can also result in undefined behavior! The problem is that std::toupper() expects a non-negative value of the value EOF but char may be signed. To avoid this problem you should use any of the functions from <cctype> or <ctype.h> with unsigned char:
userInput[i] = toupper[static_cast<unsigned char>(userInput[i]));
If the user doesn't enter an integer but, e.g., foo reading userSelection will fail and stream will get into failure state where it won't do anything until std::cin.clear() is entered. The best approach to deal with this situation is to test the result of reading the value before doing anything. If the input failed you can recover from the situation by clearing the status and skipping the offending character, e.g.:
if (std::cin >> userSelection) {
// use the selection
}
else {
std::cout << "ignoring invalid input\n";
std::cin.clear();
std::cin.ignore();
}
Note that your use of std::cin.clear() should be needed. Also, you should verify that the input you read with std::getline() is successful: in general, all user inputs should be tested for success.
If you enter a space character after the integer when reading userSelection, your call to std::cin.ignore() will ignore this space not the newline! To avoid this problem you could either read all charactors up to the first newline or skip all whitespace prior to the non-whitespace character:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // all till newline
std::cin >> std::ws; // skip all whitespace to first non-whitespace character
Do not use std::endl! It does not only create a newline but it also flushes the stream. This can easily create a performance problem.
You should probably pass std::string arguments by reference rather than by value. Passing the argument alphabet by value creates a copy with is inefficient (the morseAlphabet argument is passed by pointer although it looks like an array).
Some string literals seem to be split across multiple lines. Doing so is illegal (I guess, however, that this problem was introduced when pasting the code to the question above at some point).

How I can manage to keep white space in my String from user input

I'm coding a little console application in C++ and in it I take a string from the user:
cin >> themainstring;
int si = 0;
while (themainstring[si] != '+' || themainstring[si] != '-' ||
themainstring[si] != '*') {
if (themainstring[si] == '+' || themainstring[si] == '-' ||
themainstring[si] == '*') {
lmnopt = themainstring[si];
break; // while
}
si++;
}
int strlenthestring = themainstring.size();
lmnop1 = themainstring.substr(0, si);
lmnop2 = themainstring.substr(si + 1, strlenthestring);
So for example, when I give this input:
ilove+programming
I want to try and cut the string when I see +, - and *. which works fine.
However I want my code to do the same when I input:
ilove + programming (white spaces after and before arithmetical operator)
I have messed around with the WS but I couldn't understand the logic.
Actually the main problem of mine is about C++'s space logic. Why it thinks the space will explode the string input?
I'm not sure I've understood this question completely correctly, however I thought I'd pitch in with some help.
First off, when it comes to looking through strings, C++ has a great set of functions as standard that does that. Point your browser to: Basic String Library.
This contains all the functions you can carry out on a string in C++.
Secondly, something else you need to be aware of, is that you are using std::cin to read user input from the keyboard. By default, cin ignores white spaces, so for example, the following code:
string inputString;
cin >> intputString;
cout << "Input String is: " << inputString << endl;
and let's assume you entered Hello World in as your user input, the program would only output "Hello"
So what you need to do is to use getline. Which allows for whitespaces in your user inputs. And you use it as follows:
std::getline(cin, inputString);
So to give an example where it all gels together:
#include <iostream>
#include <sstream> // for istringstream
#include <string>
using namespace std;
int main(int argc, char * argv[])
{
string inputString;
cout << "Please Enter String: ";
getline(cin, inputString);
cout << "\n" << endl;
cout << "InputString is: " << inputString << endl;
// So you can do something like this
string searchTerm("+");
// Find first of is an operating you can carry out
// on a string so you don't have to use loops.
cout << "Position: " << inputString.find_first_of(searchTerm) << endl;
int pos = inputString.find_first_of(searchTerm);
string part1 = inputString.substr(0, pos);
string part2 = inputString.substr(pos + 1, inputString.length());
cout << "Position of + is " << pos << endl;
cout << "part 1 is: " << part1 << endl;
cout << "part 2 is: " << part2 << endl;
}
Now I know I've only done this with the + sign, but it should serve as a starting point to getting to where you want to be.
Hope all this helps.

c++ c-strings, strncat, strncpy

This program is supposed to input someones name and output it like " Last, first middle". The names are supposed to be stored in 3 different arrays and their is a fourth array for the full name at the end. I am also supposed to use strncpy and strncat to build the fourth array. My issue im having is i dont know what the use of strncpy would be in this situation and how to use it. I can make the program say "first middle last" but not the correct output. Another issue im having is the while loop is supposed to allow the user to say 'q' or 'Q' and quit the program but it doesnt do this
#include <iomanip>
#include <iostream>
#include <cctype>
using namespace std;
int main()
{
char replay; //To hold Q for quit
const int SIZE = 51;
char firstName[SIZE]; // To hole first name
char middleName[SIZE]; // To hold middle name
char lastName[SIZE]; // To hold last name
char fullName[SIZE]; //To hold the full name
int count = 0;
int maxChars1;
int maxChars2;
cout << "Enter Q to quit or enter your first name of no more than " << (SIZE - 1)
<< " letters: ";
cin.getline(firstName, SIZE);
while(firstName[SIZE] != 'Q' || firstName[SIZE] != 'q')
{
cout << "\nEnter your middle name of no more than " << (SIZE - 1)
<< " letters: ";
cin.getline(middleName, SIZE);
cout << "\nEnter your last name of no more than " << (SIZE - 1)
<< " letters: ";
cin.getline(lastName, SIZE);
maxChars1 = sizeof(firstName) - (strlen(firstName) + 1);
strncat(firstName, middleName, maxChars1);
cout << firstName << endl;
maxChars2 = sizeof(lastName) - 1;
strncpy(firstName, lastName, maxChars2);
lastName[maxChars2] = '\0';
cout << lastName << endl;
}
system("pause");
return 0;
}
Your while loop doesn't work because of several reasons:
You're actually looking one past the end of the firstName array (firstName[SIZE]) rather than the first character (firstName[0]).
You're not checking to make sure firstName is only a single character q or Q.
You're only asking for the first name one time, before the loop, instead of every loop.
Your call to strncpy doesn't look right. As written, you're taking the last name and copying it to firstName, destroying the first and middle names that you just concatenated together there. Like #steve-jessop said, assemble the full name in fullName.
You're probably supposed to use strncpy and strncat because this is a contrived example/exercise where the buffer taking the full name is of a restricted size, so some name combinations will not fit, and need to be truncated.