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

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

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;
//...

How to count words and numbers from a simple sentence in C++

I'm a beginner at c++(took a couple classes, then no c++ for a while, then starting back up several months later), and I'm trying to count the number of words in a simple sentence and then count the number of numbers in that same sentence. To count the words, I use:
int countWord(char *word)
{
int counter = 0;
char *words = strtok(word, " 0123456789-");
while (words != NULL)
{
counter++;
words = strtok(NULL, " 0123456789-");
}
return counter;
}
The number counter is basically the same, just instead of using integers I use the alphabet.
char *num = strtok(number, " abcdefghijklmnopqrstuvwxyz");
My main is:
int main()
{
char str[] = "what time is 88 it 99today";
cout << "words = " << countWord(str) << " " << "numbers = " <<
countNum(str) << endl;
system("pause");
return 0;
}
When I run this it outputs: words = 3 numbers = 2.
When i rearrange main to:
char str[] = "what time is 88 it 99today";
cout << "words = " << countWord(str) << " ";
cout << "numbers = " << countNum(str) << endl;
output is: words = 5 numbers = 0
Can anyone explain why this is incorrect? Also, if anyone can refer me to a text that covers this, I'd appreciate that. The text I learned from is: "C++ Programming: Program Design Including Data Structures by D.S. Malik. I didn't see any techniques in this book to count "words". Thank you.
The issue is that strtok marks the end of tokens in the original string by a null character. Citing from cppreference:
If such character was found, it is replaced by the null character '\0' and the pointer to the following character is stored in a static location for subsequent invocations.
Notes: This function is destructive: it writes the '\0' characters in the elements of the string str. In particular, a string literal cannot be used as the first argument of strtok.
In your case the line
cout << "words = " << countWord(str) << " " << "numbers = " <<
countNum(str) << endl;
is a composition of operator<<, like
...operator<<(operator<<(cout, "words"), countWord(str))...
so the line countNum(str) is evaluated first. Then countWord(str) is evaluated secondly. This is in contrast to
cout << "words = " << countWord(str) << " ";
cout << "numbers = " << countNum(str) << endl;
where the other way around happens.
One solution is to use a copy of the original string when using strtok, e.g. use strtok(strdup(str)) every time. Better yet, use standard C++ library features, like std::string, std::count_if etc. I'm sure there are plenty of word counting solutions around using pure C++.
Vlad has submitted a nice answer for your C-style code. My answer is demonstrating use of more C++ libraries to help move things along:
#include <iostream>
#include <string>
#include <vector>
#include <regex>
int main() {
// The main string.
std::string str = "what time is 88 it 99today";
// Space is your delimiter
std::string delimiter = " ";
// Create a regex string for matching numbers, including floating point.
std::regex number_chars(std::string("[0123456789.]+"));
// A lambda function to help tokenize strings.
// Returns a vector of substring tokens.
// The internal code is taken from an answer on Stack Overflow.
auto tokenizer = [](std::string s, std::string delimiter) {
size_t pos = 0;
std::string token;
std::vector<std::string> tokens;
while (pos = (s.find(delimiter))) {
token = s.substr(0, pos);
tokens.push_back(token);
s.erase(0, pos + delimiter.length());
if (pos == std::string::npos)
break;
}
return tokens;
};
// Apply the lambda.
auto tokens = tokenizer(str, delimiter);
// Output your tokens.
for (auto it : tokens) {
std::cout << it << "\n";
} std::cout << "\n";
// Output tokens that are numbers.
for (auto it : tokens) {
if (std::regex_match(it, number_chars)) {
std::cout << "String: " << it << " is a number.\n";
}
}
return 0;
}
Since C++ has a regular expression library in C++11, it would be good to leverage it.
Coliru: http://coliru.stacked-crooked.com/a/43cd6711e1243f4a

One-Second Timer [duplicate]

This question already has answers here:
Delay execution 1 second
(4 answers)
Closed 8 years ago.
I need a timer that does X every second.
I made this, however it doesn't print anything until the program is terminated, I find that weird.
It prints everything after three seconds if you put three as the counter, and 100 if you chose that.
How do make it print every second and not all at once at termination?
int main()
{
using namespace std;
//Number to count down from
int counter = 10;
//When changed, a second has passed
int second = (unsigned)time(NULL);
//If not equal to each other, counter is printed
int second_timer = second;
while (counter > 0) {
second = (unsigned)time(NULL);
while (second != second_timer) {
//Do something
cout << counter-- << ", ";
//New value is assigned to match the current second
second_timer = second;
}
}
cout << "0" << endl;
return 0;
}
Add << flush where you want to flush. I.e. change your printout to:
cout << counter-- << ", " << flush;
endl causes the buffer to 'flush' and be written out to stdout. You can add << endl; to your cout << counter--, manually flush the cout stream using cout.flush();, or append << flush; to the end of your cout expression (thanks #Rob!)
For more info, the answer to this question seems to go into more detail.

Return doesn't work with float or int, but does work with string?

First, let me apologize if this is the world's stupidest question. But, I'm stumped and I've done a bunch of searching both here and on Google. I'm teaching myself C++, so it's possible I just don't have to vocabulary necessary to know what to search for.
I'm trying to write a Finite State Machine to parse equations. I know it's been done before, but I'm trying to learn. To that end, I want to be able to take a string, recognize numbers, and convert them to doubles or floats. (I'll entertain any advice you have on which format to use.)
I have a function to convert a string to a double:
double convertToDouble(string value)
{
/* -- From http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.2
Using stringstream, convert a string to a double by treating it like a stream
*/
istringstream stream(value);
double doubleValue;
stream >> doubleValue;
return doubleValue;
}
And I have a function to look for the next numeric value in a string:
string evaluateNextValue (int operatorPosition, string equation)
{
/* -- Find the next value
My idea is that, since I'm using spaces as my dividers, we'll look for
the first number and then, using insert to put the individual numbers
into a string until a space is found again. Then, the numbers--now
in the correct order--can be converted to a double and returned
*/
bool digitFound = false;
string workingNumbers;
for (int pos = operatorPosition; pos < equation.size(); pos ++)
{
if (equation.at(pos) == ' ' && digitFound == true)
{
double result = convertToDouble(workingNumbers);
cout << "Converting a string to " << result << endl;
cout << "The result plus one is: " << result +1 << endl;
return workingNumbers;
} else if (equation.at(pos) == ' ' && digitFound == false)
{
cout << "Skipping a blank space." << endl;
continue;
} else
{
if (digitFound == false)
{
digitFound = true;
cout << "First digit found." << endl;
}
cout << "Adding " << equation.at(pos) << " to the string." << endl;
workingNumbers.insert(workingNumbers.end(),equation.at(pos));
}
}
}
And this is the main() I'm using to call them both as a sort of test.
int main()
{
string dataInput;
cout << "Insert a number" << endl;
getline(cin, dataInput);
cout << "You entered: " << dataInput << endl;
double numberValue = convertToDouble(evaluateNextValue(0, dataInput));
cout << "Adding ten: " << numberValue + 10;
return 0;
}
Here's the thing: as it is now, with the evaluateNextValue() returning a string, it works. It seems a bit ungainly to me (may it all seems ungainly to you), but it works.
When I have the code manipulate the variable result in the function, it works fine. I just convert the string to a double and I can work with it.
BUT, when I convert the string to a double and try to return the double. . . the double works fine in the function itself. But it's nan when it arrives in main(). Even weirder (or just as weird, at any rate) is the fact that trying to return an int DOES return an int, but never anything remotely connected to the value I enter.
I'd appreciate any help you care to offer. And, as this is my first post here, I'm open to any style pointers.
The return value is undefined if evaluateNextValue arrives at the end of the string due to the for loop condition (because you have no return statement there). This triggers undefined behaviour, which can include returning NaN values.
You should enable your compiler's warnings to catch such errors.

Converting ascii substr to int

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;