I'm currently attempting to implement a substitution cipher that for some reason keeps crashing, the code is fairly straight forward but I keep running into problems I believe originate in the for loop or when I attempt to read in the data from a file.
cout << "Ener a key :";
cin >> key;
cin.ignore();
cout << endl << "Enter input file name: ";
getline(cin,fileIn);
inputfile.open(fileIn.c_str(), ios::in);
cout << endl << "Enter output file name: ";
getline(cin,fileOut);
outfile.open(fileOut.c_str(), ios::app);
cout << endl << "[E]ncryption or [D]ecryption? :";
cin >> EorD;
//Encryption
if (EorD == "E" || "e")
{
while(!inputfile.eof()) // Reading in file data, while not end of file.
{
getline(inputfile,plainText);
}
for (int i = 0; i <= plainText.length(); i++)
{
char letter = plainText.at(i);
int val = (int)letter; // getting ascii value of each letter.
int EnVal = (val - 32) + key;
if(EnVal > 95)
{
EnVal = (EnVal - 95) + 32;
}
char EnLetter = static_cast<char>(EnVal);
outfile << EnLetter;
change
for (int i = 0; i <= plainText.length(); i++)
to
for (int i = 0; i <= plainText.length()-1; i++)
because out of range. Even better use iterator.
also change this:
if (EorD == "E" || "e")
to
if (EorD == "E" || EorD == "e")
because former is always true.
as James Kanze pointed out, don't use std::string::at, you don't need it here, change it to std::string operator[] and my advice: additionally cover your code in a nice try{}catch(...){} block
you might consider something like this:
#include <vector>
#include <iterator>
#include <algorithm>
int key=100;
char op(char c){
char letter = c;
int val = (int)letter; // getting ascii value of each letter.
int EnVal = (val - 32) + key;
if(EnVal > 95)
{
EnVal = (EnVal - 95) + 32;
}
char EnLetter = static_cast<char>(EnVal);
return EnLetter;
}
int main(){
try{
std::string s="piotrek";
std::vector<char> vc_in(s.begin(),s.end());
std::vector<char> vc_out;
std::transform (vc_in.begin(), vc_in.end(),
std::back_inserter(vc_out), op); //this do the thing
std::copy(vc_out.begin(), vc_out.end(),
std::ostream_iterator<char> (std::cout,"_")); // to print
}catch(std::exception& e){
cout<<"exception: "<<e.what();
}
return OK;
}
You are looping one index too far in the plainText string. Since it has length() entries and the first one is 0, the last index is length()-1. Try this:
for (int i = 0; i < plainText.length(); i++)
Otherwise plainText.at(i) will crash when i is too big.
Related
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
int main()
{
char str[100];
cout << "Enter a string : ";
gets(str);
cout << "The words containing y in their last place are : ";
cout << "\n";
for(int i = 0; str[i] != '\0'; i++)
{
int j = i + 1;
if((str[i] == 'y') && (str[j] == ' '))
{
int k;
cout << 134;
char stress[50];
int m = 0;
k = i;
for(; (str[k] != ' ') || (k != 0); k--, m++)
{
stress[m] = str[k];
}
stress[m] = '\0';
int g;
for(g = 0; stress[g] != '\0'; g++)
;
char strain[g];
for(int n = 0, q = k - 1; q >= 0; n++, q--)
{
strain[n] = stress[q];
}
strain[g] = '\0';
for(int p = 0; p < g; p++)
{
cout << strain[p];
}
cout << "\n";
cout << 1;
}
cout << 12;
}
return 0;
}
This c++ program is to display the word containing 'y' as its last letter. I used cout<<12 cout<<1 etc.. to know which part of program is working.
Dont get confused by seeing strain and stress. They are just strings.
I am using codeblocks in windows 7
Upon running the program i get a pop up windows screen saying "prg.exe has stopped working."
Please someone tell me why this error is occuring.
I use codeblocks
I will be really grateful.
You might have errors because of using gets() function, because when you are using gets() you need to know the amount of characters you will get. It was officialy removed by 2011 standart, but almost every C implementation uses it. So to avoid that dangerous function you can use:
getline(), which is very easy to use - like that:
getline(cin,str);
fgets(), it is used like gets, but you need to mention how many characters you will read:
fgets(str, num_of_chars, cin);
As a homework exercise we were asked to use strchr to count the amount of times a single letter appears in a string of text. It needs to count upper or lower cases as equal. It was suggested we use some sort of bit operations.
I managed to get a working program.
But i would like to make the program more interactive by allowing me to use a cin to input the string instead of typing the string directly into the source code (Which was asked by the exercise).
Is it possible to do this? Or is it not possible in the way i wrote this code.
#include <iostream>
#include <cstring>
using namespace std;
int main(){
const char *C = "This is a necesarry test, needed for testing.";
char target = 'A';
const char *result = C;
const char *result2;
int count = 0;
int j[26] ={0};
//================================================================================================================================================
for(int i = 0; i <= 51; i++){
if (i == 26){
target = target + 6;
}
result2 = strchr(result, target);
while(result2 != NULL){
if (result2 != NULL){
result2 = strchr(result2+1, target);
if (i <= 25){
j[i] = j[i] +1;
}
if(i > 25){
j[i-26] = j[i-26] +1;
}
cout << target << "\t";
}
}
cout << target << endl;
target++;
}
char top = 'a';
for(int o = 0; o<= 25; o++){
cout << "________________________________\n";
cout << "|\t" << top << "\t|\t" << j[o] << "\t|" << endl;
top++;
}
cout << "________________________________\n";
}
Simply use getline() to get a string of characters from the console. Using getline you can also consider the spaces in the user input.
string input;
getline(cin, input);
Now to use this with the strchr functionn you simply have to convert this into a C Type string which can be done as follows :
input.c_str
This returns a C type string so you can put this as an arguement to the function,
You will need
#include <string>
When I print out text2 I see that it is definitely not the reverse of the string I gave it and I'm not sure why that is. When I put in "test" I get stuff like "ȍ\2200+". Can I use strncpy on char arrays? Maybe it needs to be done with a loop - not sure. Any help would be appreciated. :)
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char text[79], text2[79];
bool input = true;
while (input) {
cout << "Please give me a line of text to examine: ";
cin.getline(text, 79);
for(int i = 0; i < strlen(text); i++ )
cout << text[i];
// test to see if it is a palindrome
strncpy(text, text2, 80);
reverse(text2, text2 + strlen(text2));
printf("%s", text2); `// when I print this out I get something odd`
if (strcmp(text, text2) == 0)
cout << " is a palindrome!" << endl;
else
cout << " is not a palindrome." << endl;
if (strcmp(text, "END") == 0)
input = false;
else
cout << "\ntype END to exit the program" << endl;
} // end while loop
} // end main
It seems you're using strncpy in a wrong way: you probably want to copy text into text2, not the other way around.
There's a much simpler way to test whether a string is a palindrome, namely:
bool is_palindrome(const char* s, size_t n) {
size_t i, j;
i = 0, j = n-1;
while (i < j && s[i++] == s[j--])
;
return i >= j;
}
Why not use std::vector<char> and std::reverse from <algorithm> to handle your problem?
I would do something like below: (note that I'm using C++11 range-based for loop and auto which you can change to a regular for loop and use std::string line if you don't have a compiler supporting this).
int main()
{
cout << "Please give me a line of text to examine: ";
auto line = ""s;
getline(cin, line);
// Push back every character to the vector
vector<char> vtext;
for (const auto &elem : line)
vtext.push_back(elem);
// Create a copy of the vector<char> and reverse the copy
vector<char> vtext_reversed{vtext};
reverse(begin(vtext_reversed), end(vtext_reversed));
// Print the line reversed
cout << "\nThis is the line reversed: ";
for (const auto &elem : vtext_reversed)
cout << elem;
}
Typically you'll see this reversal technique for char*:
void reverse(char* s) {
if(!s) return;
size_t n = strlen(s);
for(size_t i = 0; i < n/2; ++i) {
char tmp = s[i];
s[i] = s[n - i - 1];
s[n - i - 1] = tmp;
}
}
This will not work, however, with non-ASCII characters. The reason is that non-ASCII characters require multiple bytes to represent.
You will need to use wide characters to handle multi-byte codepoints, but the logic should follow above.
Alright so I've been looking though Google and on forums for hours and can't seem to understand how to solve this problem.
I need to write a program that first determines if the number entered by the user is a base 5 number (in other words, a number that only has 0s, 1s, 2s, 3s, and 4s in it). Then, I have to count how many 0s, 1s, 2s, etc are in the number and display it to the user.
I've seen people saying I should convert int to a string and then using cin.get().
I noticed that I can't use cin.get() on a string, it needs to be a char.
I can only use a while loop for this assignment, no while... do loops.
Any help is appreciated!!
Here's what I have so far, obviously with all my mistakes in it:
//----------------------------------------------
// Assignment 3
// Question 1
// File name: q1.cpp
// Written by: Shawn Rousseau (ID: 7518455)
// For COMP 218 Section EC / Winter 2015
// Concordia University, Montreal, QC
//-----------------------------------------------
// The purpose of this program is to check if the
// number entered by the user is a base of 5
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
// Declaring variables
int number;
int zeros;
int ones;
int twos;
int threes;
int fours;
bool base5;
// Get data and calculate
cin >> number;
string numberString = to_string(number);
// Determine if the number is a base 5 number
while (cin.get(numberString) == 0 || cin.get(numberString) == 1 ||
cin.get(numberString) == 2 || cin.get(numberString) == 3 ||
cin.get(numberString) == 4)
base5 = true;
// Determine the number of each digits
zeros = 0;
ones = 0;
twos = 0;
threes = 0;
fours = 0;
return 0;
}
Several things you need to beware of:
One way to get a specific character from a std::string is by []. e.g.
std::string myString{"abcdefg"};
char myChar = myString[4]; // myChar == 'e'
cin.get(aString) is not trying to get data from aString. It continues to get data from stdin and store in aString. Once you have get the data and put into the string, you can simply manipulate the string itself.
a short piece of code that will count number of vowel in a string. If you can understand it, there should be no problem doing your work. (Haven't compiled, probably some typos)
std::string inputString;
std::cin >> inputString;
// you said you need a while loop.
// although it is easier to with for loop and iterator...
int i = 0;
int noOfVowels = 0;
while (i < inputString.length()) {
if (inputString[i] == 'a'
|| inputString[i] == 'e'
|| inputString[i] == 'i'
|| inputString[i] == 'o'
|| inputString[i] == 'u' ) {
++noOfVowels;
}
++i;
}
std::cout << "number of vowels : " << noOfVowels << std::endl;
Well you can try this approach. This will solve your needs I guess.
#include <iostream>
#include <string>
#include <sstream>
#include <conio.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int number=0;
int zeros=0;
int ones=0;
int twos=0;
int threes=0;
int fours=0;
bool valid=true;;
int counter = 0;
cout<<"Enter the number: ";
cin >> number;
stringstream out;
out << number; //int to string
string numberString = out.str();
cout<<"\n\nNumber after string conversion : "<<numberString;
cout<<"\nPrinting this just to show that the conversion was successful\n\n\n";
while (counter < numberString.length())
{
if (numberString[counter] == '0')
zeros++;
else if(numberString[counter] == '1')
ones++;
else if(numberString[counter] == '2')
twos++;
else if(numberString[counter] == '3')
threes++;
else if(numberString[counter] == '4')
fours++;
else
valid=false;
counter++;
}
if(valid==true)
{
cout<<"\nZeros : "<<zeros;
cout<<"\nOnes : "<<ones;
cout<<"\nTwos : "<<twos;
cout<<"\nThrees : "<<threes;
cout<<"\nFours : "<<fours;
}
else
cout<<"\n\nInvalid data...base of 5 rule violated";
_getch();
return 0;
}
If you don't want to use std::string then use characters, first loop over the input from the user until ENTER is pressed.
char ch = 0;
while ((ch = cin.get()) != '\n')
{
...
}
For each character read, check if it is a digit (std::isdigit) and if it is in the range 0..4, if not quit and give some message of not being base 5
have an array of ints to keep track of the frequency of the digits
int freq[5] = {0,0,0,0,0};
after you have checked that the character is valid subtract the ascii value from the digit and use that as index in the array, increment that:
freq[ch - '0']++;
e.g.
char ch;
int freq[5] = {0};
while ((ch = cin.get()) != '\n')
{
cout << ch;
freq[ch-'0']++;
}
for (int i = 0; i < sizeof(freq)/sizeof(freq[0]); ++i)
{
cout << static_cast<char>(48+i) << ":" << freq[i] << endl;
}
Here's a useful function that counts digits:
// D returns the number of times 'd' appears as a digit of n.
// May not work for n = INT_MIN.
int D(int n, int d) {
// Special case if we're counting zeros of 0.
if (n == 0 && d == 0) return 1;
if (n < 0) n = -n;
int r = 0;
while (n) {
if (n % 10 == d) r++;
n /= 10;
}
return r;
}
In your code you can use this naively to solve the problem without any further loops.
if (D(n, 5) + D(n, 6) + D(n, 7) + D(n, 8) + D(n, 9) != 0) {
cout << "the number doesn't consist only of the digits 0..4."
}
cout << "0s: " << D(n, 0) << "\n";
cout << "1s: " << D(n, 1) << "\n";
cout << "2s: " << D(n, 2) << "\n";
cout << "3s: " << D(n, 3) << "\n";
cout << "4s: " << D(n, 4) << "\n";
You could also (or should also) use loops here to reduce the redundancy.
I’m trying to make something that will take lines of input from the user, separate them into strings in a vector, then print them one at a time (8 per line).
so far this is what I’ve got:
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
int main(void)
{
using namespace std;
vector<string> svec1;
string temp;
while(getline(cin, temp)) //stores lines of text in temp
{
if(temp.empty()) //checks if temp is empty, exits loop if so.
break;
stringstream ss(temp);
string word;
while(ss >> word) //takes each word and stores it in a slot on the vector svec1
{
svec1.push_back(word);
}
}
}
I’m stuck on getting it to print them 8 at a time, the solutions I’ve tried keep getting subscript out of range errors.
Something like this:
for(int i = 0; i < svec1.size(); i++)
{
cout << svec1[i];
if ((i+1) % 8 == 0)
cout << endl;
else
cout << " ";
}
?
EDIT:
the solution above outputs extra space/newline at the end. It can be avoided by something like this:
for(int i = 0; i < svec1.size(); i++)
{
if (i == 0)
/*do nothing or output something at the beginning*/;
else if (i % 8 == 0)
cout << endl; /*separator between lines*/
else
cout << " "; /*separator between words in line*/
cout << svec1[i];
}
Walk over your vector with an index:
for (unsigned int idx = 0; idx < svec1.size(); ++idx) {
std::cout << svec[idx] << sep(idx); // sep(idx) is conceptual; described below
}
What is this sep(idx)? It is the separator to print after the idxth word. This is
A newline after having printed eight words on a line. idx will be 7, 15, 23, etc: One shy of an integer multiple of 8. In code, (idx+1)%8 == 0.
A newline for the last item in the vector; you probably want the last item to be followed with a newline. In code idx+1 == svec.size().
A space otherwise.
An easy way to do this is with the ternary operator:
for (unsigned int idx = 0; idx < svec1.size(); ++idx) {
const char * sep = (((idx+1)%8 == 0) || (idx+1 == svec.size())) ? "\n" : " ";
std::cout << svec[idx] << sep;
}
If you don't like that,
for (unsigned int idx = 0; idx < svec1.size(); ++idx) {
const char * sep;
if (((idx+1)%8 == 0) || (idx+1 == svec.size())) {
sep = "\n";
}
else {
sep = " ";
}
std::cout << svec[idx] << sep;
}
Normally you iterate over a vector using a for loop clause. So if you want to print all elements of your vector<string> you have to make something like this:
for(vector<string>::iterator it = myvec.begin(); it != myvec.end(); ++it) {
cout << *it;
}
EDIT: as Vlad has posted correctly, you can also use array indices, which are less efficient in lists, but equally efficient with vectors.