Here is my code that I got it doesn't work it reads zero for everything please help i thought -1 is for the last string in the character. I need the program to report the number of words whose last letter is 'a', the number of whose last letetr is 'b' and so on that is irrespective of case. Here is my code below and I need help fixing it.
#include <string>
#include <iostream>
#include <fstream>
#include <cassert>
#include <cstring>
using namespace std;
int main(void)
{
int aCtr = 0, bCtr = 0, cCtr = 0, dCtr = 0, eCtr = 0, fCtr = 0, gCtr = 0, hCtr= 0, iCtr = 0, jCtr = 0, kCtr = 0, lCtr = 0, mCtr = 0, nCtr = 0, oCtr = 0, pCtr = 0, qCtr = 0, rCtr = 0, sCtr = 0, tCtr = 0, uCtr = 0, vCtr = 0, wCtr = 0, xCtr = 0, yCtr = 0, zCtr = 0;
string inputFileName; //Declare variables
string s; //for storage
ifstream fileIn; //and file handling
cin >> inputFileName;
fileIn.open(inputFileName.data());
assert(fileIn.is_open() );
while (fileIn>>s)
{
if(isalpha(s[-1]))
{
if((s[-1]=='a') || (s[-1]=='A'))
{
aCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='b') || (s[-1]=='B'))
{
bCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='c') || (s[-1]=='C'))
{
cCtr ;
}
}
}
{
if(isalpha(s[-3]))
{
if((s[-3]=='d') || (s[-3]=='D'))
{
dCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='e') || (s[-1]=='E'))
{
eCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='f') || (s[-1]=='F'))
{
fCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='g') || (s[-1]=='G'))
{
gCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='h') || (s[-1]=='H'))
{
hCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='i') || (s[-1]=='I'))
{
iCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='j') || (s[-1]=='J'))
{
jCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='k') || (s[-1]=='K'))
{
kCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='l') || (s[-1]=='L'))
{
lCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='m') || (s[-1]=='M'))
{
mCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='n') || (s[-1]=='N'))
{
nCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='o') || (s[-1]=='O'))
{
oCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='p') || (s[-1]=='P'))
{
pCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='q') || (s[-1]=='Q'))
{
qCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='r') || (s[-1]=='R'))
{
rCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='s') || (s[-1]=='S'))
{
sCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='t') || (s[-1]=='T'))
{
tCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='u') || (s[-1]=='U'))
{
uCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='v') || (s[-1]=='V'))
{
vCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='w') || (s[-1]=='W'))
{
wCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='x') || (s[-1]=='X'))
{
xCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='y') || (s[-1]=='Y'))
{
yCtr ;
}
}
}
{
if(isalpha(s[-1]))
{
if((s[-1]=='z') || (s[-1]=='Z'))
{
zCtr ;
}
}
}
cout<<"\nThere are "<<aCtr<<" words that end with A or a."<<endl;
cout<<"\nThere are "<<bCtr<<" words that end with B or b."<<endl;
cout<<"\nThere are "<<cCtr<<" words that end with C or c."<<endl;
cout<<"\nThere are "<<dCtr<<" words that end with D or d."<<endl;
cout<<"\nThere are "<<eCtr<<" words that end with E or e."<<endl;
cout<<"\nThere are "<<fCtr<<" words that end with F or f."<<endl;
cout<<"\nThere are "<<gCtr<<" words that end with G or g."<<endl;
cout<<"\nThere are "<<hCtr<<" words that end with H or h."<<endl;
cout<<"\nThere are "<<iCtr<<" words that end with I or i."<<endl;
cout<<"\nThere are "<<jCtr<<" words that end with J or j."<<endl;
cout<<"\nThere are "<<kCtr<<" words that end with K or k."<<endl;
cout<<"\nThere are "<<lCtr<<" words that end with L or l."<<endl;
cout<<"\nThere are "<<mCtr<<" words that end with M or m."<<endl;
cout<<"\nThere are "<<nCtr<<" words that end with N or n."<<endl;
cout<<"\nThere are "<<oCtr<<" words that end with O or o."<<endl;
cout<<"\nThere are "<<pCtr<<" words that end with P or p."<<endl;
cout<<"\nThere are "<<qCtr<<" words that end with Q or q."<<endl;
cout<<"\nThere are "<<rCtr<<" words that end with R or r."<<endl;
cout<<"\nThere are "<<sCtr<<" words that end with S or s."<<endl;
cout<<"\nThere are "<<tCtr<<" words that end with T or t."<<endl;
cout<<"\nThere are "<<uCtr<<" words that end with U or u."<<endl;
cout<<"\nThere are "<<vCtr<<" words that end with V or v."<<endl;
cout<<"\nThere are "<<wCtr<<" words that end with W or w."<<endl;
cout<<"\nThere are "<<xCtr<<" words that end with X or x."<<endl;
cout<<"\nThere are "<<yCtr<<" words that end with Y or y."<<endl;
cout<<"\nThere are "<<zCtr<<" words that end with Z or z."<<endl;
return 0;
}
CodePudding user response:
Use the back()
function for std::string
:
You can use it like this:
std::string str ("Testing");
cout << str.back()
The output will be: g
CodePudding user response:
Here's a suggestion of almost a complete rewrite of your code. Yet, it still considers ASCII input. The term "character" or "letter" might certainly be interpreted differently in languages like Japanese or Chinese. You don't just have 26 letters there.
Please look at this code, understand how much shorter it is than the code you posted and then dive into the things you don't understand (google it).
#include <string>
#include <sstream>
#include <array>
#include <iostream>
int main(void)
{
std::array<int,'Z'-'A' 1> counters{0}; // 26 counters
std::string s;
std::stringstream fileIn ("Hello world"); // I use a string instead of a file for demo purpose
while (fileIn>>s)
{
if (s.empty()) continue;
char c = toupper(s.back());
if ('A' <= c && c <= 'Z')
counters[c-'A'] ;
}
for (char c='A'; c<='Z'; c )
{
std::cout << "There are "<< counters[c-'A'] <<" words that end with " << c << std::endl;
// std::cout << std::format("There are {} words that end with {}", counters[c-'A'], c) << std::endl; // C 20
}
}
CodePudding user response:
A few issues ...
- Using 26 separate counters vs. an array obscures many things (bugs).
- You only loop for
A
, so all other counters will be 0. - Doing
s[-1]
causes an exception
Here is some refactored code. Please excuse the use of the printf
:
#include <string>
#include <iostream>
#include <fstream>
#include <cassert>
#include <cstring>
#include <cstdio>
using namespace std;
int
main(void)
{
int Ctr[26] = { 0 };
string inputFileName; // Declare variables
string s; // for storage
ifstream fileIn; // and file handling
cin >> inputFileName;
fileIn.open(inputFileName.data());
assert(fileIn.is_open());
while (fileIn >> s) {
#if 0
char chr = s[-1];
#else
size_t len = s.length();
char chr = s[len - 1];
#endif
if (isalpha(chr)) {
chr = tolower(chr);
Ctr[chr - 'a'] = 1;
}
}
for (int idx = 0; idx < 26; idx) {
int cnt = Ctr[idx];
if (cnt) {
int chr = idx 'a';
#if 0
cout << "\nThere are " << cnt <<
" words that end with " << tolower(chr) << " or "
<< toupper(chr) << endl;
#else
printf("There are %d words that end with %c or %c\n",
cnt,tolower(chr),toupper(chr));
#endif
}
}
return 0;
}
In the above code, I've used cpp
conditionals to denote old vs. new code:
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
Note: this can be cleaned up by running the file through unifdef -k
Here is some test input I used:
Able Baker esac delta
Here is the program output:
There are 1 words that end with a or A
There are 1 words that end with c or C
There are 1 words that end with e or E
There are 1 words that end with r or R
UPDATE:
Looks awesome, easy to understand compared to mine :), how can I print the letters that have 0 words were found as well? – Jake Adams
A few options:
- The TL;DR: Change
if (cnt) {
intoif (1) {
- Just remove the
if (cnt) {
and its corresponding}
[and reindent the remaining code]. - Add a command line option (e.g.
-a
).
Here's a version that uses a command line option:
#include <string>
#include <iostream>
#include <fstream>
#include <cassert>
#include <cstring>
#include <cstdio>
using namespace std;
int opt_a; // 1=print all counts
int
main(int argc,char **argv)
{
int Ctr[26] = { 0 };
string inputFileName; // Declare variables
string s; // for storage
ifstream fileIn; // and file handling
--argc;
argv;
// decode command line options
for (; argc > 0; --argc, argv) {
char *cp = *argv;
if (*cp != '-')
break;
cp = 2;
switch (cp[-1]) {
case 'a': // show all counts [even those that are zero]
opt_a = ! opt_a;
break;
}
}
cin >> inputFileName;
fileIn.open(inputFileName.data());
assert(fileIn.is_open());
while (fileIn >> s) {
size_t len = s.length();
char chr = s[len - 1];
if (isalpha(chr)) {
chr = tolower(chr);
Ctr[chr - 'a'] = 1;
}
}
for (int idx = 0; idx < 26; idx) {
int cnt = Ctr[idx];
if (cnt || opt_a) {
int chr = idx 'a';
printf("There are %d words that end with %c or %c\n",
cnt,tolower(chr),toupper(chr));
}
}
return 0;
}
Here is the output using ./myprogram -a
:
There are 1 words that end with a or A
There are 0 words that end with b or B
There are 1 words that end with c or C
There are 0 words that end with d or D
There are 1 words that end with e or E
There are 0 words that end with f or F
There are 0 words that end with g or G
There are 0 words that end with h or H
There are 0 words that end with i or I
There are 0 words that end with j or J
There are 0 words that end with k or K
There are 0 words that end with l or L
There are 0 words that end with m or M
There are 0 words that end with n or N
There are 0 words that end with o or O
There are 0 words that end with p or P
There are 0 words that end with q or Q
There are 1 words that end with r or R
There are 0 words that end with s or S
There are 0 words that end with t or T
There are 0 words that end with u or U
There are 0 words that end with v or V
There are 0 words that end with w or W
There are 0 words that end with x or X
There are 0 words that end with y or Y
There are 0 words that end with z or Z