I have been asked to write a code to print only consonants using a dynamic array. I wrote a code to do that but it prints exactly the input without canceling out the vowels.
#include <iostream>
#include<string>
using namespace std;
int main()
{
int len,i;
cin>>len;
char* pArray=new char[len];
char ch[len];
for(i=0;i<len;i++)
cin>>ch[i];
for(i =0;i<len;i++){
if(ch[i]=='a' && ch[i]=='e' && ch[i]=='i' && ch[i]=='o' && ch[i]=='u')
break;
else
pArray[i]=ch[i];
}
for( i=0;i<len;i++)
cout<<(pArray[i]);
return 0;
}
If I write the input ample, it should print only mpl.
Your program isn't working because of logic error. You have used && operator between each logical expression. So, whenever the compiler come across a character it checks whether the character is 'a' and 'e' and 'i' and 'o' and 'u', which is obviously not possible simultaneously at the same time. Use "||" operator instead of "&&". Also for entering character in pArray you need to define another integer for its index .
int k=0;
for(i =0;i<len;i++){
if(ch[i]=='a' || ch[i]=='e' || ch[i]=='i' || ch[i]=='o' || ch[i]=='u')
break;
else
{pArray[k]=ch[i]; k++;}
doing
for(i =0;i<len;i++){
if(ch[i]=='a' && ch[i]=='e' && ch[i]=='i' && ch[i]=='o' && ch[i]=='u')
break;
else
pArray[i]=ch[i];
}
the test ch[i]=='a' && ch[i]=='e' && ch[i]=='i' && ch[i]=='o' && ch[i]=='u' is always false because a character cannot be several at the same time.
you also need a dedicated index to write in pArray and not print after based on len but that additional index.
Also check cin>>len; success (and other use of >>) else you do with len is 0 and none of the next read success because you do not clear the error flag nor bypass the invalid input.
Note also there are not only vowel and consonant, so when a character is not vowel that does not means it is a consonant, what must be done for other characters ?
Do not use variable length arrays as you did for ch.
Out of that, why are you using array of characters rather than std::string, is it required by statement ?
based on your code minimal changes also managing uppercase character can be :
#include <iostream>
#include <ctype.h>
using namespace std;
int main()
{
int len;
if (!(cin>>len))
cerr << "len is not a number" << endl;
else if (len <= 0)
cerr << "len must be > 0" << endl;
else {
char* pArray = new char[len];
char* ch = new char[len];
int i;
for (i=0;i<len;i++){
if (!(cin>>ch[i])) {
cerr << "EOF, abort" << endl;
return -1;
}
if (!isalpha(ch[i])) {
cerr << "invalid character, abort" << endl;
return -1;
}
}
int j = 0;
for(i =0;i<len;i++) {
switch (ch[i]) {
case 'a':
case 'A':
case 'e':
case 'E':
case 'i':
case 'I':
case 'o':
case 'O':
case 'u':
case 'U':
case 'y': // is vowel no ?
case 'Y': // is vowel no ?
break;
default:
// suppose only consonant and vowel
pArray[j++]=ch[i];
}
}
for( i=0;i<j;i++)
cout<<(pArray[i]);
cout << endl;
}
return 0;
}
Compilation and execution :
pi#raspberrypi:/tmp $ g++ -Wall c.cc
pi#raspberrypi:/tmp $ ./a.out
5
ample
mpl
pi#raspberrypi:/tmp $
There's a few mistakes in your code. I'm feeling generous, see how you get on with this
int main()
{
// read the word
int length;
cin >> length;
char* word = new char[length];
for (int i = 0; i < length; ++i)
cin >> word[i];
// allocate enough space for the word without vowels
char* no_vowels = new char[length];
// copy the non-vowels
int no_vowels_length = 0;
for (int i = 0; i < length; ++i)
{
if (word[i] != 'a' && word[i] != 'e' && word[i] != 'i' && word[i] != 'o' && word[i] != 'u')
{
// found a non-vowel, copy it to the end of the no-vowel word
no_vowels[no_vowels_length] = word[i];
// and increase the length of the no vowel word
++no_vowels_length;
}
}
// write out the word without vowels
for (int i = 0; i < no_vowels_length; ++i)
cout << no_vowels[i];
}
I think the idea you are missing is that you need two variables for the lengths of your two different strings
Quickly fixing the code inline:
every warning(1) error(4) is commented inline.
#include <iostream>
#include<string>
using namespace std;
int main()
{
int len, i;
cin >> len;
char* pArray = new char[len];
char* ch = new char[len];
for (i = 0; i < len; i++)
cin >> ch[i];
//WARNING: please note that pArray NOR ch isn't NULL terminated
int j = 0; //ERROR 1: you need to count the inserted char
for (i = 0; i < len; i++) {
//ERROR 2: you need an OR in order to check for vowels, not an AND
if (ch[i] == 'a' || ch[i] == 'e' || ch[i] == 'i' || ch[i] == 'o' || ch[i] == 'u')
//ERROR 3: if found, do not break, instead skip the vowels...
continue;
else
pArray[j++] = ch[i]; //ERROR 1bis: so you increment the j every time you insert a char
}
for (i = 0; i < j; i++) //ERROR 4: print out only the added lettere, indeed pArray is longer than needed (space for further improvement?)
cout << (pArray[i]);
return 0;
}
Hope it helps,
Stefano
I believe there is a hole in your logic. IMHO, you can't have the same index for the ch (source) array and the pArray (target or destination) array.
Draw out the source and target arrays:
Source (example):
+---+---+---+---+---+
| H | e | l | l | o |
+---+---+---+---+---+
Target:
+---+---+---+---+---+
| | | | | |
+---+---+---+---+---+
After ignoring the e, your Source will be pointing at the first 'l' and your target will be pointing at the 3rd slot in pArray:
Source (example):
+---+---+---+---+---+
| H | e | l | l | o |
+---+---+---+---+---+
0 1 2 3 4
Target:
+---+---+---+---+---+
| H | | l | | |
+---+---+---+---+---+
0 1 2 3 4
In the simple version you will need to have one index that represents the "next" available slot in the target array, and one index that represents the current letter in the source array.
(Or you could use another pointer to the target array and increment that)
char * p_target_slot = pArray;
int target_index = 0;
for(i =0;i<len;i++)
{
if( ch[i]=='a'
|| ch[i]=='e'
|| ch[i]=='i'
|| ch[i]=='o'
|| ch[i]=='u')
continue;
else
{
*p_target_slot++ = ch[i];
// Or you can use this:
pArray[target_index] = ch[i];
++target_index;
}
}
Related
#include <iostream>
using namespace std;
int main() {
char a[101]{0};
cin>>a;
cin.getline(a,101);
cin.ignore();
int currLen{0};
int maxLen{0};
int startInd{-1};
int endInd{-1};
for(int i=0; i<101; i++) {
if(a[i]!=' ' ) {
++currLen;
} else if(a[i]==' '||a[i]=='\0') {
if(currLen>maxLen) {
maxLen=currLen;
startInd=i-currLen;
endInd=i-1;
}
if(a[i]=='\0')
break;
currLen=0;
}
}
cout<<maxLen<<endl;
if(startInd==-1)
cout<<-1;
else
for(int i=startInd; i<=endInd; i++)
cout<<a[i];
return 0;
}
If I take an input here, for example, "My name is Manav Kampani"
It will output 5
Manav instead of 7
Kampani
But if I write "My name is Manav Kampani ", with space after the last word
than it is considering Kampani too printing Kampani.
Also when I input "Kampani Manav is my name" then too it's displaying the wrong output. That means it is not considering the first word of the sentence.
if(a[i]!=' ' )
{
++currLen;
}
else if(a[i]==' '||a[i]=='\0')
{
....
}
Consider the case of a[i] == 0. Which of these if-statements will apply.
Answer: the first one. Which means you'll never look at the final word in the string. You also don't exit at the end of the string, but instead loop through whatever is in your string all the way out to character 101.
As a general structure, be very, very careful with this:
if (condition)
else if (condition)
// without a final else section
If you do that, you need to think about what you're doing. In this particular case, you can have:
if (a[i] != 0 && a[i] != ' ')
else
It may not solve all your issues, but it should solve some.
A nice sliding window pattern implementation.
You have 3 problems in your code
You must not write cin >> a;
You must not write cin.ignore();
You need to modify your if statement like so: if (a[i] != ' ' && a[i] != '\0') Otherwise you will not detect the last word.
Your complete working code with that minor fixes will lokk like that.
int main()
{
char a[101]{ 0 };
//cin >> a;
cin.getline(a, 101);
//cin.ignore();
int currLen{ 0 };
int maxLen{ 0 };
int startInd{ -1 };
int endInd{ -1 };
for (int i = 0; i < 101; i++)
{
if (a[i] != ' ' && a[i] != '\0')// Add comparison
{
++currLen;
}
else if (a[i] == ' ' || a[i] == '\0')
{
if (currLen > maxLen)
{
maxLen = currLen;
startInd = i - currLen;
endInd = i - 1;
}
if (a[i] == '\0')
break;
currLen = 0;
}
}
cout << maxLen << endl;
if (startInd == -1)
cout << -1;
else
for (int i = startInd; i <= endInd; i++)
cout << a[i];
return 0;
}
Additionally. You should not use C-Style arrays in C++. And please use std::string
There is a couple of things here:
1- You don't need to do a cin>>a this is actually consuming the first word, and afterwards the content is overrided by cin.getline(). So removing the firsst cin>>ayou'll be fine.
2- The last word is not read because there isn't any if condition that matches the condition aka.
if(a[i]!=' ' ) case of not a space
//not end of word
else if(a[i]==' '||a[i]=='\0') case of space or null
//end of word
So your last character is not a space nor null, that means you don't detect the last word.
As you can see from the title I want to change lowercase charachter in word to uppercase and vice versa.
Also I need to use struct object (in my case name).
I have a problem when I change charachter from lowercase to uppercase it only changes in the first word not in the second,third and so on. I am also reading words from file
Here is the input file
Aayak Audi
Ahmed Golf7
Samed Golf5
Here is the code
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <cctype>
using namespace std;
struct pismaStr
{
string ime;
string objekat;
};
void malaVelikaSlova (string name)
{
for (int i = 0; i < name.length()-1; i++)
{
if (name.at(i) >= 'A' && name.at(i) <= 'Z')
name.at(i) += 32;
else if (name.at(i) >= 'a' && name.at(i) <= 'z')
name.at(i) -= 32;
cout << name;
break;
}
}
int main()
{
ifstream pismo;
pismo.open("pismo.txt");
ofstream novoPismo;
novoPismo.open("novaSlova.txt");
pismaStr stvari[200];
int brojStvari = 0;
while(pismo >> stvari[brojStvari].ime >> stvari[brojStvari].objekat)
{
brojStvari++;
}
for (int i = 0; i < brojStvari; i++)
{
vector <pismaStr> vec = {pismaStr{stvari[i].ime}};
for (auto obj : vec)
{
malaVelikaSlova (obj.ime);
}
}
Here is the output:
aayak
ahmed
samed
It was:
Aayak
ahmed
samed
I want it to look like this
aAYAK
sAMED
aHMED
How can I fix this?
Any tips?
Tangential,
but it will be an issue, is this line
for (int i = 0; i < name.length()-1; i++)
This will loop from name[0] to name[name.length() - 2]. The std::string::length returns the number of usable characters. It does not include the null terminator, so you don't need to subtract 1. It should be
for (int i = 0; i < name.length(); i++)
Your bigger problem
is the break statement at the end of your loop (indentation added for clarity)
for (int i = 0; i < name.length()-1; i++)
{
if (name.at(i) >= 'A' && name.at(i) <= 'Z')
name.at(i) += 32;
else if (name.at(i) >= 'a' && name.at(i) <= 'z')
name.at(i) -= 32;
cout << name;
break; // <--- this exits the loop entirely
}
Your break; tells the program to exit the loop immediately. No further iterations of the loop are performed. Your cout statement is also within the loop. Once you do get the loop running for each iteration, you'll output each step of the transformation. To only output it once (at the end) you put it outside of the loop. If you want to loop over every character (and you do), your final code looks like
void malaVelikaSlova (string name)
{
for (int i = 0; i < name.length() - 1; i++)
{
if (name.at(i) >= 'A' && name.at(i) <= 'Z')
name.at(i) += 32;
else if (name.at(i) >= 'a' && name.at(i) <= 'z')
name.at(i) -= 32;
}
cout << name;
}
Other things you can change
You don't need to do bounds checking on your string indexes, since you're looping based on the string length, and it's not changing, so you don't need to extra overhead of std::string::at. You can just use the index operator:
// name.at(i); // <-- no need to do this anywhere
name[i] // <-- slightly faster
Since you're applying some operation to each element (character) in your container (string), this is a great candidate for std::transform, from the <algorithm> library. I'm also using a lambda expression here, which is a great too from C++ to get familiar with.
https://en.cppreference.com/w/cpp/algorithm/transform
https://en.cppreference.com/w/cpp/language/lambda
void malaVelikaSlova (string name)
{
std::transform(
name.begin(),
name.end(),
[](char c) -> char
{
if (c >= 'A' && c <= 'Z')
return c + 32;
if (c >= 'a' && c <= 'z')
return c - 32;
return c; // <-- for all other characters
}
);
std::cout << name << "\n";
}
You could even take advantage of the std::isupper, std::islower, std::toupper, and std::tolower functions to make your code more explicit. Note that std::string is an alias for std::basic_string<char> (its value type is char), the upper and lower functions operate on unsigned chars, so you'll need to convert the chars to unsigned chars:
https://en.cppreference.com/w/cpp/string/basic_string
https://en.cppreference.com/w/cpp/string/byte/tolower
https://en.cppreference.com/w/cpp/string/byte/toupper
https://en.cppreference.com/w/cpp/string/byte/isupper
https://en.cppreference.com/w/cpp/string/byte/islower
void malaVelikaSlova (string name)
{
std::transform(
name.begin(),
name.end(),
[](unsigned char c) -> unsigned char // <-- must convert to unsigned to be safe with upper/lower functions
{
if std::isupper(c) return std::tolower(c);
if std::islower(c) return std::toupper(c);
return c; // <-- for all other characters
}
);
std::cout << name << "\n";
}
I am trying to convert input text/numbers (string), which will include any characters, but I want to separate the numbers from the characters and store them into an integer array, once it is converted from a string.
I believe the problem is where the string is converting to an integer by use of stoi(), but I cannot seem to spot the problem.
Currently, the code accepts any input and turns it into a string, the string is then checked character by character, and all the numbers without separation with comma or space is added together, once a comma or space, or any other character separates the number, the number as a whole is added to the array, and then continues to check the string for more numbers.
Any ideas?
Input Example1: 12, 13, 15
Input Example2: 12 13 15
Input Example3: 12ab13cd15ef
Result in integer array: 0[12] 1[13] 2[15]
These numbers will be used in the specific order, by using the numbers within the array.
#include<iostream>
#include<string>
#include <sstream>
using namespace std;
int main()
{
string datainput, str1, str3;
cin >> datainput;
int n = 0, raycount = 0, c;
int myray[10];
while (datainput[n])
{
if (datainput[n] == ('0') || datainput[n] == ('1') || datainput[n] == ('2') || datainput[n] == ('3') || datainput[n] == ('4') ||
datainput[n] == ('5') || datainput[n] == ('6') || datainput[n] == ('7') || datainput[n] == ('8') || datainput[n] == ('9'))
{
str1 = datainput[n];
str3 += str1;
}
else
{
c= stoi(str3);
c >> myray[raycount];
raycount++;
}
n++;
}
cout << myray[0] << endl;
cout << myray[1] << endl;
cout << myray[2] << endl;
cout << myray[3] << endl;
system("pause");
return 0;
}
I see quite a few issues with your code.
Prior to C++11, while (datainput[n]) has undefined behavior once n reaches the end of the string.
The way you are checking for numeric digits can be greatly simplified using std::isdigit(), or even just a simple range check using the >= and <= operators.
You are not correctly accounting for numbers that are separated by other characters, or when the last number in the string is at the very end of the string.
The statement c >> myray[raycount]; needs to be changed to myray[raycount] = c; instead. And you are not breaking your loop if raycount reaches the max capacity of myray[].
You are not resetting str3 back to an blank string after converting it with std::stoi(). You just keep appending new digits to the end of previous digits with no break in between numbers.
With that said, try something more like this instead:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string datainput, str3;
cin >> datainput;
int myray[10];
int raycount = 0;
bool gettingDigits = false;
for (int n = 0; n < datainput.size(); ++n)
{
char ch = datainput[n];
//if (isdigit(ch))
if (ch >= '0' && ch <= '9')
{
if (!gettingDigits)
{
str3 = "";
gettingDigits = true;
}
str3 += ch;
}
else
{
if (gettingDigits)
{
myray[raycount] = stoi(str3);
raycount++;
str3 = "";
gettingDigits = false;
if (raycount == 10) break;
}
}
}
if (gettingDigits && (raycount < 10))
{
myray[raycount] = stoi(str3);
raycount++;
}
for (int n = 0; n < raycount; ++n)
cout << myray[n] << endl;
system("pause");
return 0;
}
Live Demo
Alternatively:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string datainput, str3;
cin >> datainput;
int myray[10];
int raycount = 0;
string::size_type start = datainput.find_first_of("0123456789");
string::size_type end;
while (start != string::npos)
{
end = datainput.find_first_not_of("0123456789", start+1);
if (end == string::npos)
{
str3 = datainput.substr(start);
myray[raycount] = stoi(str3);
raycount++;
break;
}
str3 = datainput.substr(start, end-start);
myray[raycount] = stoi(str3);
raycount++;
if (raycount == 10) break;
start = datainput.find_first_of("0123456789", end+1);
}
for (int n = 0; n < raycount; ++n)
cout << myray[n] << endl;
system("pause");
return 0;
}
Live Demo
So, you want to segregate numbers and characters into different arrays.
In if block, you are checking for characters, so, I suspect stoi() wouldn't work.
Better typecast it to an integer.
int temp[10];
if (datainput[n] == ('0') || ...) {
temp[n] = int(datainput[n]);
}
This way your temp array would contain the numbers.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
#include <iostream>
using namespace std;
int main()
{
int a = 0, skrb = 0, j = 0;
char b, simboliai[2000];
char zodis[50][20];
char check[1][20] = {'f'};
cout << "Prasome irasykite sakini: ";
cin.getline(simboliai,sizeof(simboliai));
//----------------- Zodziu skaidymas ----------------------------------------------------------------------------------------------------------
a = 0;
for (int i = 0; i > -1; i++)
{
if ((simboliai[i] == 's' && simboliai[i++] == ' ') || (simboliai[i] == 's' && simboliai[i++] == '\n'))
{
check[0][a] = 't';
}
if (simboliai[i] == ' ')
{
a++;
}
else
{
zodis[i][a] = simboliai[i];
}
if (simboliai[i] == '\n')
{
break;
}
}
a = 0;
while (1)
{
if (simboliai[a] == '.' || simboliai[a] == ',' || simboliai[a] == '!' || simboliai[a] == '?')
{
skrb++;
}
a++;
if (simboliai[a] == '\n')
{
break;
}
}
a = 0;
cout << "Jus ivedete tokius zodius kurie baigiasi raide 's'" << endl;
while(1)
{
if (zodis[j][a] == 'Ì')
{
cout << '\n';
a++;
}
if (check[0][a] == 't')
{
cout << zodis[j][a];
}
if (zodis[0][a] == 'Ì')
{
break;
}
}
cout << "Pas jus yra (.','!'?) simboliu: " << skrb << endl;
cin.ignore();
cin.get();
}
Basically this program would work but that for part just ruins everything. It doesn't put characters one by one. And when I debug it shows that program have put symbol in its place but then there is Ì.
So it looks just like so
input: word word
zodis[0][0] goes like wÌÌÌÌÌÌÌÌÌÌ zodis [1][0] goes oÌÌÌÌÌÌÌÌÌÌ and so on and it breaks. Thank you in advance.
If you are saying the for loop wouldn't put characters 1 by 1, it was in your "simboliai[i++] == ' '" logic. integer 'i' been incremented twice each loop when current character is 's' which mean it will be incremented from i=2 to i=4 if simboliai[i] = 's'. Use i+1 instead for your checking.
for (int i = 0; i > -1; i++)
{
...
}
is the main problem. There might be others but I don't look too closely for them.
The values of i will be 0, 1, 2. etc.
All of them are greater than -1.
The loop will go on until the value i reaches INT_MAX. (Not sure what happens when i is incremented at that time).
That is way larger than the size of the array simboliai anyway. Your program will access the array simboliai beyond valid limits and cause undefined behavior.
I think what you need is:
size_t len = strlen(simboliai);
for (size_t i = 0; i < len; i++)
{
...
}
Other Problems
Some of the errors result from the assumption that there is a newline character in simboliai. That assumption is not correct. std::istream::getline reads and discards the newline character.
If Google Translate is correct, zodis is supposed to contain a list of words. When you are iterating over the characters of simboliai, you need three counters.
One to iterate over the characters of simboliai.
One to keep track of the number words.
One to keep track of the number of characters in the current word.
Your for loop is not doing that.
When you are trying to access the contents of an array, you need to always write defensive code and make sure that you never access the array using out of bounds indices. In the last while loop, you are not doing that.
In the last while loop, you are incrementing a only in the first if block. If the conditional of that if statement evaluates to false, a never gets incremented and you get stuck in an infinite loop.
In the last loop you use j as an index but its value is initialized to 0 at the start of the function and never gets updated. It's not clear what the intent of the last while loop is. Hence, I can't say whether it's a bug but it sounds like it could be.
Here's a cleaned up version of your posted code with still a few unknowns.
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int a = 0, skrb = 0, j = 0;
char b, simboliai[2000];
char zodis[50][20];
char check[1][20] = {'f'};
cout << "Prasome irasykite sakini: ";
cin.getline(simboliai,sizeof(simboliai));
//----------------- Zodziu skaidymas ----------------------------------------------------------------------------------------------------------
int word_counter = 0;
a = 0;
size_t len = std::strlen(simboliai);
for (size_t i = 0; i < len; i++)
{
if ((simboliai[i] == 's' && simboliai[i+1] == ' ') || (simboliai[i] == 's' && simboliai[i+1] == '\0'))
{
check[0][a] = 't';
}
if (simboliai[i] == ' ')
{
zodis[word_counter][a] = '\0';
a = 0;
++word_counter;
}
else
{
zodis[word_counter][a] = simboliai[i];
++a;
}
}
a = 0;
while ( simboliai[a] != '\0' )
{
if (simboliai[a] == '.' || simboliai[a] == ',' || simboliai[a] == '!' || simboliai[a] == '?')
{
skrb++;
}
a++;
}
a = 0;
cout << "Jus ivedete tokius zodius kurie baigiasi raide 's'" << endl;
while( j < 50 && a < 20 )
{
if (zodis[j][a] == 'Ì')
{
cout << '\n';
}
if (check[0][a] == 't')
{
cout << zodis[j][a];
}
if (zodis[0][a] == 'Ì')
{
break;
}
a++;
}
cout << "Pas jus yra (.','!'?) simboliu: " << skrb << endl;
cin.ignore();
cin.get();
}
I have the following code. It's supposed to count the number of repetitions of the given letter in a given file. However, when i try to run this i get the Vector subscript out of range. Other people with the same error were trying to access undefined parts of it, but this doesn't seem to be an issue here i think.
struct letters
{
char letter;
int repetitions=0;
};
void howManyTimes(const string &output)
{
ifstream file(output);
vector <letters> alphabet;
for (int i = 0; i < 'z' - 'a' + 1; i++)
{
alphabet[i].letter = 'a' + i;
}
string line;
while (file.eof() == 0)
{
getline(file, line);
for (char c : line)
{
if(c >= 'a' && c <= 'z')
alphabet[c - 'a'].repetitions++;
else if (c >= 'A' && c >= 'Z')
alphabet[c - 'A'].repetitions++;
}
}
cout << alphabet[10].repetitions;
}
vector <letters> alphabet; // (1)
for (int i = 0; i < 'z' - 'a' + 1; i++)
{
alphabet[i].letter = 'a' + i; // (2)
}
(1) creates an empty vector.
Inside the for loop in (2) you try to access items using the index i in an empty vector, so clearly your index is out of range.
You first have to populate the vector with some data, then you can access this data.
If you want to add new items to the vector, you can use vector::push_back (which is probably what you meant in (2)).
I don't see the part of your code where alphabet is expanded to accommodate the objects you plan to store in it. std::vector only resizes itself when you use the push_back, insert, emplace or other similar methods; it doesn't do so when accessing directly using the operator[] method.
At any rate, for a task like this, I'm not sure you'd want to use a vector, when a std::map<char, int64_t> would probably be a lot cleaner, and would let you preserve the syntax you're trying to use without tons of extra maintenance.
void howManyTimes(const string &output)
{
ifstream file(output);
map<char, int64_t> alphabet;
string line;
while (getline(file, line))
{
for (char c : line)
{
if(c >= 'a' && c <= 'z')
alphabet[c - 'a']++;
else if (c >= 'A' && c >= 'Z')
alphabet[c - 'A']++;
}
}
cout << alphabet[10];
}
Other people with the same error were trying to access undefined parts of it, but this doesn't seem to be an issue here I think.
It is definitely an issue here:
vector <letters> alphabet; // Now size of the vector is 0.
for (int i = 0; i < 'z' - 'a' + 1; i++)
{
// You are trying to access elements 0, 1, 2, ..., which do not exist.
alphabet[i].letter = 'a' + i;
}
The simplest solution is to construct your vector with appropriate size:
vector <letters> alphabet('z' - 'a' + 1);
This program is really powerful for what the question is asking (makes me wonder how my students felt when I gave it as a homework assignment :) ). Do you have to use a struct? Let's assume not, and also assume we know the size of the alphabet, and that 'a' is the first letter and 'z' is the last letter:
vector<int> repetitions(26, 0);
char nextCharacter;
while( !file.eof() )
{
cin >> nextCharacter;
nextCharacter = tolower(nextCharacter);
if(nextCharacter >= 'a' && nextCharacter <= 'z')
{
repetitions[nextCharacter - 'a']++;
}
}
To check for a letter:
cin >> letterToQuery;
cout <<"The amount of occurrences of " << letterToQuery <<" is ";
cout << repetitions[tolower(letterToQuery) - 'a'] << endl;
If you don't know the size of your alphabet, the code changes to:
vector<int> repetitions('last_alphabet' - 'a' + 1, 0);
...
if(nextCharacter >= 'a' && nextCharacter <= 'last_letter')
And finally, if you DO have to use that struct, your code changes to:
struct Letter
{
char letter;
int repetitions=0;
};
vector<Letter> alphabet;
letter temp;
for(int i = 0; i < 'last_alphabet' - 'a' + 1; ++i)
{
temp.letter = 'a' + i;
alphabet.push_back(temp);
}
// then everything else is a similar structure
char nextCharacter;
while( !file.eof() )
{
cin >> nextCharacter;
nextCharacter = tolower(nextCharacter);
if(nextCharacter >= 'a' && nextCharacter <= 'last_alphabet')
{
alphabet[nextCharacter - 'a'].repetitions++;
}
}
To check for a letter:
cin >> letterToQuery;
cout <<"The amount of occurrences of " << letterToQuery <<" is ";
cout << alphabet[tolower(letterToQuery) - 'a'].repetitions << endl;
Notice, if you replace 'last_alphabet' with 'z', you get the current alphabet.