Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am doing a Date class which takes a string as a parameter that is like :
11/13/2007
9/23/2008
9/23/2008
... and set it month, date and year objects, How can I use the substr() function, or are there any other functions ?
In your case, I would use the good old C(!) sscanf function:
unsigned int year, month, day;
char c;
if(sscanf(input, "%u/%u/%u%c", &month, &day, &year, &c) == 3)
{
// check ranges of your date variables!
}
You seem to use American date format, so I set the parameters accordingly.
Wondering why I'm reading an additional character ? It catches additional data at the end of your date string to detect invalid formats (if data follows, result will be 4, otherwise, only 3 values are read, which will be returned). One drawback: before the three numbers, white space is ignored, so if you wanted to disallow, you would need additional checks (e. g. "%n %n%u" and comparing, if the two corresponding values are equal).
See sscanf documentation (scanf for parameters).
(If your input is a ::std::string instance, you need to use sscanf(input.c_str(), ...), of course.)
If you are using C++11 you can use <regex> library:
#include <iostream>
#include <regex>
#include <string>
int main() {
std::string date = "1/1/1970";
std::regex dateRegex("(\\d\\d?)/(\\d\\d?)/(\\d{4})");
std::smatch match;
if (regex_match(date, match, dateRegex)) {
std::cout << match.str(1) << std::endl;
std::cout << match.str(2) << std::endl;
std::cout << match.str(3) << std::endl;
}
else {
// error
}
return 0;
}
This is maybe an overkill for your situation but remember that by using regular expression you are also doing some form of validation on your input. In above example, if you pass anything that doesn't have the form dd/dd/dddd where "d" is a digit you will enter the "error" block of code. Of course, 99/99/9999 will count as a valid input but you can also solve that case with more complicated regex.
Another option for parsing strings with delimiter is using getline function.
Related
This question already has an answer here:
how to get more than 1 word input from cin [closed]
(1 answer)
Closed last year.
This post was edited and submitted for review last year and failed to reopen the post:
Original close reason(s) were not resolved
Am presently reading the book C Primer 5th edition, and this question is asked in the book, question problem being 3.10.
So, basically we have to remove the punctuations if they exist in the string that we would provide it with.
I've attempted the question and even I get the successful output when I initialize the string beforehand. Here is my code with strings being initialized before the code execution:
Code:
#include <bits/stdc++.h>
#include <string>
using namespace std;
int main()
{
string s("he##,llo world...!!#");
for(auto &c:s)
{
if(ispunct(c))
{
cout<<"";
}
else
cout<<c;
}
return 0;
}
This particular code provides with the correct output, i.e. hello world.
Now, if I try to use the same code format but with the condition that the user would have to provide the string as an input then the code doesn't gives the correct output, it just ignores the rest part of the string after the whitespace.
The code that I tried is:
#include <bits/stdc++.h>
#include <string>
using namespace std;
int main()
{
string s;
cin>>s;
for(auto &c:s)
{
if(ispunct(c))
{
cout<<"";
}
else
cout<<c;
}
return 0;
}
During the execution of the code when I put the string input as he##,llo world...!!#
The code provides me with the output: hello. The next part of the string after the whitespace gets ignored.
Well, my question is,
Why does this code doesn't works when the string is taken as the form
of input by the user? And what can I do to make the code work without
any errors?
Edit about suggestion:
The current suggestion provided by one of the community members doesn't answers my question, as it is not about taking the input from a user and formatting the input in a file, whereas the question asked here is about the removal of the punctuation and characters and printing the rest part of the string when an input is provided by the user.
Standard cin >> only gets the first "word" in a line; words are typically separated by a space, which is why everything after the space after he##,llo is ignored. What you need to use instead is getline(cin, s) to capture the entire line.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
So I was making guessing game to learn something (I'm a beginner) and at the start I faced the problem that I didn't know how to do rng or something like that so I came up with idea where I just ask user to give his name and something he hates and I need to make this input somehow change to number (any kind except binary).
So in short I need a way to change any inputted text (string) to any integer number.
Here is an example of how to use a hash function, that already exists for the standard library.
#include <cstdio>
#include <string>
#include <iostream>
#include <functional>
int main() {
std::cout << "Starting Process!" << std::endl;
std::cout << "Enter Name: ";
std::string name;
std::cin >> name;
std::hash<std::string> hash_fn;
size_t str_hash = hash_fn(name);
std::cout << str_hash << '\n';
return 0;
}
I would suggest you to take a look at the "random" library if you want rng or to use hashing as other suggested.
If you want to generate yourself pseudo-random numbers from an input string, you could do the following:
To acces a character, you could use the [ ] operator, something like that:
std::string str = "The Name";
str[index]; // to acces a character
Cast the characters into integers to work with them. Keep in mind that every character has an ASCII value, so you could do something like this:
static_cast<int>(str[2]);
Now you have accesed the third character, according to the string above, 'e'. Which happens to be 101 when transformed into an int (remember, the ASCII value).
You can then create some algorithm using that.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I made a code but it doesn't work.Can you help? In code, I wanted to take a line and if code see //n, end line.
Here is my example.
File:
I love C++! //n
My Code:
ifstream file("file.txt");
char text[250];
while(file >> text){
cout << text << " ";
if(text == "//n"){
cout << endl;
}
}
Thanks for your help.
I am unsure as to what you are trying to do, however it seems that you want to get a line worth of text. If so, you would want to change
char text[255];
....
if(text == "//n")
to
std::string text;
...
if(text == "\n")
The array comparison will not compare strings. So use the std::string to allow you to use == operator.
As C++ special character codes use a backslash rather than two forward slashes.
However, I'd also suggest using a single char rather than an array (as indexing doesn't seem to be a concern since you only access the first character in it).
If you want to read a file a word at a time:
ifstream file("file.txt");
std::string line;
while(std::getline(file, line)) {
std::stringstream linestream(line);
std::string word;
while(linestream >> word) {
std::cout << "Word: " << word << " ";
}
std::cout << "EOL\n";
}
Basically your code has a couple of issues.
'//n' is not a special character we all assume you meant '\n'.
Most operators that read text from a file will disgard the '\n' character.
operator>> will disguard white space (including \n).
getline() reads the line but drops the \n.
Thus '\n' is never in text to be compared too.
Arrays char text[255] will convert themselves into pointers easily.
Thus the comparison you are doing compares two pointers. This will never be equal.
You need a type that does something smart with == so that you compare the text.
For this you should use std::string.
As a good style guide.
Never put using namespace std; in your code. It causes more trouble when you have anything but a simple bit of throwaway code. And using it in simple throwaway code is a bad habit that will catch up to you someday.
The reason std (as well as others) is short and not standard is so that prefixing it items from the standard library is not burdensome.
std::cout << text << " "; // not hard.
std::cout << std::endl;
There is no real reason to use std::endl (debugging being an exception I suppose). In normal situations the extra flush it adds will generally cause the output to slow down perceptibly. So prefer to use '\n' unless you specifically want to force a flush.
The problem here is, your code compares pointers, instead of comparing strings (as noted also in the other answer):
if(text == "//n")
{
...
}
Here text is a pointer (actually, an array of char, but in this context it's equivalent to a pointer), and "//n" also is a pointer (also an array). Comparing two pointers is not what you want.
To fix your code so it compares strings, one of the things your code compares should be a string instead of a pointer. To mark "//n" as a string, append s to it:
if(text == "//n"s)
{
...
}
This is a bit obscure; another solution is to make text a string (as described in the other answer):
std::string text;
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I can't seem to come up with a chunk of code that traps the user until it gets a positive int and prompts the user appropriately if the user accidentally types a character or random garbage like "-1-3-4-39-32xfi3/". I just need a neat failproof cin loop structure and can't figure it out. Thanks.
I'm just wondering what other people do regarding console input to make draw ideas from that..how you get around bad input.
Do this:
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
int main()
{
for (std::string line; std::getline(std::cin, line); )
{
std::istringstream iss(line);
unsigned int n;
if (!(iss >> n >> std::ws) || iss.get() != EOF)
{
std::cout << "Bad input ('" << line << "'), ignoring.\n";
continue;
}
std::cout << "Success! We read: " << n << "\n";
return EXIT_SUCCESS;
}
std::cout << "Premature end of input!\n";
return EXIT_FAILURE;
}
In other words, continue reading input from the user until you are able to parse the input as the kind of data you want. I chose line-based processing, which is often the most natural, but any notion of "record" that you can skip if it isn't right will do. Note that it's possible the program never succeeds, namely if the user refuses to provide any good input.
I typically read an entire line with std::getline, then attempt to convert it to an integer with strtol. If the result is less than 0, they typed a leading -. strtol returns a pointer to the first character of input that couldn't be converted as an integer, so if it points to anything but \0, you know the user typed in something that couldn't be converted.
I really should switch to using std::stoi instead of strtol though. It supports pretty much the same capabilities, but its input is a std::string instead of a C-style string like strtol uses. I only continue to use strtol out of long habit, not because it's really a better solution.
Depending on what you have available, and how you want to respond to bad input, another possibility to consider would be boost lexical_cast. This throws an exception if it can't convert the entire input to the target type, so if you want an exception it may be more convenient (but if you don't want exceptions, it'll probably just cause you extra work).
Got a question about printing Integers with thousands/millions separator.
I got a Textfile where i got Country, City,Total Population.
I have to read in the File, and sort by country. If country is eual, i have to sort descending by population.
Textfile is like:
Australia........Sydney.........10.123.456
Brazil...........Sao Paulo.......7.123.345
I read all 3 into a seperated string. Then i erase all "." in the population string. Then i use atoi() to cast the population string to an integer.
Now i can sort by population if country is equal. This sort works correctly.
So far so good. But i need to get thousand/millions seperator into the printing of the population.
If i use string,with the "." for population, sorting dont work correctly.
Its sorted like:
x........x......1.123456
x........x......10.123.456
x........x......2.123.232
It have to look like:
Australia........Sydney.........10.123.456
Australia........Brisbane.......8.123.456
Is there a way to manipulate the printing by adding separator the the int again?
Many Thanks in advance
imbue() the output stream with a locale that has the desired separator. For example:
#include <iostream>
#include <locale>
int main()
{
// imbue the output stream with a locale.
int i = 45749785;
std::cout << i << "\n";
std::cout.imbue(std::locale(""));
std::cout << i << "\n";
}
Output on my machine (and online demo):
45749785
45,749,785
As commented, and answered, by James Kanze imbue the input stream also to read the separated int values without manually modifying the input.
See Stroustrop's Appendix D: Locales for a detailed overview of locales.
Use a locale which supports the desired separators to read the
file (that way you can read the values as integers), and the
same locale to write the data.
Note that you may not have such a locale available, or if you
do, you may not know its name (and using a named locale might
change other things, that you don't want changed); on my
machine, imbueing with "" behaves differently according to
the compiler (or maybe the shell I'm invoking it from)—you
should never use the locale "" if you have strict formatting
requirements. (The use of locale "" is for the case when you
want the format to depend on the users environment
specifications.)
In this case, it's probably better to provide the local explicitly:
class MyNumPunct : public std::numpunct<char>
{
protected:
virtual char do_thousands_sep() const { return ','; }
virtual std::string do_grouping() const { return "\03"; }
};
int
main()
{
std::cout.imbue( std::locale( std::locale::classic(), new MyNumPunct ) );
std::cout << 123456789 << std::endl;
return 0;
}
Of course, you'll want to use this locale for the input as well.
(This code will give you the "C" locale, with only the
grouping changed.)