I can't enter 01 into my c++ input, it will return with empty result but when i type other date such as 12 and 11 it does show in the system.
string month;
cin.ignore(1, '\n');
cout << "Please Enter Month For Example 01 for January:";
getline(cin, month);
string search_query = "SELECT DATE(OrderDate), SUM(TotalPrice) FROM order1 WHERE MONTH(OrderDate) like '%" + month + "%' GROUP BY DATE(OrderDate)";
const char* q = search_query.c_str();
qstate = mysql_query(conn, q);
DATABASE
This is what happen if I enter "01"
This is what happen when I enter "11"
This is when I type "12" it successfully show
The problem is that you are using the LIKE operator in MySQL, which checks to see if the pattern specified on the right occurs in the string specified on the left. The pattern "01" probably doesn't occur in the value on the left, since the string on the left should be "1" for January orders, and that doesn't have a "0" in it.
I also imagine that if you type "1" you would actually see all orders from January, October, November, and December since all those months have "1" in them.
Try using something like MONTH(OrderDate) = 1 instead.
To be more explicit: try changing the line in your program that defined search_query to this:
std::string search_query = "SELECT DATE(OrderDate), SUM(TotalPrice) FROM order1 WHERE MONTH(OrderDate) = " + month + " GROUP BY DATE(OrderDate)";
By the way, for a more robust program, you should also make sure you turn the user-supplied month number into an integer before adding it to the query string; right now you are letting users insert arbitrary strings into your query, which could be dangerous.
Related
I'm learning Python through Codeacademy, and I'm having trouble with their Madlibs exercise. I've viewed the walkthrough after I began having trouble, but I can't see any differences between their code and mode. This is my code:
STORY = "This morning % woke up feeling %. 'It is going to be a % day!' Outside, a bunch of %s were protesting to keep % in stores. They began to % to the rhythm of the %, which made all the %s very %. Concerned, % texted %, who flew % to % and dropped % in a puddle of frozen %. % woke up in the year %, in a world where %s ruled the world."
print "Let the Madlibs begin!"
name = raw_input("Enter a name: ")
print "Please provide three adjectives: "
adj_1 = raw_input("1: ")
adj_2 = raw_input("2: ")
adj_3 = raw_input("3: ")
verb = raw_input("Enter a verb: ")
print "Now, input two nouns:"
noun_1 = raw_input("1: ")
noun_2 = raw_input("2: ")
print "Please provide a word for:"
animal = raw_input("An animal: ")
food = raw_input("A food: ")
fruit = raw_input("A fruit: ")
superhero = raw_input("A superhero: ")
country = raw_input("A country: ")
dessert = raw_input("A dessert: ")
year = raw_input("A year: ")
print STORY % (name, adj_1, adj_2, animal, food, verb, noun_1, noun_2, adj_3, name, superhero, name, country, name, dessert, name, year, noun_2)
When I run the program, I get the following error:
Traceback (most recent call last): File "Madlibs.py", line 34, in
print STORY % (name, adj_1, adj_2, animal, food, v erb, noun_1, noun_2, adj_3, name, superhero, name, cou ntry, name, dessert, name,
year, noun_2) ValueError: unsupported format character 'w' (0x77) at
index 15
Please help me see what I'm missing. Thank you!
Your format string (STORY) has some invalid placeholders in it. When you're formatting a string, you have to specify what type of data will be put at each placeholder. You do this by putting a letter after the % sign. In this case, since you're always putting in a string, that should be an s. So, STORY should start like this:
STORY = "This morning %s woke up feeling %s. [...]"
There are more details about this syntax in the Python documentation, which explains how to do things like format numbers in a certain way.
(However, it's worth bearing in mind that in modern Python we normally use a newer syntax using str.format(), which looks like this:
STORY = "This morning {name} woke up feeling {adj_1}. [...]"
print STORY.format(name="James", adj_1="terrible")
)
I'm creating a program that takes in the users grade(A-F), health(0-100) and economic output(0-100). I need a while loop for when the user inputs a value wrong e.g A for health. why does the loop keep repeating? how do I do this for the grade as well?
name = raw_input(' Enter your name: ')
grade = raw_input(' Enter your grade: ')
string_two = raw_input(' Enter your economic out put: ')
while string_two not in range (0,100):
print 'please enter a value between 0 and 100.'
string_two = raw_input(' Enter your economic out put: ')
string_one = raw_input(' Enter your health: ')
while string_one not in range (0,100):
print 'please enter a value between 0 and 100.'
string_one = raw_input(' Enter your health: ')
health == int(string_one)
economic_output == int(string_two)
if economic_output > 85:
print name + ' you are exceptional! Welcome aboard!'
elif grade == 'A':
print name + ' you are exceptional! Welcome aboard!'
elif economic_output > 60:
if health > 60:
if grade == 'B' or 'C':
print 'Congatulations ' + name +'!' + ' Come aboard!'
else:
print 'Sorry, ' + name + ' but you dont meet the criteria and cammot be permitted to board. '
The while loop keeps repeating because raw_input always returns a string object, regardless if you typed digits only or something else. string_two not in range (0,100) is always true because a string cannot be in any range of ints.
So what you can do. If I were you, I would define a function which would ask the user to enter something in a while loop until his input satisfies some pattern (just as you are trying to do in your code) and convert it to a specific type if necessary. There is a very useful tool to check a string for matching some pattern, it is called regular expressions (RE).
import re
def inputAndValidate(prompt, pattern, convertFunc=str):
result = raw_input(prompt)
while re.match(pattern, result) is None:
print 'Input pattern is "' + pattern + '". Please enter a string matching to it.'
result = raw_input(prompt)
return convertFunc(result)
Putting a piece of code being used several times to a function is a good practice. So here I defined a function called inputAndValidate with 2 mandatory parameters - a prompt to be displayed for user to let him understand what do you want from him, and the pattern to check his input. The third parameter is optional - it's a function which will be applied to the user input. By default, it's str, a function converting something to a string. User input is already a string, so this function will do nothing, but if we need an int, we'll pass int as the third parameter and get an int from the inputAndValidate function, and so on.
re.match(pattern, string) returns a match object if the string did match the pattern, and None if it didn't. See official re documentation for more information.
Usage of the function
name = inputAndValidate('Enter your name: ', r'.+')
# This pattern means any string except empty one. Thus we ensure user will not enter an empty name.
grade = inputAndValidate('Enter your grade (A-F): ', r'[A-F]')
# This pattern means a string containing only one symbol in the A-F range (in the ASCII table).
economic_output = inputAndValidate('Enter your economic output (0-100): ', r'\d{1,3}', int)
# This pattern means a string containing from one to three digits. `int` passed to the third parameter means the result will be an int.
health = inputAndValidate('Enter your health (0-100): ', r'\d{1,3}', int)
# Same as the previous one.
re module documentation also contains information about the regular expressions language, it can help you understand the patterns I used.
There are two files, each has multiple columns of data, up to around 14,000 rows, neatly spaced and everything. File1 has 6 columns (Student ID #, semester code #, class name, class code # (though some have letters), the letter grade the student received, and the numeric grade they received.
The second file has 4 columns. Class name, class code, how many hours per week it is, and designation code (three letters indicating whether its a liberal arts class or not).
The task is to output everything from the first file into the new file, but add on two columns (from the second file) corresponding to each appropriate row, that have the hours for the course and designation code.
The second task is to take this new file, and output into it the students ID, overall GPA, GPA in CSCI courses, and a percent of hours spent taking non-liberal arts courses.
I'm not asking for someone to do it for me (obviously), it's just that I've run out of ideas. We're supposed to use nothing more than fstream, iostream, strings, if statements, loops, functions, and " .clear(); " and " seekg(ios::beg); " (also we're not supposed to use getline)
basically super simple stuff, no arrays or vectors or anything.
I figured out how to output parts of the two files into the third file using while loops and if statements, but I have no idea how to tell it to compare values in a column from one file to a column in a different file and that if the values are equal, to output the corresponding values from the other columns (the amount of hours for each class and designation code). And I need a lot of help with the second task as well.
What you're looking for is a map. If you need help streaming into a map you can check out this post: Is there a Way to Stream in a Map?
But what you'll want to do is stream File2 into a map, useing the "class code" as the map key, and a tuple or your own custom struct as value. Then index that map with the "class code #" from the line you're currently outputting from File1, appending the appropriate elements of the map's indexed value.
All this may sound like hand-waving, so, because the question lacks an exemplary input and output, I have created an exemplary File1 input as though it had already been streamed in: tuple<int, int, string, string, char, int> File1[] = {make_tuple(13, 1, "Computer Science 1", "CS101", 'A', 100), make_tuple(13, 2, "Computer Science 2", "CS201", 'A', 100)}; and File2 input as though it had already been streamed in: map<string, tuple<string, int, string>> File2 = {make_pair("CS101", make_tuple("Computer Science 1", 4, "NOT")), make_pair("CS201", make_tuple("Computer Science 2", 4, "NOT"))};
These can then be streamed out, potentially to another file as follows:
for(auto& it : File1) {
const auto& i = File2[get<3>(it)];
cout << get<0>(it) << ' ' << get<1>(it) << ' ' << get<2>(it) << ' ' << get<3>(it) << ' ' << get<4>(it) << ' ' << get<5>(it) << ' ' << get<1>(i) << ' ' << get<2>(i) << endl;
}
[Live Example]
I want to extract the minutes and seconds from an time stamp of ISO8601 format. I made some tries with regexp but I have no experience on that.
Could you please help me on this?
Examples:
PT1M46S --> 1 minute, 46 seconds
PT36S --> 36 seconds
Thanks!
getPart = #(str, c) str2double(['0' regexp(str, ['\d*(?=' c ')'], 'match', 'once')]);
str = 'PT36S';
seconds = getPart(str, 'S');
minutes = getPart(str, 'M');
hours = getPart(str, 'H');
This looks for character c, finds the digits behind it and converts them to a double. It adds character '0' in the beginning because if regexp can't find a match it returns an empty string. Adding this converts empty strings to zero while not affecting other numbers. If you want to restrict it to the parts after PT, you can remove that from original string using
str = regexprep(str, '^.*PT', '');
Use datevec to turn strings representing hours, minutes etc into corresponding numeric values. See "help datestr" to understand rules for symbols used in second input to datevec, ie. the format string. Here's how you can convert the two examples given, I leave it to you to extend it to cover the entire format.
str = 'PT36S';
str = strrep(str, 'PT', ''); % PT have to go.
if ~ismember('M', str)
% To use a single format string, we must write zero minutes if none are there already
str = ['00M', str];
end
% Date string cannot contain characters y,m,d,H,M or S, so remove these
str = strrep(str, 'S', ' ');
str = strrep(str, 'M', ' ');
% Call datevec with appropriate format string
[~, ~, ~, ~, min, sec] = datevec(str, 'MM SS')
You can extend this to manage hours, days etc by including additional if loops similar to that above. I am not familiar with this standard beyond the examples given so let me know if it's not as simple as that.
Hi does any one know a reg ex for a uk date format e.g. dd/mm/yyyy.
The dd or mm can be 1 character e.g. 1/1/2010 but the year must always be 4 characters.
Thanks in advance
^\d{1,2}/\d{1,2}/\d{4}$
will match 1/1/2000, 07/05/1999, but also 99/77/8765.
So if you want to do some rudimentary plausibility checking, you need
^(0?[1-9]|[12][0-9]|3[01])/(0?[1-9]|1[012])/\d{4}$
This will still match 31/02/9999, so if you want to catch those, it's getting hairier:
^(?:(?:[12][0-9]|0?[1-9])/0?2|(?:30|[12][0-9]|0?[1-9])/(?:0?[469]|11)|(?:3[01]|[12][0-9]|0?[1-9])/(?:0?[13578]|1[02]))/\d{4}$
But this still won't catch leap years. So, modifying a beast of a regex from regexlib.com:
^(?:(?:(?:(?:31\/(?:0?[13578]|1[02]))|(?:(?:29|30)\/(?:0?[13-9]|1[0-2])))\/(?:1[6-9]|[2-9]\d)\d{2})|(?:29\/0?2\/(?:(?:(1[6-9]|[2-9]\d)(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))|(?:0?[1-9]|1\d|2[0-8])\/(?:(?:0?[1-9])|(?:1[0-2]))\/(?:(?:1[6-9]|[2-9]\d)\d{2}))$
will match
1/1/2001
31/5/2010
29/02/2000
29/2/2400
23/5/1671
01/1/9000
and fail
31/2/2000
31/6/1800
12/12/90
29/2/2100
33/3/3333
All in all, regular expressions may be able to match dates; validating them is not their forte, but if they are all you can use, it's certainly possible. But looks horrifying :)
Regex is not the right tool for this job.
It is very difficult (but possible) to come up with the regex to match a valid date. Things like ensuring Feb has 29 days on leap year and stuff is not easily doable in regex.
Instead check if your language library provides any function for validating dates.
PHP has one such function called checkdate :
bool checkdate ( int $month , int $day , int $year)
\b(0?[1-9]|[12][0-9]|3[01])[/](0?[1-9]|1[012])[/](19|20)?[0-9]{2}\b
Match :
1/1/2010
01/01/2010
But also invalid dates such as February 31st
^\d{1,2}/\d{1,2}/\d{4}$
In braces there is min and max char count. \d means digit, ^ start, and $ end of string.
\b(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\d\d
This wont validate the date, but you can check for format
I ran into the similar requirements.
Here is the complete regular expression along with Leap Year validation.
Format: dd/MM/yyyy
(3[01]|[12]\d|0[1-9])/(0[13578]|10|12)/((?!0000)\d{4})|(30|[12]\d|0[1-9])/(0[469]|11)/((?!0000)\d{4})|(2[0-8]|[01]\d|0[1-9])/(02)/((?!0000)\d{4})|
29/(02)/(1600|2000|2400|2800|00)|29/(02)/(\d\d)(0[48]|[2468][048]|[13579][26])
It can be easily modified to US format or other EU formats.
edited:
(3[01]|[12]\d|0[1-9])/(0[13578]|10|12)/((?!0000)\d{4})|(30|[12]\d|0[1-9])/(0[469]|11)/((?!0000)\d{4})|(2[0-8]|[01]\d|0[1-9])/(02)/((?!0000)\d{4})|29/(02)/(1600|2000|2400|2800|00)|29/(02)/(\d\d)(0[48]|[2468][048]|[13579][26])
There are two things you want to do, which in my view are best considered separately
1) You want to make sure that the date is a real, actual date.
For example the 2019-02-29 isn't a real date whereas 2020-02-29 is a real date because 2020 is a leap year
2) You want to check that the date is in the correct format (so dd/mm/yyyy)
The second point can be done easily enough with a simple RegEx, plenty of examples of that.
To complicate matters, if you ask Firefox if 2019-02-29 is a real date, it'll return NaN, which is what you'd expect.
Chrome, on the other hand will say it is a real date and give you back the 1st of March 2019 - which will validate
Chrome, will also accept a single digit number as a proper date too for some strange reason, feed it "2" and it'll give you full date from 2001 back - which will validate
So first step is to create a function which attempts to decipher a date (no matter the format) and works cross-browser to return a boolean indicating if the date is valid or not
function validatableDate(value)
{
Date.prototype.isValid = function()
{ // An invalid date object returns NaN for getTime() and NaN is the only
// object not strictly equal to itself.
return this.getTime() === this.getTime();
};
minTwoDigits = function(n)
{ //pads any digit less than 10 with a leading 0
return (parseInt(n) < 10 ? '0' : '') + parseInt(n);
}
var valid_date = false;
var iso_array = null;
// check if there are date dividers (gets around chrome allowing single digit numbers)
if ((value.indexOf('/') != -1) || (value.indexOf('-') != -1)) { //if we're dealing with - dividers we'll do some pre-processing and swap them out for /
if (value.indexOf('-') != -1) {
dash_parts = value.split('-');
value = dash_parts.join("/");
//if we have a leading year, we'll put it at the end and work things out from there
if (dash_parts[0].length > 2) {
value = dash_parts[1] + '/' + dash_parts[2] + '/' + dash_parts[0];
}
}
parts = value.split('/');
if (parts[0] > 12) { //convert to ISO from UK dd/mm/yyyy format
iso_array = [parts[2], minTwoDigits(parts[1]), minTwoDigits(parts[0])]
} else if (parts[1] > 12) { //convert to ISO from American mm/dd/yyyy format
iso_array = [parts[2], minTwoDigits(parts[0]), minTwoDigits(parts[1])]
} else //if a date is valid in either UK or US (e.g. 12/12/2017 , 10/10/2017) then we don't particularly care what format it is in - it's valid regardless
{
iso_array = [parts[2], minTwoDigits(parts[0]), minTwoDigits(parts[1])]
}
if (Array.isArray(iso_array)) {
value = iso_array.join("-");
var d = new Date(value + 'T00:00:01Z');
if (d.isValid()) //test if it is a valid date (there are issues with this in Chrome with Feb)
{
valid_date = true;
}
//if the month is Feb we need to do another step to cope with Chrome peculiarities
if (parseInt(iso_array[1]) == 2) {
month_info = new Date(iso_array[0], iso_array[1], 0);
//if the day inputed is larger than the last day of the February in that year
if (iso_array[2] > month_info.getDate()) {
valid_date = false;
}
}
}
}
return valid_date;
}
That can be compressed down to
function validatableDate(t) {
Date.prototype.isValid = function () {
return this.getTime() === this.getTime()
}, minTwoDigits = function (t) {
return (parseInt(t) < 10 ? "0" : "") + parseInt(t)
};
var a = !1,
i = null;
return -1 == t.indexOf("/") && -1 == t.indexOf("-") || (-1 != t.indexOf("-") && (dash_parts = t.split("-"), t = dash_parts.join("/"), dash_parts[0].length > 2 && (t = dash_parts[1] + "/" + dash_parts[2] + "/" + dash_parts[0])), parts = t.split("/"), i = parts[0] > 12 ? [parts[2], minTwoDigits(parts[1]), minTwoDigits(parts[0])] : (parts[1], [parts[2], minTwoDigits(parts[0]), minTwoDigits(parts[1])]), Array.isArray(i) && (t = i.join("-"), new Date(t + "T00:00:01Z").isValid() && (a = !0), 2 == parseInt(i[1]) && (month_info = new Date(i[0], i[1], 0), i[2] > month_info.getDate() && (a = !1)))), a
}
That gets you a cross-browser test as to whether the date can be validated or not and it'll read & decipher dates in formats
yyyy-mm-dd
dd-mm-yyyy
mm-dd-yyyy
dd/mm/yyyy
mm/dd/yyyy
Once you've validated the date is a real, proper one you can then test the format with a regex. So for UK dd/mm/yy
function dateUK(value) {
valid_uk_date=false;
valid_date=validatableDate(value);
if(valid_date && value.match(/^(0?[1-9]|[12][0-9]|3[01])[\/](0?[1-9]|1[012])[\/]\d{4}$/))
{ valid_uk_date=true;
}
return valid_uk_date;
}
You then know that the date is a real one and that it's in the correct format.
For yyyy-mm-dd format, you'd do:
function dateISO(value) {
valid_iso_date=false;
valid_date=validatableDate(value);
if(valid_date && value.match(/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/))
{ valid_iso_date=true;
}
return valid_iso_date;
}
It depends how thorough you want to be of course, for a rough check of format sanity a RegEx may be enough for your purposes. If however you want to test if the date is a real one AND if the format is valid then this will hopefully help point you along the way
Thanks