I am writing a program to convert all lowercase letters in a string to uppercase letters, vice versa.
However, I found that my program cannot return the whole converted string.
Here are outcomes and my program code.
Input: "a Survey", Output: "A".
Input: "Hello", Output: "hELLO".
#include <iostream>
#include <cstring>
using namespace std;
int main() {
char inWord[50], outWord[50];
int j = 0;
cin.getline(inWord, 50);
for (j = 0; j < strlen(inWord); j++)
{
//upper to lower
if (inWord[j]>='A'&&inWord[j]<='Z')
outWord[j] = inWord[j] + 'a' - 'A';
//lower to upper
else
outWord[j] = inWord[j] + 'A' - 'a';
}
cout << outWord;
return 0;
}
You need to take into account characters that are not letters. Now you are converting the space to 0, which is the way cout knows he needs to stop reading from the string. This is a simple solution:
#include <iostream>
#include <cstring>
using namespace std;
int main() {
char inWord[50], outWord[50];
cin.getline(inWord, 50);
for (int j = 0; j < strlen(inWord); j++)
{
char c = inWord[j];
//upper to lower
if (c>='A' && c<='Z')
outWord[j] = c + 'a' - 'A';
//lower to upper
else if (c>='a' && c<='z')
outWord[j] = c + 'A' - 'a';
else
outWord[j] = c;
}
cout << outWord;
return 0;
}
And if you are programming in C++, you should probably replace those char[50] with std::string, and avoid that using namespace std:
#include <iostream>
#include <string>
int main() {
std::string inWord, outWord;
std::getline(std::cin, inWord);
outWord.reserve(inWord.size());
for (int i = 0; i < inWord.size(); i++)
{
char c = inWord[i];
//upper to lower
if (c>='A' && c<='Z') {
outWord.push_back(c + 'a' - 'A');
}
//lower to upper
else if (c>='a' && c<='z') {
outWord.push_back(c + 'A' - 'a');
}
else {
outWord.push_back(c);
}
}
std::cout << outWord;
return 0;
}
In ascii,
' ' is not in 'A'-'Z' range, so second branch is taken.
By hazard, its value is 'a' - 'A'. resulting in '\0' (nul terminator of C-string).
To fix that issue, you have to handle a third case:
const std::size_t size = strlen(inWord)
for (std::size_t j = 0; j < size; j++)
{
//upper to lower
if (inWord[j]>='A'&&inWord[j]<='Z')
outWord[j] = inWord[j] + 'a' - 'A';
//lower to upper
else if (inWord[j]>='a'&&inWord[j]<='z')
outWord[j] = inWord[j] + 'A' - 'a';
else
outWord[j] = inWord[j];
}
'a'-'z', 'A'-'Z' are not guaranteed to be contiguous ranges (it is for Ascii, not for EBCDIC), so you might use standard methods instead (even if their interfaces is error prone :( ):
const std::size_t size = strlen(inWord)
for (std::size_t j = 0; j < size; j++)
{
unsigned char c = static_cast<unsigned char>(inWord[j]);
if (std::isupper(c))
outWord[j] = static_cast<char>(std::tolower(c));
//lower to upper
else if (std::islower(c))
outWord[j] = static_cast<char>(std::toupper(c));
else
outWord[j] = inWord[j];
}
If you want to convert all letters to for instance to the opposite case you would need to check which case the string is after input. (for instance by counting the upper case characters).
Right now you are inverting the case of each letter, as you do an if else comparison of each letter in the loop. If you execute only one of the 2 branching conditions it will do an conversion to the same case.
A few words on how you might want to improve your style:
You can define j inside the for loop if you are not using the int outside of the loop
for (int j = 0; j < strlen(inWord); j++){}
'a' - 'A' and 'A' - 'a' do have the same absolute value and do not change during the loop, so you could define a variable before the loop and then add or subtract inside of the loop respectively.
It is also useful to know that C++ treats characters as 8bit numbers in the case of ascii, this is the reason why the offset calculation works:
Link to an ASCII table
Related
As you can see from the title I want to change lowercase charachter in word to uppercase and vice versa.
Also I need to use struct object (in my case name).
I have a problem when I change charachter from lowercase to uppercase it only changes in the first word not in the second,third and so on. I am also reading words from file
Here is the input file
Aayak Audi
Ahmed Golf7
Samed Golf5
Here is the code
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <cctype>
using namespace std;
struct pismaStr
{
string ime;
string objekat;
};
void malaVelikaSlova (string name)
{
for (int i = 0; i < name.length()-1; i++)
{
if (name.at(i) >= 'A' && name.at(i) <= 'Z')
name.at(i) += 32;
else if (name.at(i) >= 'a' && name.at(i) <= 'z')
name.at(i) -= 32;
cout << name;
break;
}
}
int main()
{
ifstream pismo;
pismo.open("pismo.txt");
ofstream novoPismo;
novoPismo.open("novaSlova.txt");
pismaStr stvari[200];
int brojStvari = 0;
while(pismo >> stvari[brojStvari].ime >> stvari[brojStvari].objekat)
{
brojStvari++;
}
for (int i = 0; i < brojStvari; i++)
{
vector <pismaStr> vec = {pismaStr{stvari[i].ime}};
for (auto obj : vec)
{
malaVelikaSlova (obj.ime);
}
}
Here is the output:
aayak
ahmed
samed
It was:
Aayak
ahmed
samed
I want it to look like this
aAYAK
sAMED
aHMED
How can I fix this?
Any tips?
Tangential,
but it will be an issue, is this line
for (int i = 0; i < name.length()-1; i++)
This will loop from name[0] to name[name.length() - 2]. The std::string::length returns the number of usable characters. It does not include the null terminator, so you don't need to subtract 1. It should be
for (int i = 0; i < name.length(); i++)
Your bigger problem
is the break statement at the end of your loop (indentation added for clarity)
for (int i = 0; i < name.length()-1; i++)
{
if (name.at(i) >= 'A' && name.at(i) <= 'Z')
name.at(i) += 32;
else if (name.at(i) >= 'a' && name.at(i) <= 'z')
name.at(i) -= 32;
cout << name;
break; // <--- this exits the loop entirely
}
Your break; tells the program to exit the loop immediately. No further iterations of the loop are performed. Your cout statement is also within the loop. Once you do get the loop running for each iteration, you'll output each step of the transformation. To only output it once (at the end) you put it outside of the loop. If you want to loop over every character (and you do), your final code looks like
void malaVelikaSlova (string name)
{
for (int i = 0; i < name.length() - 1; i++)
{
if (name.at(i) >= 'A' && name.at(i) <= 'Z')
name.at(i) += 32;
else if (name.at(i) >= 'a' && name.at(i) <= 'z')
name.at(i) -= 32;
}
cout << name;
}
Other things you can change
You don't need to do bounds checking on your string indexes, since you're looping based on the string length, and it's not changing, so you don't need to extra overhead of std::string::at. You can just use the index operator:
// name.at(i); // <-- no need to do this anywhere
name[i] // <-- slightly faster
Since you're applying some operation to each element (character) in your container (string), this is a great candidate for std::transform, from the <algorithm> library. I'm also using a lambda expression here, which is a great too from C++ to get familiar with.
https://en.cppreference.com/w/cpp/algorithm/transform
https://en.cppreference.com/w/cpp/language/lambda
void malaVelikaSlova (string name)
{
std::transform(
name.begin(),
name.end(),
[](char c) -> char
{
if (c >= 'A' && c <= 'Z')
return c + 32;
if (c >= 'a' && c <= 'z')
return c - 32;
return c; // <-- for all other characters
}
);
std::cout << name << "\n";
}
You could even take advantage of the std::isupper, std::islower, std::toupper, and std::tolower functions to make your code more explicit. Note that std::string is an alias for std::basic_string<char> (its value type is char), the upper and lower functions operate on unsigned chars, so you'll need to convert the chars to unsigned chars:
https://en.cppreference.com/w/cpp/string/basic_string
https://en.cppreference.com/w/cpp/string/byte/tolower
https://en.cppreference.com/w/cpp/string/byte/toupper
https://en.cppreference.com/w/cpp/string/byte/isupper
https://en.cppreference.com/w/cpp/string/byte/islower
void malaVelikaSlova (string name)
{
std::transform(
name.begin(),
name.end(),
[](unsigned char c) -> unsigned char // <-- must convert to unsigned to be safe with upper/lower functions
{
if std::isupper(c) return std::tolower(c);
if std::islower(c) return std::toupper(c);
return c; // <-- for all other characters
}
);
std::cout << name << "\n";
}
I am currently working on a project that converts Roman Numerals to Arabic Numbers and vice versa.
I am also responsible to implement concepts like vinculum, where if you put a bar on top of a Roman numeral, the numbers below will be multiplied by 1,000.
The problem I am having is I can get only one side working, meaning:
I can either just convert from Roman Numeral to Arabic without Vinculum:
ex. I = 1, II = 2
However, when this works my vinculum code does not work.
Here is a snippet of my code:
int romanToDecimal(char input[], size_t end) {
int roman = 0;
int vroman = 0;
for (int i = 0; i < strlen(input); ++i)
{
int s1 = value(input[i]);
int s2 = value(input[i]);
if (input[i] == '-')
{
for (int j = i - 1; j >= 0; --j)
{
roman = (roman + value(input[j]));
}
roman *= 1000;
for (int k = i + 1; k <= strlen(input); k++)
roman += value(input[k]);
}
else
roman += s1;
}
return roman;
}
We use '-' instead of the bar on top of the characters, because we cannot do that in computer easily. So IV-, would be 4000 and XI- would be 11,000 etc...
I understand that the way I am doing the loop is causing some numbers that were converted to add twice, because if(input[i] == '-') cycles through each character in the string one at a time.
OK, so my question is basically what is the logic to get it to work? So if the string contains '-' it will multiply the number by 1000, if the string does not contain '-' at ALL, then it will just convert as normal. Right now I believe what is happening is that when "if (input[i] == '-')" is false, that part of the code still runs, how do I not get it to run at all when the string contains '-'??
The posted code seems incomplete or at least has some unused (like end, which if it represents the length of string could be used in place of the following repeated strlen(input)) or meaningless (like s2) variables.
I can't understand the logic behind your "Vinculum" implementation, but the simple
roman += s1; // Where s1 = value(input[i]);
It's clearly not enough to parse a roman number, where the relative position of each symbol is important. Consider e.g. "IV", which is 4 (= 5 - 1), vs. "VI", which is 6 (= 5 + 1).
To parse the "subtractive" notation, you could store a partial result and compare the current digit to the previous one. Something like the following:
#include <stdio.h>
#include <string.h>
int value_of(char ch);
long decimal_from_roman(char const *str, size_t length)
{
long number = 0, partial = 0;
int value = 0, last_value = 0;
for (size_t i = 0; i < length; ++i)
{
if (str[i] == '-')
{
number += partial;
number *= 1000;
partial = 0;
continue;
}
last_value = value;
value = value_of(str[i]);
if (value == 0)
{
fprintf(stderr, "Wrong format.\n");
return 0;
}
if (value > last_value)
{
partial = value - partial;
}
else if (value < last_value)
{
number += partial;
partial = value;
}
else
{
partial += value;
}
}
return number + partial;
}
int main(void)
{
char const *tests[] = {
"I", "L", "XXX", "VI", "IV", "XIV", "XXIII-",
"MCM", "MCMXII", "CCXLVI", "DCCLXXXIX", "MMCDXXI", // 1900, 1912, 246, 789, 2421
"CLX", "CCVII", "MIX", "MLXVI" // 160, 207, 1009, 1066
};
int n_samples = sizeof(tests) / sizeof(*tests);
for (int i = 0; i < n_samples; ++i)
{
long number = decimal_from_roman(tests[i], strlen(tests[i]));
printf("%12ld %s\n", number, tests[i]);
}
return 0;
}
int value_of(char ch)
{
switch (ch)
{
case 'I':
return 1;
case 'V':
return 5;
case 'X':
return 10;
case 'L':
return 50;
case 'C':
return 100;
case 'D':
return 500;
case 'M':
return 1000;
default:
return 0;
}
}
Note that the previous code only checks for wrong characters, but doesn't discard strings like "MMMMMMMMMMIIIIIIIIIIIIIV". Consider it just a starting point and feel free to improve it.
I was training on solving algorithms, I wrote a code but it won't compile
in (if) I can not check s[i]=='S' .
I'm trying to if s[i] is S character or not but I don't know where my problem is.
If I can't use this syntax, what could be a solution?
#include<iostream>
#include<string>
using namespace std;
int main()
{
double v_w=25,v_s=25,d_w=25,d_s=25;
int n;
cin>>n;
string s[]={"WSSS"};
int i ;
for (i=0; i<n; i++)
{
if( s[i] == "W" )
{
v_s += 50;
d_w = d_w + (v_w/2);
d_s = d_s + (v_s/2);
cout<<"1 \n";
}
if(s[i]=='W')
{
v_w +=50;
d_w = d_w + (v_w/2);
d_s = d_s + (v_s/2);
cout<<"2 \n";
}
return 0;
}
cout<< d_w<<endl<<d_s;
}
string s[]={"WSSS"}; means an array of strings which the first one is "WSSS".
What you need is:
std::string s="WSSS";
string s[] = {"Hello"} is an array of strings (well, of one string).
If you iterate over it, or index into it s[0] is "Hello".
Whereas
string s{"Hello"} is one string, which is made up of characters.
If you iterate over it, or index into it s[0], you will get 'H'.
To pre-empt all the other things that are going to go wrong when the string versus character problem is sorted, lets move the return 0; from the middle of the for loop.
Then let's think about what happens if the number n entered is larger than the length of the string:
int n;
cin>>n; //<- no reason to assume this will be s.length (0 or less) or even positive
string s{"WSSS"}; //one string is probably enough
int i ;
for(i=0;i<n;i++)
{
if( s[i] == 'W' ) //ARGGGGGGG may have gone beyond the end of s
{
In fact, let's just drop that for now and come back to it later. And let's use a range based for loop...
#include<iostream>
#include<string>
using namespace std;
int main()
{
double v_w = 25, v_s = 25, d_w = 25, d_s = 25;
string s{ "WSSS" };
for (auto && c : s)
{
if (c == 'W')
{
v_w += 50;
d_w = d_w + (v_w / 2);
d_s = d_s + (v_s / 2);
cout << "2 \n";
}
}
cout << d_w << '\n' << d_s << '\n'; //<- removed endl just because...
return 0;
}
s is an array of strings in this case it has only element:
string s[] = {"WSSS"};
so writing s[2]; // is Undefined behavior
your code will produce a UB if the user enters n greater than the number of elements in s:
n = 4;
for(i = 0; i < n; i++) // s[3] will be used which causes UB
{
if( s[i] == 'W' ) // s[i] is a string not just a single char
{
}
}
also as long as s is an array of strings then to check its elements check them as strings not just single chars:
if( s[i] == "W" ) // not if( s[i] == 'W' )
I think you wanted a single string:
string s = {"WSSS"};
because maybe you are accustomed to add the subscript operator to character strings:
char s[] = {"WSSS"};
if so then the condition above is correct:
if( s[i] == 'W' )
i'm trying to implement Ceaser cipher in c++ language
#include <iostream>
#include <string>
#include <locale>
using namespace std;
int main()
{
string word;
getline(cin,word);
for(int i=0; i<word.length();i++)
{
if(isalnum(word[i]))
{
//shift by 3
word[i]+= 3;
}
}
cout << word ;
return 0;
}
what i want is to limit the output also for only letter and number .
for example if i want to shift z by 3 the output would be 'c' and not '}' as in my code .
Compilers are much better at handling the tedious details than humans, so in this case, I would write the code to show clearly what you intend, and then let the compiler figure out the numbers.
For example, if you want to shift a letter, don't you really just want to add 3 to the index of the letter in the range A to Z, and then mod by 26 -- the number of letters from A to Z? This is really what you want -- rotate around the circle of LETTERS from A to Z, of which there are 26, and not worry about ASCII values.
In that case, you can let the compiler figure it out for you:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int shift = 3;
char* input = "Is it 90 with a ZERO?";
printf("%s\n", input);
int length = strlen(input);
char* output = malloc(length + 1);
output[length] = '\0';
for (int i = 0; i < length; i++)
{
char c = input[i];
if (c >= 'A' && c <= 'Z')
{
c = (((c - 'A') + shift) % 26) + 'A';
}
else if (c >= 'a' && c <= 'z')
{
c = (((c - 'a') + shift) % 26) + 'a';
}
else if (c >= '0' && c <= '9')
{
c = (((c - '0') + shift) % 10) + '0';
}
output[i] = c;
}
printf("%s\n", output);
}
Why would you want to take on that responsibility, if you are not worried about speed or memory footprint?
You have to make sure it does not go out of the valid range for ASCII letters. A way of doing this is to convert the input to lowercase, then make sure that when the shift is added, it does not exceed 122 (z's value in ASCII).
if (word[i] + SHIFT > 'z') {
SHIFT -= 123 - word[i];
word[i] = 'a'; // go back to the beginning
word[i] += SHIFT; // add on the remaining amount
}
This should work.This assumes that there will be only lower case letters.
word[i]+= 3;
//at this point word[i] might have cross the ascii limit for lower case letters
ie may be word[i]>122.Ascii range for lower case letters is 97-122
So we use mod to wrap it around.
But now may be word[i]<97 which is again out of range so we add 97 to it.
word[i]%=123;
if(word[i]<97)word[i]+=97;
Example z
word[i]+=3 makes word[i] as 125 //out of range
word[i]%=123 //word[i]=3
word[i]+=97 //word[i]=99=c
I'm writing a program that solves Caesar ciphers in C++. It takes a string of the alphabet and shifts it to the left each loop: "abc....yz" --> "bcd.....yza". The problem is after another loop it goes: "bcd.....yza" --> "cde.....yzaa".
char temp; // holds the first character of string
string letters = "abcdefghijklmnopqrstuvwxyz";
while (true)
{
temp = letters[0];
for (int i = 0; i < 26; i++)
{
if (i == 25)
{
letters += temp;
}
letters[i] = letters[i + 1];
cout << letters[i];
}
cin.get();
}
Copy and paste that code and you'll see what I'm talking about. How do I fix this mysterious problem?
If I'm not mistaken, your loop does precisely the same as the following code:
letters = letters.substr(1,25) + letters.substr(0,1);
// [skip 1, take 25] + [first char goes last]
I think you need letters to be 27 characters, not 26, and instead of letters += temp (which grows the string every time), use letters[26] = temp[0].
...at which point you can just ditch temp entirely:
string letters = "abcdefghijklmnopqrstuvwxyz.";
while (true)
{
letters[26] = letters[0];
for (int i = 0; i < 26; i++)
{
letters[i] = letters[i + 1];
cout << letters[i];
}
cin.get();
}
[edit]
Although the more natural way to handle this is to use arithmetic on the characters themselves. The expression 'a' + ((c - 'a' + n) % 26) will shift a char c by n places Caesar-style.
You can achieve this easily using valarray< char >::cshift(n) (cyclical shift) method.