I have a char * which contains year and month lets say YYYYMM. How can I compare MM within the range of 01 to 12 ? Do I have to do atoi for the substring and do it or anything else exists?
If the first character of the month portion of the string is '0' the second must be between '1' and '9' inclusive to be valid. If the first character is '1' the second must be between '0' and '2' inclusive to be valid. Any other initial character is invalid.
In code
bool valid_month (const char * yyyymm) {
return ((yyymm[4] == '0') && (yyymm[5] >= '1') && (yyymm[5] <= '9')) ||
((yyymm[4] == '1') && (yyymm[5] >= '0') && (yyymm[5] <= '2'));
}
You can do atoi() of the substring or you can simply compare the ASCII values. For example:
if (buf[4] == '0')
{
// check buf[5] for values between '1' and '9'
}
else if (buf[4] == '1')
{
// check buf[5] for values between '0' and '2'
}
else
{
// error
}
Either way is acceptable. I guess it really depends on how you will eventually store the information (as int or string).
Assuming your char* variable is called "pstr" and is null terminated after the MM you can do:
int iMon = atoi(pstr + 4);
if ( (iMon >= 1) && (iMon <= 12) )
{
// Month is valid
}
Related
How do I remove the first full number of a string as an integer in C++
for instance a string "thdfwrhwh456dfhdfh764"
Would need to only pull out the first number 456 as an integer.
Thanks
Start by finding the first digit:
std::size_t pos = str.find_first_of(“0123456789”);
then check whether a digit was found:
if (pos != std::string::npos)
and then extract the tail of the string:
std::string tail = str.substr(pos);
and then extract the value:
int value = std::stoi(tail);
Here is a good example of how you might go about reading only the first number of a string that appears:
const char string_c[] = "this is a number 67theaksjdhflkajsh 78";
std::string string_n;
bool exitable = false;
for (int i = 0; i < sizeof(string_c); i++)
{
char value = string_c[i];
if (value == '0' ||
value == '1' ||
value == '2' ||
value == '3' ||
value == '4' ||
value == '5' ||
value == '6' ||
value == '7' ||
value == '8' ||
value == '9')
{
string_n += string_c[i];
exitable = true;
} else if (exitable == true)
{
printf("break\n");
break;
}
}
printf("this is the number: %s ", string_n.c_str());
If you need the number as int then you can use the std::stoi() function.
Currently, I'm having some trouble implementing a parse integer program I've made. I get two yellow lines appearing under the function when it is called in the program
using namespace std;
char parseInt(char userInput[40], char& integers);
int main()
{
char userInput[40];
char integers[40];
cout << "After you enter string input, the program will parse all the integers "
<< "inside the string and display them. \n Enter a string: \n";
cin.ignore();
cin.getline(userInput, 40);
parseInt(userInput, integers); //Here lies the problem
cout << "The integers inside the string you entered were: \n" << integers;
return 0;
}
char parseInt(char userInput[40], char& integers)
{
int j = 0;
for(int i = 0; i<sizeof(userInput); i++)
{
if( userInput[i] == 1 || userInput[i] == 2 || userInput[i] == 3 ||
userInput[i] == 4 || userInput[i] == 5 || userInput[i] == 6 ||
userInput[i] == 7 || userInput[i] == 8 || userInput[i] == 9 ||
userInput[i] == 0 )
{
integers = userInput[i];
j++;
}
}
}
When the parse Int function is called, the two error messages I'm getting are :
-cannot bind rvalue (char) (char*) (&integers) to '(char&)'
-invalid conversion from 'char*' to char [-fpermissive]
I'm just having a hard time understanding exactly what the error codes are trying to say, I'm trying to understand them more.
Many bugs here.
sizeof(userInput) doesn't work like you expect (user4581301 mentioned this in a comment). userInput is a parameter, and due to parameter type adjustment.
The type of a function is determined using the following rules. The type of each parameter (including function parameter packs) is determined from its own decl-specifier-seq and declarator. After determining the type of each parameter, any parameter of type "array of T" or of function type T is adjusted to be "pointer to T". After producing the list of parameter types, any top-level cv-qualifiers modifying a parameter type are deleted when forming the function type.
As a result, your loop only goes up to sizeof (char*).
You are reading in a string but checking the numeric value of each character. Don't expect that '1' == 1, it's not true on any character encoding in common use. (EloyBG mentioned this one)
You declared integers as a reference to just one integer, but tried to pass a whole array. (Ilan mentioned this)
You're trying to stuff many values into a reference to just one integer. (EloyBG mentioned this too, but his fix is misleading for the same reason as #1)
Reaching the end of a non-void function is illegal, you have to return a value or leave abnormally (user4581301 mentioned this too)
The C way to fix it would be to pass the length of the array as a separate parameter. In C++, you can use a reference to array to either enforce a fixed length or even infer the actual length:
void parseInt(char (&userInput)[40], char (&integers)[40])
Parameter adjustment only changes arrays, not references to arrays, and therefore your sizeof attempt will again work.
In parseInt, integers is declared like single character but you are passing an array. Furthermore, you compare userInput as integer instead of as ASCII.
void parseInt(char userInput[40], char integers[40])
{
int j = 0;
for(int i = 0; i<sizeof(userInput); i++)
{
if( userInput[i] == '1' || userInput[i] == '2' || userInput[i] == '3' ||
userInput[i] == '4' || userInput[i] == '5' || userInput[i] == '6' ||
userInput[i] == '7' || userInput[i] == '8' || userInput[i] == '9' ||
userInput[i] == '0' )
{
integers[j] = userInput[i];
j++;
}
}
}
If you use your code,
It return a single character by reference, but not return a chain of characters.
char parseInt(char userInput[40], char& integers)
{
int j = 0;
for(int i = 0; i<sizeof(userInput); i++)
{
Here, you are comparing the userInput with the first elements of the ASCII table.
if( userInput[i] == 1 || userInput[i] == 2 || userInput[i] == 3 ||
userInput[i] == 4 || userInput[i] == 5 || userInput[i] == 6 ||
userInput[i] == 7 || userInput[i] == 8 || userInput[i] == 9 ||
userInput[i] == 0 )
{
In the next line, you change the value of the single character but you do not adding a new character, because it is not a array (I supuse you got the idea because you declare j)
integers = userInput[i];
j++;
}
}
}
In the main,
cin.ignore()
is unnecesary,it makes that you lose the first character of the chain.
Declare integers like an array of characters
Compare userInput as ASCII not as integer (you can compare it as integer but you have to use the integer that corresponds with the character on the ASCII table)
Delete the cin.ignore() line
You are passing in char integers[40] into a function that it's second parameter requires a char to be passed by reference.
change char& to char[40]
char parseInt(char userInput[40], char integers[40])
I'm working on a Caesar Cipher program for an assignment and I have the general understanding planned out, but my function for determining the decipher key is unnecessarily long and messy.
while(inFile().peek != EOF){
inFile.get(character);
if (character = 'a'|| 'A')
{ aCount++; }
else if (character = 'b' || 'B')
{ bCount++; }
so on and so on.
What way, if it's possible, can I turn this into an array?
You can use the following code:
int count [26] = {0};
while(inFile().peek != EOF){
inFile.get(character);
if (int (character) >=65 || int (character) <=90)
{ count [(int (character)) - 65] ++; }
else if (int (character) >=97 || int (character) <=122)
{ count [(int (character)) - 97] ++; }
}
P.S. This is checking for the ASCII value of each character and then increment its respective element in the array of all characters, having 0 index for A/a and 1 for B/b and so on.
Hope this helps...
P.S. - There was an error in your code, = is an assignment operator and == is a conditional operator and you do not assign value in if statement, you check for condition... So always use == to check for equality...
You can use an array in the following manner
int letterCount['z'] = {0}; //z is the highest letter in the uppercase/lowercase alphabet
while(inFile().peek != EOF){
inFile.get(character);
if (character > 'A' && character < 'z')
letterCount[character]++;
}
You can also use a hashmap like this
#include <unordered_map>
std::unordered_map<char,int> charMap;
while(inFile().peek != EOF){
inFile.get(character);
if (charMap.find(character) == charMap.end())
charMap[character] = 1;
else
charMap[character] = charMap[character] + 1;
}
In case you do not know, a hashmap functions as an array, where the index can be any class you like, as long as it implements a hash function.
I'm fairly new to programming and I'm trying to get a function working that converts a string to an int. My idea with this function was to collect every number in the string and store it in another string, then convert it to an int.
The function returns the value 0.
What this function is supposed to do is return the converted number. Which should not be 0.
int getNumberFromString(int convertedNumber, string textToConvert)
{
for (int i = 0; i < textToConvert.size(); i++)
{
string collectNumbers;
int j = 0;
if (textToConvert[i] == '1' || textToConvert[i] == '2' || textToConvert[i] == '3' ||
textToConvert[i] == '4' || textToConvert[i] == '5' || textToConvert[i] == '6' ||
textToConvert[i] == '7' || textToConvert[i] == '8' || textToConvert[i] == '9' || textToConvert[i] == '0')
{
collectNumbers[j] = textToConvert[i];
j++;
}
if (collectNumbers.size() == 0)
{
return false;
}
else if (collectNumbers.size() > 0)
{
stringstream convert(collectNumbers);
if (!(convert >> convertedNumber))
{
convertedNumber = 0;
}
return convertedNumber;
}
}
}
Maybe you should just use library function ?
int stoi (const string& str, size_t* idx = 0, int base = 10);
You want somehting more like:
int getNumberFromString(int convertedNumber, string textToConvert) {
int retval = 0;
for (auto c: textToConvert) {
retval *= 10;
retval += c - '0';
}
return retval;
}
if you need to code it, or simply use stoi()
Your MAIN problem is that you are trying to convert the number before you have collected all the digits. You should loop over all the digits (use isdigit or if (x >= '0' && x <= '9') to avoid long list of individual digits - or, if you really like to list all digits, use switch to make it more readable).
Once you have collected all the digits, then convert AFTER the loop.
The statement return false, will be the same as return 0; since false will get converted to an integer with the value zero. So you won't be able to tell the difference between reading the value zero from a string and returning false (this is not PHP or JavaScript where type information is included in return values).
I'm trying to create a program that removes vowels from a string, add them into a vector and then give the user the possibility of having the original code again.
In my code i have this:
char s[20];
And soon after i have this comparison:
for(j=0;j<tam;j++)
{
if(strcmpi(s[j],"a")==1 ||
(strcmpi(s[j],"e")==1 ||
(strcmpi(s[j],"i") ==1||
(strcmpi(s[j],"o") ==1||
(strcmpi(s[j],"u")==1))
{
So if the array is char and the vowels are char(""), why the compiler give me this error?:
[Warning] passing arg 1 of `strcmpi' makes pointer from integer without a cast
EDIT
As someone said the correct is s[j] == 'a', but that result in wrong way. If a put car the result is still car. Don't know why.
if(s[j] == 'a' ||
s[j] == 'A' ||
s[j] == 'e' ||
s[j] == 'E' ||
s[j] == 'i' ||
s[j] == 'I' ||
s[j] == 'o' ||
s[j] == 'O' ||
s[j] == 'u' ||
s[j] == 'U')
{
s[j] = s[j++]; }
Strcmpi is for comparing strings. The first argument to strcmpi is of type char, when it expects a char*.
In order to compare single chars, s[j]=='e' is enough, or tolower(s[j])=='e' if you need it to be case insensitive. You'll need to include ctype.h. for tolower.
The arguments to strcmpi must be strings, but s[j] is just a single character, not a string. You can use == to compare characters directly. To get case-insensitive comparisons, get the lowercase version of the character first and compare it.
for (j = 0; j < tam; j++) {
char lower = tolower(s[j]);
if (lower == 'a' || lower == 'e' || lower == 'i' || lower == 'o' || lower == 'u') {
...
}
}
You don't want to use strcmp or any of its variants.
Because you want to know whether the string contains vowels or not, you may want to use a substring search using strstr.
You use function strcmpi incorrectly. It first parameter has type const char * while you pass an argument of type char. That is the function expects a string while you pass only one character.
Moreover this function is not a standard C/C++ function. So it should not be used.
You could achieve the same result using the following approach
char vowels[] = "aeiou";
//...
if ( strchr( vowels, tolower( s[j] ) )
{
std::cout << s[j] << " is a vowel" << std::endl;
}
You have already been told that strcmpi is not the right way to check single characters. This is an answer to the edit to your question, where you ask about actually stripping the vowels.
If you want to retain the original string, you need extra memory for the string without consonants. You also need two indices, because once you have skipped a vowel in the original string, the indices are out of sync. Here's an example implementation:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
char orig[] = "Jackdaws love my big sphinx of quartz.";
char cons[sizeof(orig)]; // Make new char buffer as big
// as the original
int i, j;
j = 0;
for (i = 0; orig[i]; i++) {
if (strchr("AEIOUaeiou", orig[i]) == NULL) {
cons[j++] = orig[i];
}
}
cons[j] = '\0'; // Terminate consonant string
printf("was: '%s'\n", orig);
printf("is: '%s'\n", cons);
return 0;
}
The expression strchr checks whether a character is in a string. You can use it as a shortcut to spelling out all vowels in explicit comparisons.