Converting ascii substr to int - c++

first year college having problem converting ascii into int.
The problem is this piece of code
unsigned short iminutes = ((minutes[3]-48)*10) + (minutes[4]-48);
When I run this on codeblocks at home it returns an incorrect value, when I run it again I get a different incorrect value.
When I run it at on Borlands at college, the screen just ups and disappears before I can read it, so I can't use the system clock here either.
It's Easter hols now so even though I'm at college, I can't annoy my tutors because they're not.
#include <iostream.h>
#include <conio.h>
#include <string>
//#include <time.h>
//#include <ctype.h>
using namespace std;
int main() {
bool q = false;
do {
// convert hours to minutes ... then total all the minutes
// multiply total minutes by $25.00/hr
// format (hh:mm:ss)
string theTime;
cout << "\t\tPlease enter time " << endl;
cout <<"\t\t";
cin >> theTime;
cout << "\t\t"<< theTime << "\n\n";
string hours = theTime.substr (0, 2);
cout <<"\t\t"<< hours << endl;
unsigned short ihours = (((hours[0]-48)*10 + (hours[1] -48))*60);
cout << "\t\t"<< ihours << endl;
string minutes = theTime.substr (3, 2);
cout <<"\t\t"<< minutes << endl;
unsigned short iminutes = ((minutes[3]-48)*10) + (minutes[4]-48);
cout << "\t\t" << iminutes << endl;
cout << "\n\n\t\tTotal Minutes " <<(ihours + iminutes);
cout << "\n\n\t\tTotal Value " <<(ihours + iminutes)*(25.00/60) << "\n\n";
}
while (!q);
cout << "\t\tPress any key to continue ...";
getch();
return 0;
}

You set minutes to be a substring of theTime. So minutes has 2 characters. The first one starting at position 0 within minutes.
So this
unsigned short iminutes = ((minutes[3]-48)*10) + (minutes[4]-48);
is wrong as it accesses characters 3 and 4 in minutes which don't exist, because minutes is only two characters long. It only has characters as positions 0 and 1.
should be this
unsigned short iminutes = ((minutes[0]-48)*10) + (minutes[1]-48);
or you could use this:
unsigned short iminutes = ((theTime[3]-48)*10) + (theTime[4]-48);

The problem is that even though you get the characters at position 3 and 4 from the original string, the new string is just two characters (i.e. only have index 0 and 1).

istringstream iss(theTime.substr(0, 2));
iss >> ihour;

Related

Stringing together multiples of the same string (an asterisk) determined by an input file. C++

Essentially, the objective is to read an input file (hence inFile and inFileName) and output a population growth with asterisks representing each 1000 people using an ID (ex. 1375892), going from the year 1900 to 2020 in 20-year increments.
So, 1 asterisk for 1000 people, 3 asterisks for 3000 people, etc. The input file has numbers like 5000 and 7000 that I need to use to calculate the number of asterisks I need (by dividing by 1000). Even with that, I'm trying to figure out the final step in converting asteriskNum (the number of asterisks I need to use) and have it output the string of asterisks, not an integer of how many asterisks I need.
I definitely know I'm missing SOMETHING, but even after asking my teacher and scouring through my textbook and notes, I can't figure out how to solve this specific issue.
#include<iostream>
#include<iomanip>
#include<string>
#include<fstream>
using namespace std;
int main(){
string asterisk = "*";
string firstName;
int PopNum{0};
int year{1900};
int asteriskNum{};
const string INTROLINE{"POPULATION GROWTH \n(each * represents 1000 people)"};
cout << INTROLINE << "\n";
string inFileName="DL8_L5_Morrison.txt";
ifstream inFile{inFileName};
if (inFile){
cout << inFileName << " opened for reading. \n";
inFile >> firstName;
while (not inFile.eof()){
inFile >> PopNum;
asteriskNum = PopNum/1000;
cout << year << " " << asteriskNum << " " << << "\n";
year+=20;
inFile.close();
}
else {
cout << inFileName << " did not open for reading. \n";}
cout<<"Goodbye!\n";
return EXIT_SUCCESS;
}
}
You can use a std::string object and use the constructor that takes a count and character as arguments (constructor version #2 here). This will work with an int for the count argument, but it is better to cast it to a size_t type (or just have the calculated value as a size_t in the first place):
//...
asteriskNum = PopNum/1000;
cout << year << " " << std::string(static_cast<size_t>(asteriskNum), '*') << std::endl;
//...

C++ program if statements in function not executing. Seems Logically errored

I am making a program in C++, that takes the user entered time in U.S. standard time and converts it to military time. The body of the main code is executing fine, but the problem comes in the body of my function beginning with the if statements. I am wondering why this is occurring; am fairly new with c++. Here's my code if you have question feel free to ask or need explanation of what the program is supposed to be doing.
#include <iostream>
#include <string>
using namespace std;
void militaryConversion(string am_pmPart_st, string firstPartofTime, string secondPartofTime){
// Converts they obtained strings, but first we must concatenate the two parts into one string
string concatenatedTime;
int militaryTime;
cout << "test1" << endl;
concatenatedTime = firstPartofTime + secondPartofTime;
if(firstPartofTime == "12")
{
cout << "Corresponding military time is: " << concatenatedTime << " hours" << endl;
}
else if(am_pmPart_st == " am")
{
if (concatenatedTime.length() < 4){
cout << "Corresponding military time is: " << concatenatedTime << " hours"<< endl;
}
}
else if(am_pmPart_st == " pm")
{
int castedTime;
castedTime = stoi(concatenatedTime); //This is where we convert the string to int because its the only place it matters
militaryTime = castedTime + 1200;
cout << "Corresponding military time is: " << militaryTime << " hours" << endl;
}
}
int main()
{
char DELEMETER = ':';
char DELEMETER_sp = ' ';
string time, firstPartofTime, secondPartofTime, am_pmPart_st, loweredAM_PM;
cout << "Enter the time in the format of: HH:MM AM/PM ";
getline(cin, time);
firstPartofTime = time.substr(0, time.find(DELEMETER));
cout << "The first digits of time " << firstPartofTime << endl;
secondPartofTime = time.substr(time.find(DELEMETER) + 1, time.find(DELEMETER_sp)-1);
cout << "The second set of digits " << secondPartofTime << endl;
am_pmPart_st = time.substr(time.find(DELEMETER_sp), time.size());
cout << "The am/pm part is:" << am_pmPart_st << endl;
for(int i=0; am_pmPart_st[i]; i++) am_pmPart_st[i] = tolower(am_pmPart_st[i]); //Converts am/pm to lowercase
cout << am_pmPart_st << endl;
militaryConversion(am_pmPart_st, firstPartofTime, secondPartofTime);
}
First, your question is vague because it does say what is happening that should not be happening. However, I think I can see what is happening. When you check for the hour part of the time in the first condition, you check for "12" first. However, you never correct for am or pm within that 12. My recommendation would be to check for 12 inside the am (12 am == 0000 hours) and pm (12 pm == 1200 hours). In am you will need to check for 12 and subtract 1200 from the time, in pm you will need to check for 12 and not add 1200 to the time.
substr takes two parameters. The first is the start position and the second is the length. When you call secondPartofTime = time.substr(time.find(DELEMETER) + 1, time.find(DELEMETER_sp)-1); you are mistakenly passing the second parameter as the end position, not the length.
Instead, you can do:
int startPos = time.find(DELEMETER) + 1;
int endPos = time.find(DELEMETER_sp) - 1;
secondPartofTime = time.substr(startPos, endPos - startPos + 1);
Ideally, you should check the return values of find and handle the case when npos is returned so you don't crash on invalid user input.
Input which doesn't follow the HH:MM AM/PM form is creating a problem. (Exactly 5 characters for HH:MM (including colon))
You have an if-else based decision tree, where one if is not accompanied by an else. The lack of else is why your program is not giving any output
string.substr() has some issues as explained by MFisherKDX

Extracting hours, minutes and seconds from binary encoding

I wrote a program to solve the exercise below. I got my hours and minutes right, but I cannot get my seconds right.
In order to save disk space Time field in the directory entry is 2
bytes long. Distribution of different bits which account for hours,
minutes and seconds is given below:
15 14 13 12 11|10 9 8 7 6 5| 4 3 2 1 0
H H H H H| M M M M M M| S S S S S
Write a C++ Program that take input two-byte time entry and
appropriately separates hours, minutes and seconds using suitable
bitwise operators.
#include<iostream>
using namespace std;
int main()
{
unsigned int hours, mins, secs;
unsigned int time;
cout << "enter time ";
cin >> time;
hours = (time >> 11);
mins = ((time << 5) >> 10);
secs = ((time << 11) >> 11);
cout << hours << " " << mins << " " << secs << endl;
return 0;
}
To get the minutes, I shift the input to the left by 5 positions, hoping to eliminate all the H bits, and then shift to the right by 10 positions to eliminate all the S bits and have the M bits at the rightmost position.
Similarly for the seconds.
However, if I enter 445 I expect the result to be 13 minutes and 29 seconds, but the program outputs 0 13 445.
Why do the hours and minutes appear to come out correctly, but not the seconds?
secs = time & 0x1F; // This should give the 5 bits you're expecting for seconds.
You are assuming that the size of unsigned int is 16 bit but it is normally implemented as 32bit integer on nowadays machines.
If you would use uint16_t for the variable time instead it should work.
To use uint16_t include the header stdint.h.
#include <iostream>
#include <stdint.h>
using namespace std;
int main()
{
uint16_t hours, mins, secs;
uint16_t time = 445;
hours = (time >> 11);
mins = ((time << 5) >> 10);
secs = (time << 11);
secs >>= 11;
cout << hours << " " << mins << " " << secs << endl;
return 0;
}
(Tested on QT 5.5)
You should zero the bits that don't correspond to the part of time you are looking at. I will use binary literals (which are available in C++14), but comment the equivalent hex literals.
struct time {
time(unsigned = 0); // also default constructs
unsigned hours;
unsigned mins;
unsigned secs;
}
time::time(unsigned packed) :
hours((packed & 0b1111100000000000) >> 11), // 0xF800
mins ((packed & 0b0000011111100000) >> 5 ), // 0x07E0
secs ((packed & 0b0000000000011111) ) // 0x001F
{ }
#include<iostream>
std::ostream& operator<< (std::ostream& os, time t) {
return os << t.hours << " " << t.mins << " " << t.secs;
}
int main()
{
time t(445);
std::cout << t << std::endl;
return 0;
}
The task given is impossible, because 6 bits are required for both the minutes and the seconds. You have alotted 5 bits for the seconds.
2^5=32
2^6=64
Using this scheme, 17 bits are required to represent the time.

C++ fstream keep reading the same first 5 lines?

I'm really frustrated. I'm trying to read a txt file which has the following content:
Arenas
Edward
239924731
2525976612
Autry
Richard
527646269
6028236739
Using this code :
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main(int argc, const char * argv[])
{
string line;
string last, first;
int uin, number;
ifstream phoneBook;
phoneBook.open("PhoneBook.txt");
while (!phoneBook.eof()) {
phoneBook >> last >> first >> uin >> number;
cout << last << ", " << first << ", " << uin << ", " << number <<endl;
}
return 0;
}
The output would be the same contact endlessly
Arenas, Edward, 239924731, 2147483647
Arenas, Edward, 239924731, 2147483647
Arenas, Edward, 239924731, 2147483647
Arenas, Edward, 239924731, 2147483647
Arenas, Edward, 239924731, 2147483647
I also tried this version of while loop:
while (phoneBook >> last >> first >> uin >> number) {
cout << last << ", " << first << ", " << uin << ", " << number <<endl;
}
For some reasons, the compiler doesn't even step into the loop. It would just jump to return 0;
Your number values are too big to fit into a four-byte signed integer. Maximum value for that is 2147483647 (2^31 - 1), which is why you get that printing out at the end. (You weren't asking about that issue; I don't know how I noticed it myself!)
But what I'm also wondering about is that extra line that you have in between each record. I found this question that discusses fstreams and delimiters. I wonder if it's getting stuck at the blank line, reading nothing, and then just outputting the same values of last, first, uin, and number.
There may be a different type of error. The best method to use is ios::good:
while (!phoneBook.good()) {

Reading input from text file to array in c++ [duplicate]

This question already has answers here:
Reading input from text file to array in c++
(2 answers)
Closed 4 years ago.
Alright, be gentle, since I'm very much a novice to programming. So far I've only studied C++ and I'm running Visual Studio 2010 as my compiler. For this program, I'm trying to read from a text input file and write the information to a set of three arrays. One array will handle a list of names, and the other two are for hours worked and hourly pay rate, respectively. I will use the latter two to calculate a set of earnings and output those calculations to another text file. My problem, however, is with acquiring input for the first array. The input file I'm using has text arranged like this:
J. Doe* 35 12.50
J. Dawn* 20 10.00
.........
The names are trailed by asterisks since I'm trying to use ifstream getline to acquire the names with the asterisks acting as delimiters, and writing the following two numbers into the other two arrays. The latter two values are separated by whitespaces, so I don't think they'll cause any problems. I'm sure there are other errors that need handling but I need to work through the first error before I can start debugging the rest. I encounter an error with the line where I call inFile.getline, which reads as follows:
error C2664: 'std::basic_istream<_Elem,_Traits> &std::basic_istream<_Elem,_Traits>::getline(_Elem *,std::streamsize,_Elem)' : cannot convert parameter 1 from 'std::string' to 'char *'.
From what I've read elsewhere, (I think) the problem stems from trying to write a string to a char array, which won't work since they are of different data types. I'm not sure if other feasible methods exist for acquiring the names since I need the delimiter to separate the names from the numerical values. Any advice on how to resolve this issue would be much appreciated.
Here is the source I've written:
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;
const int EMP_NUM = 5;
const int BASE_HOURS = 40;
const char N_SIZE = 8;
int main()
{
int i;
double rEarnings, oEarnings, tEarnings,
trEarnings, toEarnings, ttEarnings;
ifstream inFile;
ofstream outFile;
inFile.open("records.txt");
outFile.open("report.txt");
outFile << setprecision(2) << showpoint << fixed;
outFile << setw(50) << "Payroll Report" << "\n\n";
outFile << "EMPLOYEE NAME" << setw(25) << "REGULAR EARNINGS" << setw(25) << "OVERTIME EARNINGS" << setw(25) << "TOTAL EARNINGS" << endl;
string nameAr[EMP_NUM];
int hoursAr[EMP_NUM];
double hrateAr[EMP_NUM];
for (int i = 0; i < EMP_NUM; i++) // Get input from our input file.
{
inFile.getline(nameAr[i], EMP_NUM, "*");
inFile >> hoursAr[i] >> hrateAr[i];
}
for (int i = 0; i < EMP_NUM; i++) // Make the calculations to be sent to our report.
{
char nameAr[N_SIZE];
int hoursAr[N_SIZE];
double hrateAr[N_SIZE];
if (hoursAr[i] > 40) // For employees with overtime hours.
{
// double rEarnings, double oEarnings, double tEarnings,
// double trEarnings, double toEarnings, double ttEarnings;
// rEarnings = 0, oEarnings = 0, tEarnings = 0,
// trEarnings = 0, toEarnings = 0, ttEarnings = 0;
rEarnings = BASE_HOURS * hrateAr[i];
oEarnings = (hoursAr[i] - BASE_HOURS) * hrateAr[i] * 1.5;
tEarnings = rEarnings + oEarnings;
trEarnings += rEarnings;
toEarnings += oEarnings;
ttEarnings += tEarnings;
outFile << left << nameAr[i];
// << setw(25) << right << rEarnings << setw(25) << right << oEarnings << setw(25) << right << tEarnings << endl;
}
else // For employees without overtime hours.
{
double rEarnings, double oEarnings, double tEarnings,
double trEarnings, double toEarnings, double ttEarnings;
rEarnings = 0, oEarnings = 0, tEarnings = 0,
trEarnings = 0, toEarnings = 0, ttEarnings = 0;
rEarnings = hoursAr[i] * hrateAr[i];
oEarnings = 0;
tEarnings = rEarnings + oEarnings;
trEarnings += rEarnings;
toEarnings += oEarnings;
ttEarnings += tEarnings;
outFile << left << nameAr[i] << setw(25) << right << rEarnings << setw(25) << right << oEarnings << setw(25) << right << tEarnings << endl;
}
}
outFile << endl << endl;
outFile << setw(33) << trEarnings << " *" << setw(23) << toEarnings << " *" << setw(23) << ttEarnings << " *\n\n";
outFile << left << "TOTAL EMPLOYEES" << " " << (i - 1);
inFile.close(); outFile.close();
return 0;
}
I've included the entire program to give you an idea of where I plan to go with the coding. Thanks in advance for the help!
Hello C++ new programmer! Welcome to the awesomeness of coding in C/C++.
I know you just started C++. But to fix your problem, we have to touch a bit of C. C++ so happens to be a superset of C. Meaning everything that can be done in C will work in a C++ program.
Ok enough words, code time. Replace the code you use to get input from your input file with this:
char tmp[256];
memset(tmp, '\0', sizeof tmp);
inFile.getline(tmp, EMP_NUM, '*');
nameAr[i] = tmp;
inFile >> hoursAr[i] >> hrateAr[i];
Let's walk through it.
char tmp[256]; will create a temporary array for reading in the values. The size of this array may vary with the average length of names you receive.
Strings in C are like high maintenance chics. You have to specify a NULL character '\0' at the end or they may crash your program with not-so-obvious Segmentation faults. However, Memset is a little man that works down in the mines of a computer; he's gonna help us fix this. When called in this form memset(tmp, '\0', sizeof tmp), memset starts at the address of tmp, walks through all the bits of the array - the size id specified as sizeof tmp - and sets these bits to the character specified - in this case NULL. This way we would not have to remember to append the NULL character every-time we read in a C string; provided the size of tmp is sufficiently large. Convenient!
inFile.getline(tmp, EMP_NUM, '*'); reads the input [string] from your file as expected and stores it in tmp.
nameAr[i] = tmp; puts the input read into the names array.
and finally, inFile >> hoursAr[i] >> hrateAr[i]; reads the hours and hourly rates as before.
Hope this helps.
Cheers!
Happy Learning.
I would not use getline in this way, because you have two separate separator chars to deal with - space and asterisk. Here's what I would do instead:
Use getline to get the FULL line into a string called line.
Find the asterisk using line.find('*');
Extract the name as a new string using line.substr up to the position just found
Take another substr beyond the asterisk into a stringstream called remainder.
Read the int and double directly from it using operator>>: remainder >> hours >> rate;