I keep running into an issue with this code in C++:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string words[25];
int i = 0;
char * word;
cout << "Input a phrase, no capital letters please.";
char phrase[100] = "this is a phrase";
word = strtok (phrase, " ,.");
while (word != NULL)
{
i++;
words[i] = word;
cout << words[i] << " ";
word = strtok (NULL, " ,.-");
int g = 0;
}
cout << endl << endl;
int g = 0;
while (g < i)
{
g++;
char f = words[g].at(0);
if ((f == 'a') || (f == 'e') || (f == 'i') || (f == 'o') || (f == 'u') || (f == 'y'))
{
words[g].append("way");
cout << words[g] << " ";
}
else
{
words[g].erase (0,1);
cout << words[g] << f << "ay" << " ";
}
}
cout << endl;
system("PAUSE");
}
I actually want my program user to generate the phrase to be put in char phrase[100] but I can't figure out the proper syntax to initiate input on it without screwing up the translation.
This is a program that translates phrases into pig latin BTW.
What you want is:
char phrase[100];
fgets(phrase, 100, stdin);
Though, as stated in the comments and other answer, you're using C string functions in C++ and this is very odd. You should not do so unless you are required by an assignment or something.
Instead use:
string input;
getline(cin, input);
To tokenize you can do the following:
string token;
size_t spacePos;
...
while(input.size() != 0)
{
spacePos = input.find(" ");
if(spacePos != npos)
{
token = input.substr(0, spacePos );
input = input.substr(spacePos + 1);
}
else
{
token = input;
input = "";
}
// do token stuff
}
Or, to skip all of that jazz:
string token;
while(cin >> token)
{
// Do stuff to token
// User exits by pressing ctrl + d, or you add something to break (like if(token == "quit") or if(token == "."))
}
The preferred way of doing terminal I/O in C++ are streams. Use std::cin and the std::getline function to read strings from input output.
std::string input;
std::getline(std::cin, input);
After that you probably want to get rid of strtok and look at this question to understand how to do string tokenization in C++.
Related
So I have been searching, but couldn't exactly find a solution for the thing I want to do. Basically User input's a char like "asdasdasd" and I need to go thru each symbol to check if it's 'a', and need to stop the loop after it has reached the end of char. I got this far and it works, it output's the char symbols one by one, but in this case I can't stop the loop, I tried adding another char at the end and make it something specific like "." and use that to stop the loop but then I need to use char o[] which brakes the symbol by symbol thing going on there. Need help.. any input would be appreciated.
#include <iostream>
using namespace std;
int main(){
char o;
cout<<"input: "; cin>>o;
while(o!= '\0'){
cout<<o<<"\n";
cin >> o;
}
return 0;
}
When I understand your question correct you will input a string like "ahobansodfb" and search in there after a specific char? If yes, this is a little example:
#include <iostream>
using namespace std;
int main() {
string input;
char search;
int findPos = 0, countOfSearchedChars = 0;
cout << "input searched char: ";
cin >> search;
cout << "input string: ";
cin >> input;
while((findPos = input.find_first_of(search, findPos)) != string::npos){
cout << "Find searched char on pos: " << findPos << endl;
++findPos;
++countOfSearchedChars;
}
if(countOfSearchedChars == 0)
cout << "Char: " << search << " not found in: " << input << endl;
else
cout << "Char: " << search << " found: " << countOfSearchedChars << " time/s in string: " << input << endl;
}
Explanation for: while((findPos = input.find_first_of(search, findPos)) != string::npos)
input.find_first_of(search, findPos) find the first place where the searched char lies. When the char doesn't found it returns string::npos (18446744073709551615)
So we loop so long the return value is not string::npos: != string::npos
Edit to answer comment question:
Possibilities to iterate through a string:
std::string str = "aabaaba";
for(char& c : str) {
if(c == 'a'){
//it's a
} else if(c == 'b') {
//it's b
}
}
std::string str = "abaaba;
for(std::string::iterator it = str.begin(); it != str.end(); ++it) {
if(*it == 'a'){
//it's a
} else if(*it == 'b') {
//it's b
}
}
For every character in string
THANKS for all the answers!, you were big help, this code will do for me, going to go research what it does x.x
std::string str = "abaaba;
for(std::string::iterator it = str.begin(); it != str.end(); ++it) {
if(*it == 'a'){
//it's a
} else if(*it == 'b') {
//it's b
}
}
I found so incredibly many question posts of this sort - i'm speaking of "convert string to char array" - but none of those solutions actually work for me, trying to convert cin >> text into some char array textArray[1024] which I could then convert into a list cause I think it's easier to work with.
The Problem is: Spaces. Every time when there's a space in there, it just skips the following actions and punches me with my own error messeges.
It's for some encryptor (code down below).
If there's any easier way of doing this then let me know.
#include <iostream>
#include <string>
#include <fstream>
#include <list>
#include "encryptor.h"
using namespace std;
void encrypt()
{
string text;
char textArray[1024];
list<char> listText;
list<char>::iterator it;
int textSize;
string code;
bool fail = false;
string segment;
string fileName;
cout << "Now enter your text. (max 1024 chars)" << endl;
cin >> text;
textSize = text.size();
//string to char[]
//none of these work
strncpy(textArray, text.c_str(), sizeof(textArray));
textArray[sizeof(text) - 1] = 0;
strcpy_s(textArray, text.c_str());
for (int i = 0; i < text.length(); i++)
{
textArray[i] = text[i];
}
aText[text.length()] = '\0';
text.copy(textArray, text.length()+1);
//char[] to list
for(int i = 0; i < textSize; i++)
{
char *c = new char(textArray[i]);
listText.push_back(*c);
}
//Going through list
//for every char there's a special segment added to the string
for(it = listText.begin(); it != listText.end(); it++)
{
if(fail == true) break;
switch (*it)
{
case 'a':
case 'A':
{
segment = "XQ7";
} break;
{/*---*/} //I just let everything from b - z and 0 - 9 out for this post
case ' ':
{
segment = "Z 7";
} break;
case '.':
{
segment = "Z 8";
} break;
case ',':
{
segment = "Z 4";
} break;
default:
{
cout << "There's a special char this program doesn't understand. It is "
cout << *it << endl;
cout << "Do it again" << endl;
fail = true;
} break;
}
code = code + segment;
}
do
{
cout << "\n\nname of the file: ";
cin >> fileName;
if(fileName != "")
{
ofstream write;
write.open(fileName + ".txt");
write << code;
write.close();
} else {
cout << "Name shouldn't be empty!" << endl;
}
} while(fileName == "");
}
Your main issue is not in converting the string text to a character array but it is that you are not capturing the entire line from stdin.
The line cin >> text; will read from stdin until the first whitespace character has been met. That is why you are having issues with spaces. You are only reading characters into text up to the first whitespace character. Instead you need to use getline(). Replacing cin >> text; with getline(cin, text); will read in an entire line from stdin including any whitespace characters.
I've included a complete example to read in a line of text from stdin and convert it to a list of characters for you below. It completely skips the need to convert the string into a character array before converting it into a list.
#include <iostream>
#include <list>
#include <string>
using namespace std;
int main() {
string s;
list<char> text;
getline(cin, s);
for (string::iterator it = s.begin(); it != s.end(); ++it) {
text.push_back(*it);
}
// Verification
cout << "You entered " << text.size() << " characters\nThey were:\n";
for (list<char>::iterator it = text.begin(); it != text.end(); ++it) {
cout << *it;
}
cout << endl;
}
I'm making a software as an ATM, so when the user try to enter the password the user only sees *******, but when trying to delete it doesn't delete a character. It just adds a new one. Here's my code:
string password2 = "";
cout << "PASSWORD: ";
ch = _getch();
while(ch != 13) //character 13 is enter
{
password2.push_back(ch);
cout << '*';
ch = _getch();
}
And also, I try to use pop_back(); but it doesn't work either. Can anybody help me please?
Just did a little magic and created this:
I must admit, I don't like the style... But it "works" !
#include<iostream>
#include<string>
#include <conio.h>
bool verify_pass(const std::string& pass)
{
std::string input = "";
char ch = '0';
while(true)
{
ch = getch();
if(ch == '\b')
{
if(input.size() > 0)
{
input.erase(input.begin() + input.size() - 1); // erase last char
std::cout << "\b \b";
}
}
else if(ch != '\r\n' && ch != '\n' && ch != '\r')
{
input += ch;
std::cout << '*';
}
else
break;
}
return input == pass;
}
int main()
{
std::string insecurePass = "1234";
std::cout << "Enter Password: ";
if(verify_pass(insecurePass))
std::cout << "\nCorrect!\n";
else
std::cout << "\nFalse!\n";
}
By the way, you can use the vector like I used the string, but use push_back instead of += and pop_back() should work too instead of my method with erase.
I am working on a project where I will be able to read in a file that contains any text, like the sample text below. Then, character by character, it will be able to output n-character long sequences (represented below as a read-in value given by the user along the lines of 1, 2, 3, 4...) along the whole length of the text. So, for example:
As Gregor Samsa awoke one morning from uneasy dreams he found himself transformed in his bed into a gigantic insect.
If the user provided 2 as the sequence length, the program should spit out: "As" "s " " G" "Gr" "re" "eg" "go" "or" "r " and so on...
I have written this code but don't know why it won't work. Right now, it doesn't spit out every possible variation of the sequence. Any suggestions would be very helpful. Thanks.
#include "genlib.h"
#include <iostream>
#include <fstream>
#include "simpio.h"
#include "random.h"
#include "vector.h"
#include "map.h"
/* Private Instance Variables */
int seed_length;
string line;
string seed_string;
string next_string;
char ch;
/* Function Prototypes */
string promptUserForFile(ifstream & infile);
int main() {
ifstream infile;
promptUserForFile(infile);
// Ask what order of Markov model to use.
cout << "What order of Markov model should we use? ";
cin >> seed_length;
while (infile.eof() == false) {
ch = infile.get();
for (int i = 0; i < seed_length - 1; i++) {
cout << "ch up here is " << ch << endl;
if (isspace(ch) && i == 0) {
seed_string += ch;
} else {
seed_string += ch;
ch = infile.get();
}
}
next_string = ch;
if (isspace(ch)) {
next_string = " ";
} else {
char trythis = infile.get();
next_string += trythis;
}
cout << seed_string << endl;
cout << next_string << endl;
seed_string = "";
next_string = "";
}
cout << "TEST" << endl;
// Close the file when you're done storing all of the scores.
infile.close();
return 0;
}
string promptUserForFile(ifstream & infile) {
string prompt = "Please input your filename: ";
while(true) {
cout << prompt;
string filename;
getline (cin, filename);
infile.open(filename.c_str());
if(!infile.fail()) return filename;
infile.clear();
cout << "Unable to open that file. Try again." << endl;
if (prompt == "") prompt == "Input file: ";
}
return 0;
}
The code has two problems.
The special handling for isspace is broken:
if (isspace(ch) && i == 0) {
seed_string += ch;
} else {
seed_string += ch;
ch = infile.get();
}
This essentially means that if the first character in this loop is a space, it will be added twice.
Every character received from infile.get() is only added to seed_string once (with the exception of isspace characters).
A better way to code this is to recognize that:
You have to ignore consecutive isspace characters.
Every sequence can be obtained by removing the first character of the preceding sequnce and appending the next character from the file.
Here is a better implementation; it takes the order of the Markov model in the first command line parameter and takes the text from standard input. By encapsulating the skipping of duplicate spaces in a separate function, you don't have to deal with it in the main body of the algorithm.
#include <iostream>
#include <cstdlib>
char next_character() {
static bool was_space = false;
char ret = 0;
do {
ret = std::cin.get();
} while (was_space && std::isspace(ret));
if (std::isspace(ret)) {
was_space = true;
ret = ' ';
} else {
was_space = false;
}
return ret;
}
int main(int argc, char **argv) {
if (argc != 2) return 0;
int mlen = std::atoi(argv[1]);
std::string seq;
for (unsigned i = 0; i < mlen; ++i) {
seq += next_character();
}
std::cout << seq << '\n';
while (true) {
seq.erase(0, 1);
char c = next_character();
if (std::cin.eof()) break;
seq += c;
std::cout << seq << '\n';
}
return 0;
}
Example input:
This is a test
Example output:
This
his i
is is
s is
is a
is a
s a t
a te
a tes
test
I'm a C++ beginner and wrote a program to check if two phrases are anagrams. The characters are being read one at a time and stored in an array. I have everything working, except in some cases, extra characters are being inserted into the array.
For example, if I enter the phrases aabb and abba, this is the output of the program:
Enter two lines that might be anagrams:
--> aabb
--> abba
String A is aabb
String B is abbai?
The two strings are NOT anagrams.
They should be anagrams, but for some reason, i? is added into the array, causing the phrases to not be anagrams. I'm probably overlooking a simple mistake in the code, but would really appreciate any feedback.
Here is the code:
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
int check_anagram(char [], char []);
int main()
{
char ch, a[60], b[60];
int flag, i;
cout << "Enter two lines that might be anagrams:" << endl;
cout << "--> ";
cin.get(ch);
ch = tolower(ch);
i = 0;
while (ch != '\n')
{
if (ch > '#') {
a[i] = ch;
i++;
}
cin.get(ch);
ch = tolower(ch);
}
cout << "--> ";
cin.get(ch);
ch = tolower(ch);
i = 0;
while (ch != '\n')
{
if (ch > '#') {
b[i] = ch;
i++;
}
cin.get(ch);
ch = tolower(ch);
}
flag = check_anagram(a, b);
cout << "String A is " << a << endl;
cout << "String B is " << b << endl;
cout << "The two strings ";
if (flag == 1)
cout << "ARE";
else
cout << "are NOT";
cout << " anagrams." << endl << endl;
return 0;
}
int check_anagram(char a[], char b[])
{
int first[26] = {0}, second[26] = {0}, c = 0;
while (a[c] != '\0')
{
first[a[c]-'a']++;
c++;
}
c = 0;
while (b[c] != '\0')
{
second[b[c]-'a']++;
c++;
}
for (c = 0; c < 26; c++)
{
if (first[c] != second[c])
return 0;
}
return 1;
}
Thanks in advance!
You just need to terminate the two character arrays with '\0' because the logic in check_anagram treats both arrays as NULL-terminated.
..
while (ch != '\n')
{
if (ch > '#') {
a[i] = ch;
i++;
}
cin.get(ch);
ch = tolower(ch);
}
a[i] = '\0'; // <<<<<<<< Add this line
cout << "--> ";
cin.get(ch);
ch = tolower(ch);
i = 0;
while (ch != '\n')
{
if (ch > '#') {
b[i] = ch;
i++;
}
cin.get(ch);
ch = tolower(ch);
}
b[i] = '\0'; // <<<<<<<< Add this line
..
Here is the result:
Enter two lines that might be anagrams:
--> aabb
--> abba
String A is aabb
String B is abba
The two strings ARE anagrams.