Wrote a function that calculates the average length of words in a sentence.
Why does the program print 0 instead of the average?
Please help me fix my mistake.
If you know how to make an implementation in one function, please write.
#include <iostream>
#include <string>
using namespace std;
int CountWordsAndLetters(char* str, int& words, int& letters)
{
words = 0;
int i = 0;
letters = 0;
while (str[i] == ' ')
i++;
for (; str[i]; i++) {
if (((str[i] >= 'a') && (str[i] <= 'z'))
|| ((str[i] >= 'A') && (str[i] <= 'Z')))
letters++;
if (str[i] == ' ') {
words++;
while (1)
if (str[i] == ' ')
i++;
else {
i--;
break;
}
}
}
words = words + 1;
return (words);
}
float AverageLetters(float words, float letters)
{
float a = (double)(letters / words);
return a;
}
int main()
{
char array[255];
int words = 0;
int letters = 0;
cout << "Enter the string\n\n";
gets_s(array);
int size;
for (size = 0; array[size]; size++)
;
char* str = new char[size];
CountWordsAndLetters(str, words, letters);
cout << "\nAverage number of letters per word: "
<< AverageLetters(words, letters);
return 0;
}
If you know how to make an implementation in one function, please write.
Here, you are allocating an uninitialized array of char:
char* str = new char[size];
You put nothing in it.
You then pass it to CountWordsAndLetters:
// here -------v
CountWordsAndLetters(str, words, letters);
You should consider simply sending array instead:
CountWordsAndLetters(array, words, letters);
Here's a live example of your code working.
I'm trying to write a function which only reads four ints out of a users input like this: ewzge242jfdsiii23 So it is supposed to save only 2422.
This is my code and it just gives me some weird output, if I let it cout number.
Can you maybe see my mistakes and explain why I can't do it how I did and what I could do instead? Thanks a lot!
int readnumber ( ) {
char kar, ont_kar, ont_ont_kar;
int number;
while (kar != '\n' ){
cin.get (kar);
if (kar >= '0' && kar <= '9') {
old_kar=kar;
old_kar = old_kar*10 + (kar - '0');
old_old_kar = old_kar ;
} //if
} //while
if (old_kar < 9999) {
number=old_kar;
}//if
else {
number=old_old_kar;
}//else
}//readnumber
This looks too complicated, why do you need so many variables?
Also old_kar and old_old_kar are misstyped. The function does not return, that should be the main problem.
Here's a quick simple example:
unsigned readnumber(int number_of_chars) {
char ch;
unsigned number = 0;
while (number_of_chars > 0) {
std::cin.get(ch);
if ('\n' == ch)
break; // Stop on new line
if (ch < '0' or ch > '9')
continue; // Skip non-digits
--number_of_chars; // One digit processed
number = number * 10 + ch - '0'; // And added to the result
}
return number;
}
And here is a full version without break or continue:
#include <iostream> // std::cin, std::cout
#include <fstream> // std::ifstream
using namespace std;
int readnumber(int number_of_chars) {
char ch;
int number = 0;
while (number_of_chars > 0) {
std::cin.get(ch);
if ('\n' == ch)
return number;
if (ch >= '0' and ch <= '9') {
--number_of_chars;
number = number * 10 + ch - '0';
}
}
return number;
}
int main() {
int n = readnumber(4);
cout << "You entered: " << n << endl;
return 0;
}
NB: Always compile with all warnings on, this will save you a lot of time.
I'm having trouble storing my code into two different arrays. The following text file contains a format like this: name,1,2,3,4,5anothername,6,7,8,9,10...
For example it could be something like this, I'll name it test.txt:
Drake,1,2,3,4,5
Kanye West,6,7,8,9,10
Ka,11,12,13,14,15,16
Young Thug,17,18,19,20
Kendrick Lamar,21,22,23,24,25
Here is my code so far:
#include <iostream>
#include <fstream>
#include <stdlib.h>
using namespace std;
int main(){
ifstream inputFile;
inputFile.open("test.txt");
if (inputFile.fail()){
cout << "File open error!" << endl;
return -1;
}
string namesarray[25]; //array used to store names
float numbersarray[25]; //array used to store numbers
string line; //string used to read text file
int i = 0; //counter for entire text input
int j = 0; //counter for namesarray
int k = 0; //counter for numbersarray
while(getline(inputFile, line, ',')){
if (line[i] >= 'A' && line[i] <= 'Z'){
namesarray[j] = line;
j++;
}
else{
numbersarray[k] = stof(line);
k++;
}
i++;
}
inputFile.close();
}
My problem is that I can't store all the names into the string array, but the numbers are stored into the float array just fine. My code only stores in the first name and then a random number. For example if I create a loop to check if the names or the numbers are stored in correctly
for (int a = 0; a < 25; a++){
cout << numbersarray[a] << endl;
}
The numbers are stored in fine but checking for the names it doesn't store all the names in there. If I'm checking for the first letter of the line shouldn't it store the name in there if it contains a letter? I don't want to use isalpha() because it still outputs the same problem.
for (int a = 0; a < 25; a++){
cout << namesarray[a] << endl;
}
With getline() the third parameter does not eliminates commas. It specifies the delimeter until which the function fills your string. So according to your input file, it is going to get the names.
I can not find the use of the i++;. You always have to look for line[0].
I suggest using isdigit(line[0]) to check either it is a number or a character
The problem with your code is that you are checking only for upper case letters.
Upper case letters exist only in the first character of the string with the name.
So when i++; goes to i>0, line[i] stops to be an upper case, and becomes a lower case.
Also I want you to know that stof works only in c++11
the getLine function's delimiter is a comma, so when it gets to the last number for each name, it reads the number and the name in one string. To fix it, consider something like:
bool letter = true;
bool letterNum = false;
int index = 0;
if((line[0] >= '9' && line[0] >= '0') || line[0] == '.') {
letter = false;
}
for(int l = 0; l < line.length()) {
if((letter && ((line[l] >= '9' && line[l] >= '0') || line[l] == '.')) || (!letter && !((line[l] >= '9' && line[l] >= '0') || line[l] == '.'))) {
index = l;
l = line.length();
}
}
if(letter && index == 0) {
namesarray[j] = line;
j++;
i++;
}
if(!letter && index == 0) {
numbersarray[k] = atoi(line);
k++;
i++;
}
if(letter && index != 0) {
namesarray[j] = line.substr(0, index);
numbersarray[k] = stof(line.substr(index, line.length() - index));
j++;
k++;
i += 2;
}
if(!letter && index != 0) {
numbersarray[k] = stof(line.substr(0, index));
namesarray[j] = line.substr(index, line.length() - index);
j++;
k++;
i += 2;
}
Instead of:
if (line[i] >= 'A' && line[i] <= 'Z'){
namesarray[j] = line;
j++;
}
else{
numbersarray[k] = stof(line);
k++;
}
i++;
Inside the while loop. You could also use ifstream >> string, because that reads one line at a time, and you could just parse each substring in between the commas. That may look something like:
#include <iostream>
#include <fstream>
#include <stdlib.h>
using namespace std;
int main(){
ifstream inputFile;
inputFile.open("test.txt");
if (inputFile.fail()){
cout << "File open error!" << endl;
return -1;
}
string namesarray[25]; //array used to store names
float numbersarray[25]; //array used to store numbers
string line; //string used to read text file
int i = 0; //counter for entire text input
int j = 0; //counter for namesarray
int k = 0; //counter for numbersarray
while(!inputFile.eof()){
string data;
inputFile >> data;
int lastIndex = 0;
for(int l = 0; l < data.length(); l++) {
if(data[l] == ',' || l == data.length() - 1) {
line = data.substr(lastIndex, l - lastIndex);
lastIndex = l + 1;
if (((line[l] >= '9' && line[l] >= '0') || line[l] == '.')){
numbersarray[k] = stof(line);
k++;
}
else{
namesarray[j] = line;
j++;
}
i++;
}
}
}
inputFile.close();
}
However, this only works when each name and it's numbers are separated by a \n. If they are, this is the better option. But if they aren't, use the first method.
This is better handled using std::getline() to read an entire line, and then std::istringstream to parse each line, eg:
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;
int main()
{
ifstream inputFile;
inputFile.open("test.txt");
if (!inputFile)
{
cout << "File open error!" << endl;
return -1;
}
string namesarray[25]; //array used to store names
float numbersarray[25*5]; //array used to store numbers
string s; //string used to read text file
int i = 0; //counter for entire text input
int j = 0; //counter for namesarray
int k = 0; //counter for numbersarray
while (getline(inputFile, s))
{
istringstream iss(s);
getline(iss, namesarray[j], ',');
++j;
while (getline(iss, s, ','))
{
numbersarray[k] = stof(s);
++k;
}
++i;
}
inputFile.close();
return 0;
}
Why in else statement is i++? You must check the i variable first element of array be but not the addition of it.
#include <iostream>
#include <cstring>
#include <string>
//#include <cctype>
using namespace std;
string k;
int key[1024];
int size = 0;
int count = 0;
char text[1024];
char o;
void encrypt(char input[]);
void decrypt(char input[]);
// get arguments from command line
int main(int argc, char *argv[])
{
if(argc >= 3)
{
k = argv[2];
// removing spaces from key
// storing key into char array
for(int i = 0; i < k.length(); i++)
{
if(k.at(i) == ' ')
{
key[i] = k.at(i+1);
i++;
}
else
{
key[i] = k.at(i);
// cout << key[i] << endl;
}
size++;
}
if(strcmp(argv[1], "-e") == 0)
{
// get text from user
// encrypt
cout << "encryption " << endl;
cin.getline(text, sizeof(text));
encrypt(text);
}
else if(strcmp(argv[1], "-d") == 0)
{
// get text from user
// decrypt
cout << "decryption " << endl;
decrypt(text);
}
}
}
void encrypt(char input[])
{
string word = input;
char wkey[word.length()];
// cout << word.length();
for(int i = 0; i < word.length(); count++, i++)
{
// if input is larger than the key
// chars of key will repeat until the size is the length of the input
if(i > size - 1)
{
if(i == size)
{
count = 0;
}
wkey[i] = wkey[count];
}
else
{
wkey[i] = key[i];
}
// if input is a space, cout a space
if(input[i] == ' ')
{
cout << " ";
}
// if input is something other than a letter, then just print it out
else if(input[i] < 65 || input[i] > 122 || input[i] > 90 && input[i] < 97)
{
cout << input[i];
}
else
{
// ignoring case of the letters in the key
// give the letters a range of 0-25
if(wkey[i] >= 65 && wkey[i] <= 90)
{
wkey[i]-= 'A';
}
else if(wkey[i] >= 97 && wkey[i] <= 122)
{
wkey[i]-= 'a';
}
// cout << wkey[i] << endl;
// if input is uppercase, put it in the range of 0-25
// make shift by adding to char in key
// mod by 26 to wrap around
// o is the encrypted character that will be printed
if(input[i] >= 65 && input[i] <= 90)
{
o = ((wkey[i] + (input[i] - 'A')) % 26) + 'A';
}
else if(input[i] >= 97 && input[i] <= 122)
{
o = ((wkey[i] + (input[i] - 'a')) % 26) + 'a';
}
}
cout << o;
}
}
The problem is that I am having trouble encrypting plaintext if that text contains a space. If the text is just one single word, then the program works. In the encryption function where I test the input for a space, I just print out a space, and then the next iteration of the for loop occurs. I think that this problem is occurring because once that next iteration occurs, the character in the key that is at the same index as the space in the input is skipped. I've tried doing an if statement to roll back to the skipped letter in the key, but I still get the wrong output. If anyone could give me some advice on how to fix this problem, I would really appreciate it.
I am trying to understand how to use cin.get(). I would like to only accept 20 characters of input, but any method I've tried using to detect further input stop
I am accepting input one character at a time and inputting it into an array like so:
void getInput(char arr[], int size) {
char number = '0';
for (int i = 0; i < size + 1; i++) {
char number;
cin.get(number);
if ((number >= '0') && (number <= '9')) {
arr[i] = number;
}
if ((number == ' ') || (number == '\n')) {
break;
}
}
}
I've tried doing something like this, but you can see that my understanding is not excellent:
if (number == '\n') {
done == true;
}
and wrapping the whole thing in a while (!done) for example, but that doesn't work in situations where I input 20 characters or less.
You could initialise a variable int count= 1;. With each iteration you can increment it with count++;and put the check
if (count==20)
break;
I hope this helps.
You could round down the passed size parameter to 20 if it's larger than 20. Then the for-loop will break at most after 20 iterations.
#include <iostream>
using namespace std;
void getInput(char arr[], size_t size) {
const size_t MAX_SIZE = 20;
if (MAX_SIZE < size) {
// 'round down' size if it's too big
size = MAX_SIZE;
}
char number = '0';
for (unsigned int i = 0; i < size; i++) {
cin.get(number);
if ((number >= '0') && (number <= '9')) {
arr[i] = number;
} else if ((number == ' ') || (number == '\n')) {
break;
}
}
}
int main() {
char arr[32] = {};
// even though arr could fit 32 chars
// only MAX_SIZE=20 numbers at most will be accepted
getInput(arr, 32);
cout << arr << endl;
return 0;
}
I'm assuming size is the length of arr (can't yet comment so could not ask this), if so then watch out for doing i < size + 1; that let's i take values from 0 to size inclusive, and then the for-loop eventually reaches arr[size] which is off the end of the array. Use i < size instead.