I was asked to do a program for an assignment which sounds something like this:
Create a program to which you pass a text file with any number of words separated by a colon. The program will create a new file where the letters of the alphabet will be written (from A to Z), each on a new line, followed by a number of words from the input file that begins with the respective letter of the alphabet.
At first, it appeared to be quite easy to me. I was able to read the file, find the first letter in all the words and get them to appear in the console.
Here is the point that I am stuck on. I have no clue how to proceed. I am aware that I should use an array, which I could later use to get the required numbers, but I am not for the love of god able to make it work.
Here is what I came up with so far:
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
#include <stdio.h>
using namespace std;
int main() {
ifstream fin("test.txt");
char ch;
string word;
int alphabet [26];
while (fin.get(ch))
{
if (isspace(ch))
{
continue;
}
else if (ch == ':') // found the end of a word
{
char first_letter = toupper(word[0]);
cout << first_letter << '\n';
word.clear();
}
else
{
word += ch;
}
}
if (word.size() > 0)
{
char first_letter = toupper(word[0]);
cout << first_letter << '\n';
}
}
Just to clarify. The input should look something like this - video:Elizabeth:Martin:service:work:place:British:file:stream:movie:song:quake:love:hate:York etc
And the output should look like this -
A 0
B 1
C 0
D 0
E 1
F 1
G 0
H 1
I 0
J 0
K 0
L 1
M 2
N 0
O 0
P 1
Q 1
R 0
S 3
T 0
U 0
V 1
W 1
X 0
Y 1
Z 0
Break the problem up into smaller problems.
Write a program that takes a text file and prints its contents
Modify the program to splits the words by colon and prints each word on it's own line
Modify the program to print only the first character of each word
Modify the program to count the number of instances of each letter (keep printing the letter) - print out the counts when done
Modify the program to not print out the letters
Now you're done.
At every point along the way you are making a single change to the logic which means you can isolate both your thought process and debug mistakes much more easily.
You want to store the characters in the array by looking at the character byte code. First, set alphabet to an array of all 0's. Then count the first letter of each word with the index representing the letter.
char first_letter = toupper(word[0]);
alphabet[first_letter - 'A']++;
Then, at the end, print out:
for(int i = 0; i < 26; ++i) {
printf("%c %d\n", i + 'A', alphabet[i]);
}
Related
Hey everyone I'm a newbie to C++ and could use some help.
I'm trying to code a program which counts only the words that start with Capital Letters.
int countLegalWords(char str[])
int counter = 0; // counts the legal words
for (int i = 0; i < MAXSIZE; i++)
{
if (str[i] >= 'A' && str[i] <= 'Z')
{
if (str[i + 1] >= 'a' && str[i + 1] <= 'z')
{
counter++;
}
else if (str[i] == ' ')
i++;
}
}
return counter;
Example:
Input:
I liKE Ice Cream H
Output:
4 words with capital letters at the beginning of the word.
There are several problems with your code
In C++, std::string is used for strings. Things like ´char*´ or ´char[]´ are not used in C++ They are used in C. But C and C++ are 2 different languages
You use a C-Style array (char str[]). In C++, C-Style arrays are not used
There is a magic constant MAXSIZE, which has nothing to do with the length of the string. If MAXSIZE is 100 but the your string is smaller, then you compare out of bounds values in the for loop. This is a severe bug.
You need to understand that C-style strings are 0-terminated. The last charcter is a '\0'. You must not operate past the terminating 0.
Your logic in detecting words and word begin is wrong. You check any character for uppercase and then the next for lowercase. But this can happen also within a word. See your sentence with "liKe" in it.
You do not want to switch to C++. You have written in the comment that you want to use strcmp and such, which is a C-function
If you would write comments and use meaningful variable names, then you would find all errors by yourself.
OK, that were the problems. Now a possible solution, using your programming style.
#include <iostream>
int countLegalWords(char myString[]) {
// Here we will store the number of words which start with a capital letter
int countOfLegalWords = 0;
// We will iterate over the complete string and check all characters
unsigned int indexInString = 0;
// Check all characters of the string until we hit the terminating 0
while (myString[indexInString] != '\0') {
// Search for the begin of a word. This is the first non-space character
while (myString[indexInString] == ' ')
++indexInString;
// OK, Now we found the begin of a word. Check, if the first character is upper case
if ((myString[indexInString] >= 'A') and (myString[indexInString] <= 'Z')) {
// Yes, uppercase, count up
++countOfLegalWords;
}
// Now search for the end of the word or for the end of the complete string
while ((myString[indexInString] != '\0') and (myString[indexInString] != ' '))
++indexInString;
}
// And return the count of legal words to ther calling program
return countOfLegalWords;
}
int main() {
char myString[] = "I liKE Ice Cream H";
std::cout << "\nCount of legal words: " << countLegalWords(myString) << '\n';
}
in C++ all this would be done with a one liner:
#include <iostream>
#include <string>
#include <iterator>
#include <regex>
// Regex for a word starting with a capital letter
const std::regex re{ R"(\b[A-Z]\w*)" };
// Main program
int main() {
std::string myString{ "I liKE Ice Cream H" };
std::cout << "\nCount of legal words: " << std::distance(std::sregex_token_iterator(myString.begin(), myString.end(),re), {}) << '\n';
}
hi can someone please help me to complete this code in c++ if you may interested
here is the project which will print the position of a char in string, this is very close to my task but not exactly
here is the problem: program only print the position of a char, for example for letter 'S' it prints 18 because it sits at position 18, how i can change this program which instead of that, the program print my values, i don't really care about the position i care about the value that should return or store, the value i specify,
program for sam prints
S=18
A=1
M=13
instead i want it know for letter S print 7 or store 7, i mean instead of caring about position should care about the value at the final result which i explained
all 26 alphabet as you see has a value base on the position i want that pos value to be changed and result other pos int value
#include<iostream>
#include<string>
#include<exception>
#include <cstdlib>
#include<stdio.h>
#include <cctype>
using namespace std;
int main()
{
const std::string alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << "Please enter your the name:";
std::string text;
std::cin >> text;
// convert all lower case characters to upper case
for (char& c : text)
c = std::toupper(c);
// Lookup character
for (char& c : text) // for each character c in text
{
const auto pos = alpha.find(c);
if (pos != std::string::npos) // if found (if the character is an alpha character)
// note: non-alpha characters are ignored
{
const int value = pos + 1; // +1 because position of 'A' is 0, value of 'A' is 1
// Print the character and the position
cout << c << "=" << pos << endl;
}
}
}
It depends on what kind of result you're looking for. If you're looking to return values in the range of the alphabet, then just rearrange the letters to match what you want them to return.
If you're looking for something with higher or lower values, then take a look at building a map and accessing the key value pairs. https://en.cppreference.com/w/cpp/container/map
so there's something in my program that is not going the way I feel like it should go. If I could get some help I would appreciate it. I'll explain how it's supposed to work first and follow up with my questions starting with the most important one since I'm stuck on it and it isn't allowing me to progress.
So I wrote an encryption program that asks the user to input a string and then it encrypts it and creates a file called "secret.dat" and puts the encrypted phrase in there.
If the user were to put in the phrase:
hello world 123
it would send this into the file:
11spwwzshzcwoh234&6#12
The "11" indicates how many letters the letter was shifted to the right by. This is followed by the phrase he entered in encrypted. The '&' character shows where the encryption ends. Each space in his phrase uses the previous letter and shifts it over by 4 and finally after the '&' character it tells the number location of where the spaces are seperated by a '#' character.
The current program I am writing decrypts the "secret.dat" file and shows his phrase on the screen.
This is what I have so far:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
//Declare Variables
int shift;
ifstream inData;
string input;
string output;
int length;
//Open file
inData.open("secret.dat");
//Begin program
inData >> shift;
getline(inData, input, '&');
length = input.length();
for (int count = 0; count < length; count++)
{
if (input[count] >= 'a' && input[count] <= 'z')
{
output += ((input[count] - 'a' - shift) % 26) + 'a';
}
else if (input[count] >= '0' && input[count] <= '9')
{
output += ((input[count] - '0' - shift) % 10) + '0';
}
}
//Declare variables for location of spaces
int i = 0;
char ignore;
int spaces[20];
int location;
//Begin finding the spaces
while (!EOF)
{
inData >> location;
spaces[i] = location;
inData >> ignore;
}
//Preview each result to compare and make sure they are working right
cout << shift << endl;
cout << input << endl;
cout << output << endl;
cout << spaces[0] << endl;
cout << spaces[1] << endl;
return 0;
}
This is what I get as a result
11
spwwzshzswoh234
helloh]oXld]'()
4704512
0
Obviously the last 3 lines are not working correctly (NOTE: this is not how I am going to display it, I just printed these to the screen so that I could see what the result was and make sure it was correct, which it isn't).
So, my first and most important question is why my while loop isn't working correctly. It gives me a bunch of random numbers in the first array slot when it should put a 6 in the first spot, then it should skip the next character and then put a 12 in the second spot in the array which it just puts a 0 there. If I just call an integer from the file outside of the while loop it gives me a 6 no problem so I'm unsure on why it is doing this. I figured it would put the first integer in the first slot in the array, then skip the next character, then put the next integer in the array and skip the next character and so on until the end of the file. This part is what's keeping me from proceeding in the program so I put this as the most important.
Second, what's wrong with my formula for shifting the characters back? I used this same exact formula for shifting the characters forward for my encryption program except I added shift so I assumed just subtracting the shift would decrypt it.
Thanks for anyone willing to help!
In your encryption scheme, the character 'h' stands for the letter 'w' in clear text.
Let's work through how your code tries to decode this:
if (input[count] >= 'a' && input[count] <= 'z')
{
output += ((input[count] - 'a' - shift) % 26) + 'a';
}
input[count] is character "h". 'h' - 'a' is 7. Your value of "shift" is 11.
Your expression calculates (7-11) % 26, or -4 % 26.
Pop quiz: what's -4 % 26? You'd be surprised to learn that the answer is -4. Adding -4 to 'a' produces the character ']', which is what you see, in the corresponding position, in your output.
To fix this, change this line to read:
output += ((input[count] - 'a' - shift + 26) % 26) + 'a';
And change the other line, for digits, in the same way.
I need help with this if statement. Im trying to read each character to see if it is a number. If it is not a digit then say it is not a number if it is continue reading on to the next character. for example if the user inputs 54gr 21 gr42 134 3f3. the only thing that would cout is 21 and 134.
#include <iostream> // libraries
#include <iomanip>
#include <string>
using namespace std;
int main()
{
char string[80];
// char num[80];
// char good[80];
cout << "enter a string "; // prompting user
cin.getline(string,80); // geting line
// int i = 0;
// int j = 0;
int count = 0;
{
while(string[count] != '\0') {
if(string[count] >= '0' && string[count] <= '9' )
cout << count << endl;
}
++ count;
}
}
I would not try to do this character by character. The problem is that you don't now that 5 is really part of a number until you've read to the end of the string of non-space characters to verify that all the contents are legitimately part of a number.
As such, I think you need/want to break the input up into "words", then check whether each complete word can be converted entirely to a number. You can read "words" with just some_stream >> some_string;
Once you have a "word" you check whether you can convert it entirely to a number. Assuming you want integers, you use strtol to (try to) convert it to a number. That will give you a pointer to the first character it couldn't convert as a number. If that's not the end of the string, then that "word" wasn't a number (even if it started with/contained one or more digits).
I am attempting to solve a problem from topcoder.com and it's driving me crazy. I am learning C++ after a long break from C and am having trouble with strings.
The purpose of the program is to decode a string of 0s and 1s that has gone through an encryption algorithm that consists of adding each adjacent digit to the digit in question.
So 010111 becomes 112232 (LSB and MSB are considered to have zeros next to them). Below is my algorithm to decode the string:
#include <string>
#include <vector>
#include <iostream>
using namespace std;
class BinaryCode {
public:
vector<string> decode(string message);
};
vector<string> BinaryCode::decode(string message) {
vector<string> decoded(2);
int i;
string myTempString;
myTempString.append("0");
myTempString.append(1,message[0] - myTempString[0]);
for(i=2; i<message.size(); i++) {
myTempString.append(1,message[i-1] - myTempString[i-1] - myTempString[i-2]);
}
decoded[0] = myTempString;
myTempString = "";
myTempString.append("1");
myTempString.append(1,message[0] - myTempString[0]);
for(i=2; i<message.size(); i++) {
myTempString.append(1, message[i-1] - myTempString[i-1] - myTempString[i-2]);
}
decoded[1] = myTempString;
return decoded;
}
int main () {
string message("123210122");
BinaryCode *code = new BinaryCode;
vector<string> result = code->decode(message);
cout << "Decoded strings are "+result[0]+" and "+result[1];
getchar();
return 0;
}
The output is nonsense:
Decoded strings are 01
This is just a guess, since you don't show what output you're getting, but it looks like you're doing math on the character values and ending up with characters in the control range. For example, '1' - '0' is not '1' (character 49), it is 1, or Control-A. This is not printable and will typically be invisible in the output. Similarly, '1' + '2' is 49 + 50, or 99, which is 'c'. C++ is not going to magically convert these characters to integers for you. Hopefully this will give you the information you need to fix your code.
A character is an 8-bit integral type. It has the special property that, when printed, it will appear as the character that matches the ASCII value that it contains.
For example:
int valueAsInt = 65;
char valueAsChar = valueAsInt;
std::cout << valueAsChar << "\n";
valueAsInt = 'A';
std::cout << valueAsInt << "\n";
A
65
Take the value of the character literal '0'. This corresponds to the ASCII value 48. '1' is 49, etc.
If you subtract 48 from 49, you get 1. But that's not what you're looking for.
The ASCII value 1 corresponds to a non-printable character, called "start of heading". It was once used on old printers as a sort of markup. It would not print, but it would modify how further characters are printed.
When you subtract one numeric character from another, you get a delta, not a printable character. To turn this delta back into a printable character, you have to add it to a base character:
char value = '5' - '3';
value += '0';
std::cout << "5 - 3 = " << value << "\n";
5 - 3 = 2
So, your code such as message[0] - myTempString[0] must be changed to message[0] - myTempString[0] + '0' in order to work the way you intend it to.