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.
Related
I am given a string and I have to remove a substring from it. Namely WUB, and replace it with a space character.
There are 2 WUB's between ÁRE' and 'THE'. SO the first condition in if statement is for not printing two blank spaces but on executing the code two blank spaces are being printed.
Input: WUBWEWUBAREWUBWUBTHEWUBCHAMPIONSWUBMYWUBFRIENDWUB
Output: WE ARE THE CHAMPIONS MY FRIEND
Here is my code so far:
#include <iostream>
using namespace std;
int main()
{
const string check = "WUB";
string s, p;
int ct = 0;
cin >> s;
for (int i = 0; i < s.size(); i++)
{
if (s[i] == 'W' && s[i+1] == 'U' && s[i+2] == 'B')
{
i += 2;
if (p[ct] == '32' || p.empty())
{
continue;
}
else
{
p += ' ';
ct++;
}
}
else
{
p += s[i];
ct++;
}
}
cout << p;
return 0;
}
Why is the first if statement never executed?
2 things are going to break your code:
you are doing a for loop like this int i=0;i<s.size() but reading (s[i]=='W' && s[i+1]=='U' && s[i+2]=='B')
and here: if(p[ct]=='32') you mean for sure if(p[ct]==32) or if(p[ct]==' ')
This condition
if(p[ct]=='32')
should read either
if(p[ct]==32)
or
if(p[ct]==' ')
that is, compare to the numeric value of the space character or to the space character itself.
Additionally, when your i grows close to the string's length, the subexpressions s[i+1] and s[i+2] may reach non-exiting characters of the string. You should continue looping with a i<s.length()-2 condition.
EDIT
For a full solution you need to fully understand the problem you want to solve. The problem statement is a bit vague:
remove a substring ("WUB") from (a given string). And put a space inplace of it if required.
You considered the last condition, but not deeply enough. What does it mean, 'if required'? Replacement is not required if the resulting string is empty or you appended a space to it already (when you encounter a second of further consecutive WUB). It is also not necessary if you are at WUB, but there is nothing more following it - except possibly another WUBs...
So, when you find a "WUB" substring it is too early to decide if a space is needed. You know you need a space when you find a non-WUB text following some WUB (or WUBs) and there was some text before those WUB(s).
There are actually three bugs here, so it's probably worth to conclude them in one answer:
The first condition:
if (s[i] == 'W' && s[i+1] == 'U' && s[i+2] == 'B')
is out of bounds for the last two characters. One fix would be to check the length first:
if(i < s.length() - 2 && s[i] == 'W' && s[i+1] == 'U' && s[i+2] == 'B')
There's a multicharacter-literal in
if (p[ct] == '32' || p.empty())
Use ' ' or 32 or std::isspace instead. IMO the last one is the best.
In the same condition
p[ct] == '32'
is always out of bounds: ct is equal to p.length(). (Credits to Some programmer dude, who mentioned this in the comments!) The variable ct is also redundant, since std::string knows it's length. I suggest to use std::string::back() to access the last character and reorder the condition as so:
if (p.empty() || std::isspace(p.back()))
The algorithm to this program is on the right track.
However, there is a few issues..
The for loop goes out of index. A way to solve this issue is substracting the size -3. Something like this.
for (int i=0; i<s.size()-3; i++) {
}
I do not suggest using other variables as counters like ct. In this case ct can reach an index out of bound error by using p[ct] inside the for loop.
Creating a string and using append() function will be a better solution. In this case, we iterate through each character in the string and if we find "WUB" then we append a " ". Otherwise, we append the character.
I highly recommend to write the first if() statement using substring() from C++.
This makes the code easier to read.
Substring creates and returns a new string that starts from a specific position to an ending position. Here is the syntax
syntax: substr(startingIndex, endingIndex);
endingIndex is exclusive
#include <string>
#include <iostream>
int main() {
string s, p;
cin >> s;
for(int i=0;i<s.size()-3;i++) {
if (s.substr(i, i+3) == "WUB") {
p.append(" ");
} else {
p.append(s.substr(i,i+1));
i++;
continue;
}
i+=3;
}
}
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 am trying to check if each character of a string in a string array is equal to any of the five vowels. However, when I test it to see when a vowel character in a string is equal to 'vowel', I get that they are not equal. The problem with the code is the bolded part below. Also, when I try to do "a" || "e" || "i" || "o" || "u", I get the error that ISO C++ forbids comparison between pointer and integer. How can I be able to check if they are equal? Thank you for your time.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <cmath>
#include <cstdlib>
using namespace std;
int l, c; //l is amount of letters in password, c is amount of letters being inputted
char letters[1000000]; //the letters being inputted
vector <string> pass; //string vector of the stored passwords
void rec(string current, int index, int x){ //determining all possible passwords
if (index >= 4){
pass.push_back(current);
}
else{
for (int i=0; i<c; i++){
if (x<i){
int old;
old = x;
x = i;
rec(current + letters[i], index+1, x);
x = old;
}
}
}
}
int main (int argc, char ** argv)
{
cin >> l >> c;
int x = -1;
for (int i=0; i<c ;i++){
cin >> letters[i];
}
sort(letters, letters + c); //sorted from least to greatest
rec("", 0, x);
for (int i=0; i<pass.size(); i++){
int vl=0; //number of vowels
int nvl=0; //number of non-vowels (consonants)
for (int j=0; j<l; j++){
**if (pass.at(0)[j] == 'a' || 'e' || 'i' || 'o' || 'u'){**
vl++;
}
else{
nvl++;
}
if (j == l-1){
if (vl >= 1 && nvl >= 2){
cout << pass.at(0) << endl;
}
}
}
}
return 0;
}
In C++, X || Y means:
Test if X is true. If so, result of whole expression is true
Otherwise, test if Y is true. Result of Y is result of expression.
So your code:
pass.at(0)[j] == 'a' || 'e'
(omitting for now the i etc. as they don't change anything).
We tested pass.at(0)[j] == 'a' . That was false, so now we test 'e'. Not that you did NOT test pass.at(0)[j] == 'e'. You just tested 'e'. This is the same as testing 'e' != 0, which is true. So your expression evaluates to true at this point (and does not go onto check 'i' etc.)
You probably intended to test whether pass.at(0)[j] held any of the values 'a', 'e', etc. If so then one way to encode that is:
if ( std::strchr("aeiou", pass.at(0)[j]) )
You should make sure j < strlen(pass.at(0)) before doing this though; using [] to generate an out of bounds index causes undefined behaviour.
Because you are using the || wrong. The part either side of || is a "true or false" expressin in itself, so you need something like:
if (pass.at(0)[j] == 'a' || pass.at(0)[j] == 'e' ... )
Otherwise, the expression is always true, since || is true if the expression on left or right is true, and 'e' is true by not being zero.
This does not do what you think...
(pass.at(0)[j] == 'a' || 'e' || 'i' || 'o' || 'u')
You need to explicitly compare,
char t = pass.at(0)[j];
if (t == 'a' || t == 'e' || t == 'i' || t == 'o' || t == 'u') {
I need to input a string, if the string is just a whole string and not with spaces, the codes is fine, if the input is a string with spaces, the string only copys the first set of strings and not the whole strings? I'm an noob, please help.
#include <stdio.h>
#include <string.h>
int main() {
char again = 0;
do {
char str[60], s[60];
int i, j = 0;
printf("Enter any string->");
scanf("%s", str);
printf("The string is->%s", str);
for (i = 0; i <= strlen(str); i++) {
if (str[i] == 'a' || str[i] == 'e' || str[i] == 'i' ||
str[i] == 'o' || str[i] == 'u' || str[i] == 'A' ||
str[i] == 'E' || str[i] == 'I' || str[i] == 'O' ||
str[i] == 'U') {
str[i] = ' ';
} else {
s[j++] = str[i];
}
}
s[j] = '\0';
printf("\nThe string without vowel is->%s", s);
NSLog(#"Do you want to enter another string to be edit? (y/n) ");
scanf("%s", &again);
} while (again != 'n');
}
Your code stops reading at a space because that's how scanf works with the %s format. It reads a sequence of non-whitespace characters.
If you're really using C++, then you'd be wise to switch to std::string and std::getline, which will read all input up to the end of the line. Your code doesn't appear to use any C++ features, though, so maybe you're really using C. In that case, consider fgets instead. It will read the whole line, too (up to a specified size, which generally corresponds to the size of your buffer).
This code is a mess.
C++ features like std::string are not used at all.
You're mixing printf/scanf and NSLog for no reason.
Modifying str in the if branch makes no sense, as it won't be read later.
You probably want to use i < strlen(str) instead of <=, or you'll copy that terminating zero character twice.
Your scanf("%s", &again); specifies to read a string, but you only have memory for a character, thus you probably end up writing into some random memory position.
While some of these points are more severe than others, I suggest fixing those issues and see what happens. If you experience unexpected output, then please do give your example input and output as well.
You are allocating an array of 60 chars long (str). You can't expect to read a lot into it. Here are a few tips:
Don't use such buffers, they are dangerous. The C++ library provides you std::string.
Never omit the curly braces {}.
There are an easier way to check for chars than this horribly long if. Hint: std::string::find_first_of