How to convert char to integer from .txt file in C++ - c++

I have a .txt file that contains:
XXXX:YYYY:ABCCCCE.
I need to write a function that reads this section of the .txt file ABCCCCE and finds the sum of the values of those characters.
Assume:
A = 1, B = 2, C = 3, D = 4, E = 5
Here is what I have so far to distinguish the values of each character:
int getComplexity(char theCode)
{
int complexity;
if(theCode == 'A')
{
complexity = 1;
} else if(theCode == 'B')
{
complexity = 2;
} else if(theCode == 'C')
{
complexity = 3;
} else if(theCode == 'D')
{
complexity = 4;
} else if(theCode == 'E')
{
complexity = 5;
}
return complexity;
}
I'm just not sure how I would read from the .txt file and convert the values. I am new to c++ so any help would be greatly appreciated!

I don't know if this is what your after but:
#include <fstream>
#include <numeric>
#include <vector>
using namespace std;
int Return_Complexity(char character)
{
switch (character)
{
case 'a':
return 1;
break;
case 'b':
return 2;
break;
case 'c':
return 3;
break;
case 'd':
return 4;
break;
case 'e':
return 5;
break;
default:
return 0; //Zero indicates that we didn't find what we're looking for
}
}
int main()
{
ifstream file{ "some-file.txt" };
vector<int> values;
char character;
while (file >> character)
{
int result = Return_Complexity(tolower(character));
if (result > 0) //if its a-e
values.push_back(result);
}
int Result = accumulate(values.begin(), values.end(), 1); //add them together
cout << Result;
}
this pushes back all characters found and then sums them up.
If this is not what your after, i will fix this.

Related

warning: control may reach end of non-void function problem

Well, i made RGB To Hex Conversion. My programm in online compiler works pretty well, but on codewars it has a problem "control may reach end of non-void function". What should i do? Should I remove for loop?
using namespace std;
#include <iostream>
#include <string>
int checkForNumber(int input) {
if (input > 255) return 255;
if (input < 0) return 0;
else return input;
}
string check(int input) {
if (input < 10) return to_string(input);
switch (input)
{
case 10:
return "A";
break;
case 11:
return "B";
break;
case 12:
return "C";
break;
case 13:
return "D";
break;
case 14:
return "E";
break;
case 15:
return "F";
break;
}
}
**string YES(int input) {
string m;
char temp;
for (int i = 0; i < 2; i++) {
m += check(input % 16);
input /= 16;**
//problem is somewhere here
}
temp = m[0];
m[0] = m[1];
m[1] = temp;
return m;
}
int main()
{
string output;
ios_base::sync_with_stdio(false);
int r = 148 , g = 0, b = 211;
r = checkForNumber(r);
g = checkForNumber(g);
b = checkForNumber(b);
output += YES(r) + YES(g) + YES(b);
cout << output;
}
The problem is in your check(int input) function -- consider what happens if the value of the input argument is not in the range [10, 15]. I suggest putting in a default: case that returns something appropriate at the bottom of your switch block.

Overwrite the elements in a vector without specifying specific elements

I am making a calculator that accepts multiple operators at once. I have a vector pair that stores the position of operators, and the type of operator. The vector must be updated after each loop as the previous positions are no longer valid due to the result replacing a part of the input string.
I've attempted to use clear() so that it starts from the beginning again, but that results in Expression: vector iterators incompatible. I don't think I can use std::replace since the number of operators in the string changes after each loop. Is there a way to just have it start from the beginning again and overwrite any existing elements?
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
int main()
{
std::cout << "C++ Calculator" << std::endl;
while (true) //runs forever with loop
{
std::string input;
std::getline(std::cin, input);
//erases whitespace
int inp_length = input.length();
for (int i = inp_length - 1; i >= 0; --i)
{
if (input[i] == ' ')
input.erase(i, 1);
}
std::vector<std::pair<int, char>> oper_pvec;
int vec_pos = 0;
//finds the position of operators and type
for (std::string::iterator i = input.begin(); i != input.end(); ++vec_pos, ++i)
{
switch (*i)
{
case 'x':
{
oper_pvec.push_back(std::pair<int, char>(vec_pos, 'x'));
break;
}
case '/':
{
oper_pvec.push_back(std::pair<int, char>(vec_pos, '/'));
break;
}
case '+':
{
oper_pvec.push_back(std::pair<int, char>(vec_pos, '+'));
break;
}
case '-':
{
oper_pvec.push_back(std::pair<int, char>(vec_pos, '-'));
break;
}
}
}
//declarations before loop to make sure they're all able to be accessed, will probably change later
int loper_pos = 0; //must be set 0 since there's no left operator at first
int roper_pos;
double lnum; //left number
double rnum; //right number
char loper; //left operator
char roper; //right operator
int pos = -1; //position of loop, needs to be -1 since it increments it each time
std::string holder = input; //copy of input
auto op = oper_pvec.begin();
while (op != oper_pvec.end())
{
op = oper_pvec.begin();
++pos; //position of loop
int key = std::get<0>(*op); //gets first value from vector pair
char val = std::get<1>(*op); //gets second value from vector pair
//gets previous/next vector pairs
std::vector<std::pair<int, char>>::iterator prev_op = oper_pvec.begin();
std::vector<std::pair<int, char>>::iterator next_op = oper_pvec.end();
if (op != oper_pvec.begin()) prev_op = std::prev(op);
if (op != oper_pvec.end()) next_op = std::next(op);
//extracts the value of pairs
if (pos > 0)
{
loper_pos = std::get<0>(*prev_op);
loper = std::get<1>(*prev_op);
}
if (pos == oper_pvec.size() - 1) roper_pos = oper_pvec.size();
else
{
roper_pos = std::get<0>(*next_op);
roper = std::get<1>(*next_op);
}
//replaces numbers and etc with product, only multiplication for now
switch (val)
{
case 'x':
{
int lnum_start = loper_pos + 1;
if (loper_pos == 0) lnum_start = 0;
int lnum_len = key - (loper_pos + 1);
if (loper_pos == 0) lnum_len = key;
lnum = std::stod(input.substr(lnum_start, lnum_len));
int rnum_start = key + 1;
int rnum_len = (roper_pos - 1) - key;
rnum = std::stod(input.substr(rnum_start, rnum_len));
double prod = lnum * rnum;
std::string to_string = std::to_string(prod);
input.replace(loper_pos, roper_pos, to_string);
break;
}
}
/////////////////////////////////problem area////////////////////////////////////////
//clears the vector and then finds the operators again
oper_pvec.clear();
int vpos = 0;
for (std::string::iterator it = input.begin(); it != input.end(); ++vpos, ++it)
{
if (vpos == input.length())
{
vpos = 0;
break;
}
switch (*it)
{
case 'x':
{
oper_pvec.push_back(std::pair<int, char>(vpos, 'x'));
break;
}
case '/':
{
oper_pvec.push_back(std::pair<int, char>(vpos, '/'));
break;
}
case '+':
{
oper_pvec.push_back(std::pair<int, char>(vpos, '+'));
break;
}
case '-':
{
oper_pvec.push_back(std::pair<int, char>(vpos, '-'));
break;
}
}
}
/////////////////////////////////////////////////////////////////////////////////////
}
//converts to double then prints on screen
double out = std::stod(input);
std::cout << out << std::endl;
}
}
Not really the answer to the title but instead of trying to overwrite the vector I just continued to use clear() and changed the while loop to oper_pvec.size() != 0.
(Full code since I had to change quite a few things to get it to work properly)
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
int main()
{
std::cout << "C++ Calculator" << std::endl;
while (true) //runs forever with loop
{
std::string input;
std::getline(std::cin, input);
//erases whitespace
int inp_length = input.length();
for (int i = inp_length - 1; i >= 0; --i)
{
if (input[i] == ' ')
input.erase(i, 1);
}
std::vector<std::pair<int, char>> oper_pvec;
int vec_pos = 0;
//finds the position of operators and type
for (std::string::iterator i = input.begin(); i != input.end(); ++vec_pos, ++i)
{
switch (*i)
{
case 'x':
{
oper_pvec.push_back(std::pair<int, char>(vec_pos, 'x'));
break;
}
case '/':
{
oper_pvec.push_back(std::pair<int, char>(vec_pos, '/'));
break;
}
case '+':
{
oper_pvec.push_back(std::pair<int, char>(vec_pos, '+'));
break;
}
case '-':
{
oper_pvec.push_back(std::pair<int, char>(vec_pos, '-'));
break;
}
}
}
//declarations before loop to make sure they're all able to be accessed, will probably change later
int loper_pos = 0; //must be set 0 since there's no left operator at first
int roper_pos;
double lnum; //left number
double rnum; //right number
char loper; //left operator
char roper; //right operator
int pos = -1; //position of loop, needs to be -1 since it increments it each time
std::string holder = input; //copy of input
std::vector<std::pair<int, char>> vec_copy = oper_pvec;
auto op = oper_pvec.begin();
while (oper_pvec.size() != 0)
{
op = oper_pvec.begin();
++pos; //position of loop
int key = std::get<0>(*op); //gets first value from vector pair
char val = std::get<1>(*op); //gets second value from vector pair
//gets previous/next vector pairs
std::vector<std::pair<int, char>>::iterator prev_op = oper_pvec.begin();
std::vector<std::pair<int, char>>::iterator next_op = oper_pvec.end();
if (op != oper_pvec.begin()) prev_op = std::prev(op);
if (op != oper_pvec.end()) next_op = std::next(op);
//extracts the value of pairs
if (pos > 0)
{
loper_pos = std::get<0>(*prev_op);
loper = std::get<1>(*prev_op);
}
if (op == oper_pvec.begin()) loper_pos = 0;
if (oper_pvec.size() == 1) roper_pos = input.length();
else
{
roper_pos = std::get<0>(*next_op);
roper = std::get<1>(*next_op);
}
//replaces numbers and etc with product, only multiplication for now
switch (val)
{
case 'x':
{
int lnum_start = loper_pos + 1;
if (lnum_start == 1) lnum_start = 0;
if (loper_pos > 0)
if (isdigit(input[loper_pos - 1])) lnum_start = 0;
int lnum_len = key - (loper_pos + 1);
if (lnum_start == 0)
{
if (key == 1) lnum_len = 1;
else lnum_len = key - 1;
}
lnum = std::stod(input.substr(lnum_start, lnum_len));
int rnum_start = key + 1;
int rnum_len = (roper_pos - 1) - key;
rnum = std::stod(input.substr(rnum_start, rnum_len));
double prod = lnum * rnum;
std::string to_string = std::to_string(prod);
input.replace(loper_pos, roper_pos, to_string);
break;
}
}
//clears the vector and then finds the operators again
oper_pvec.clear();
int vpos = 0;
for (std::string::iterator it = input.begin(); it != input.end(); ++vpos, ++it)
{
if (vpos == input.length())
{
vpos = 0;
break;
}
switch (*it)
{
case 'x':
{
oper_pvec.push_back(std::pair<int, char>(vpos, 'x'));
break;
}
case '/':
{
oper_pvec.push_back(std::pair<int, char>(vpos, '/'));
break;
}
case '+':
{
oper_pvec.push_back(std::pair<int, char>(vpos, '+'));
break;
}
case '-':
{
oper_pvec.push_back(std::pair<int, char>(vpos, '-'));
break;
}
}
}
}
//converts to double then prints on screen
double out = std::stod(input);
std::cout << out << std::endl;
}
}

Why doesn't a While Loop inside a For Loop work in my program?

I should make a program where I should print out the short (compressed word), having the long one. For an example: 8S2Q3R is short for SSSSSSSSQQRRR. Now, I made this short program, which doesn't work (loops endlessly). I'm pretty sure I shouldn't be putting a while-loop inside a for-loop, but I'm not sure how exactly to fix this.
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char word[80];
cin >> word;
int length = strlen(word);
int counter = 1;
for (int i = 0; i < length; i++) {{
while (word[i] == word[i + 1]) {
counter++;
}
cout << counter << word[i];
}
return 0;
}
Similarly, if I have to print out a long word having a short one, I made a program which also doesn't work (output is a bunch of hieroglyphs):
#include <iostream>
#include <string.h>
using namespace std;
int number = 0;
bool Number(char c) {
switch(c) {
case '1':
number = 1;
return true;
break;
case '2':
number = 2;
return true;
break;
case '3':
number = 3;
return true;
break;
case '4':
number = 4;
return true;
break;
case '5':
number = 5;
return true;
break;
case '6':
number = 6;
return true;
break;
case '7':
number = 7;
return true;
break;
case '8':
number = 8;
return true;
break;
case '9':
number = 9;
return true;
break;
case '0':
number = 0;
return true;
break;
default:
return false;
}
}
int main()
{
char word[80];
cin >> word;
int length = strlen(word);
int counter = 1;
for (int i = 0; i < length; i++) {
if (Number(word[i])) {
for (int j = 0; j < number; i++) {
cout << word[i];
}
} else {
continue;
}
}
return 0;
}
Not sure if this is what you want but I assumed that there can be 2 or more consecutive digits and only one character after the digits.
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
int
main ()
{
char word[80];
char out[128];
char temp[10];
cin >> word;
int len = strlen (word);
int index = 0;
int numindex = 0;
int count;
while (index < len) {
while (word[index] >= '0' && word[index] <= '9') {
temp[numindex++] = word[index++];
}
temp[numindex] = 0;
count = atoi (temp);
numindex = 0;
char ch = word[index++];
for (int i = 0; i < count; i++) {
out[i] = ch;
}
out[count] = 0;
cout << out;
}
return 0;
}

Converting Roman Numerals to Int - Getting the Wrong Output - Why?

Here is my code. First, I want to say, I have been experimenting, so if you see unnecessary variables here and there, that's why. But the main part of my code is in the function decimal in my class romanType. When I input certain roman numerals, I am not getting the exact numbers I want and it might be in my logic somewhere in my if/else statements.
By the way, to show how I traverse the string - I do it by reverse traversing. I go from the very end of the string to the very beginning of the string, which I think is easier with roman numerals. By the way, I also made an enum type so I could compare the roman numerals seeing which one is lesser, which one is greater etc. Then I used a map to be able to compare the enum values with the char value.
So the problem: For instance, when I type in CCC, I get 290 instead of 300. If you know what is wrong in my logic, I would greatly appreciate that! Thank you.
Furthermore, I am quite new to programming and would greatly appreciate any stylistic tips or anything I can learn about classes etc that I missed in writing this code? Please let me know what is best. Thank you.
#include <iostream>
#include <string>
#include <map>
using namespace std;
class romanType {
string numeral;
int k;
public:
romanType();
void rnumeral (string b) {numeral = b;}
int decimal(string num, char b, int temp) {
num = "";
enum RomanNumerals {I, V, X, L, C, D, M };
map<char, RomanNumerals> m;
m['I'] = I;
m['V'] = V;
m['X'] = X;
m['L'] = L;
m['C'] = C;
m['D'] = D;
m['M'] = M;
RomanNumerals roman1;
RomanNumerals roman2;
cout << "Please type in your roman numeral:" ;
cin >> num;
for (int i =0; i <num.length()-1; i++){
}
for(long i = num.length()-1; i>=0; i--)
{
b = num[i];
if (islower(b)) b=toupper(b);
roman1 = m[num[i]];
roman2 = m[num[i-1]];
switch(b){
case 'I':
if(num[i] == num.length()-1){
temp += 1;
}
break;
case 'V':
if(roman1 > roman2){
temp += 4;
continue;
}
else {
temp += 5;
}
break;
case 'X':
if(roman1 > roman2){
temp += 9;
continue;
}
else {
temp += 10;
}
break;
case 'L' :
if(roman1 > roman2){
temp += 40;
continue;
}
else {
temp += 50;
}
break;
case 'C':
if(roman1 > roman2){
temp += 90;
continue;
}
else {
temp += 100;
}
break;
case 'D' :
if(roman1 > roman2){
temp += 400;
continue;
}
else {
temp += 500;
}
break;
case 'M':
if(roman1 > roman2){
temp += 900;
continue;
}
else {
temp += 1000;
}
break;
}
}
return temp;
}
};
romanType::romanType () {
numeral = "";
}
int main() {
string k = "";
char b = ' ';
int temp = 0;
romanType type;
type.rnumeral(k);
int c = type.decimal(k, b, temp);
cout << c;
return 0;
}
EDIT: _____________________________________________________________________________
I found the solution to my problem. Here is my new code:
#include <iostream>
#include <string>
#include <map>
using namespace std;
string acceptRN();
class romanType {
string numeral;
int temp2;
int l;
// VARIABLES
public:
romanType();
//DEFAULT CONSTRUCTOR
void getRnumeral (string b)
{
numeral = b;
}
//SETTER
void decimal(string num, int temp, char b) {
num = numeral;
enum RomanNumerals {I, V, X, L, C, D, M };
map<char, RomanNumerals> m;
m['I'] = I;
m['V'] = V;
m['X'] = X;
m['L'] = L;
m['C'] = C;
m['D'] = D;
m['M'] = M;
RomanNumerals roman1;
RomanNumerals roman2;
RomanNumerals roman3;
for(long i = num.length()-1; i>=0; i--)
{
b = num[i];
if (islower(b)) b=toupper(b);
roman1 = m[num[i]];
roman2 = m[num[i-1]];
roman3 = m[num[i+1]];
switch(b){
case 'I':
if( roman3 > roman1 && i != num.length()-1){
continue;
}
else {
temp += 1;
break;
}
case 'V':
if(roman1 > roman2 && i != 0){
temp += 4;
continue;
}
else {
temp += 5;
}
break;
case 'X':
if( roman3 > roman1 && i != num.length()-1)
continue;
if(roman1 > roman2 && i!= 0){
temp += 9;
continue;
}
else {
temp += 10;
}
break;
case 'L' :
if(roman1 > roman2 && i!= 0){
temp += 40;
continue;
}
else {
temp += 50;
}
break;
case 'C':
if( roman3 > roman1 && i != num.length()-1)
continue;
if(roman2 == X && i!= 0){
temp += 90;
continue;
}
else {
temp += 100;
}
break;
case 'D' :
if(roman2 == C && i!= 0){
temp += 400;
continue;
}
else {
temp += 500;
}
break;
case 'M':
if(roman2 == C && i!= 0){
temp += 900;
continue;
}
else {
temp += 1000;
}
break;
}
}
temp2 = temp;
}
void showDecimal() {
cout << "Here is your roman numeral in decimal format:";
cout << temp2 << " \n \n \n";
}
};
romanType::romanType () {
numeral = "";
}
int main() {
string k = acceptRN();
int m = 0;
char l= ' ';
romanType type;
type.getRnumeral(k);
type.decimal(k, m, l);
type.showDecimal();
return 0;
}
string acceptRN(){
string num = "";
cout << "Please type in your roman numeral:" ;
cin >> num;
return num;
}
When I done the stuff from my comment and tweaked your code a bit I got this:
//---------------------------------------------------------------------------
int roman_ix[256]={-1};
const int roman_val[]={ 1 , 5 ,10 ,50 ,100,500,1000,0};
const char roman_chr[]={'I','V','X','L','C','D', 'M',0};
//---------------------------------------------------------------------------
int roman2int(char *s)
{
int i,x=0,v=0,v0;
// init table (just once)
if (roman_ix[0]<0)
{
for (i=0;i<256;i++) roman_ix[i]=0;
for (i=0;roman_chr[i];i++) roman_ix[roman_chr[i]]=i;
}
// find end of string
for (i=0;s[i];i++);
// proccess string in reverse
for (i--;i>=0;i--)
{
v0=v; // remember last digit
v=roman_val[roman_ix[s[i]]]; // new digit
if (!v) break; // stop on non supported character
if (v0>v) x-=v; else x+=v; // add or sub
}
return x;
}
//---------------------------------------------------------------------------
I tested on these:
1776 1776 MDCCLXXVI
1954 1954 MCMLIV
1990 1990 MCMXC
2014 2014 MMXIV
300 300 CCC
first number is converted from string, second is what it should be and last is the roman string.
If 256 entry table is too big you can shrink it to range A-Z which is significantly smaller but that require one more substraction in the code. It can be also hardcoded to get rid of the initialization:
//---------------------------------------------------------------------------
int roman2int(char *s)
{
// init
int i,x=0,v=0,v0; // A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
const int val['Z'-'A'+1]={ 0, 0, 100, 500, 0, 0, 0, 0, 1, 0, 0, 50, 1000, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 10, 0, 0 };
// find end of string
for (i=0;s[i];i++);
// process string in reverse
for (i--;i>=0;i--)
{
if ((s[i]<'A')||(s[i]>'Z')) break; // stop on non supported character
v0=v; v=val[s[i]-'A'];
if (v0>v) x-=v; else x+=v;
}
return x;
}
//---------------------------------------------------------------------------
As I got rid of your temp and roman1,roman2 and the switch if/else conditions and the code worked from the first compilation ... I am assuming that you are doing something fishy with them (got lost in the if/else combinations missing some edge case).

Parse number until comma

I have a format where, in a string, 88 is to be parsed as the number 88 while 8,8 is to be parsed as two 8s. I need to go through the string, and for every ., push a 0 to a vector, and otherwise push the number(s) at the current position to the vector according to the above rule. Zeros will never appear in the input string. I don't want to use yacc or another BNF parser generator; it would be overkill for my situation. What's the easiest way to do this? Here's what I've go so far; it's only partial and doesn't even compile:
for(int i=0; i<line.length(); i++){
if (line[i] == '.')
puzzle.push_back(0);
else
//do weird comma stuff
//push stuff
}
Example:
line = ".1.1,1.11"
puzzle = {0,1,0,1,1,0,11}
Here's a sketch what it looks like you're asking for (not compiled, not tested):
int value;
bool in_number = false;
while (cin.getline(line)) {
for (int i = 0; i < line.length(); ++i)
switch(line[i]) {
case '.':
if (in_number) {
puzzle.push_back(value);
in_number = false;
}
puzzle.push_back(0);
break;
case ',':
if (in_number) {
puzzle.push_back(value);
in_number = false;
}
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if (in_number) {
value *= 10;
value += line[i] - '0';
} else {
in_number = true;
value = line[i] - '0';
}
break;
}
}
For such tasks common solution is to use regexp:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <regex>
#include <vector>
int main(int argc, char* argv[])
{
std::string s(".1.1,1.11");
std::smatch m;
std::regex e("([0-9]+|\\.)[,]?");
std::vector<int> v;
while (std::regex_search(s, m, e)) {
const std::string& d = m[1];
v.push_back(strtol(d.c_str(), 0, 10));
s = m.suffix().str();
}
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
}
AntolyS's answer is probably cleanest, but I went with a modified version of Pete Becker's answer because I'm a noob and there were to many weird things going on with Antoly's:
int value; bool in_number = false;
for(int i=0; i<line.length(); i++){
if (line[i] == '.'){
if (in_number){
puzzle.push_back(value);
in_number = false;
}
puzzle.push_back(0);
}
else if (line[i] == ','){
if (in_number) {
puzzle.push_back(value);
in_number = false;
}
}
else if (line[i] > '0' && line[i] <= '9'){
if (in_number) {
value *= 10;
value += line[i] - '0';
} else {
in_number = true;
value = line[i] - '0';
}
}
}