Converting all to uppercase - c++

Hey so I'm very new to c++ and trying to convert a word a user enters to all uppercase
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
int size=10;
int i =0;
char arr[size];
cout<<"Enter a word"<<endl;
cin.get(arr,size);
for(i = 0; i < 10; i++)
{
if(islower(arr[i]))
{
cout<<toupper(arr[i])<<endl;
}
}
return 0;
}
I'm getting numbers when I run this. What do I fix?

Don't write C-like C++, use the standard library to your advantage. Use an std::string and do something like this instead:
#include <iostream>
#include <algorithm>
#include <string>
int main() {
std::string input;
std::cin >> input;
std::transform(input.begin(), input.end(), input.begin(), ::toupper);
std::cout << input << std::endl;
return 0;
}
Or alternatively with a lambda:
std::transform(input.begin(), input.end(), input.begin(), [](unsigned char c){ return std::toupper(c); });

It is the time to learn one of bit-wise applications
#include <iostream>
#include <string>
int main()
{
int mask = 0xDF;
std::string str = "aBcdeqDsi";
for(int i(0); i < str.size(); ++i)
std::cout << static_cast<char>(str[i] & mask);
std::cout << std::endl;
return 0;
}

Related

Remove duplicates from the string in CPP

I wrote the following code for removing the duplicates from a given string i.e. if ARRUN is the input then the output will be ARUN.
#include <bits/stdc++.h>
using namespace std;
char* removeDuplicates(string &s,int n){
char arr[n];
unordered_map<char,int> exists;
int index = 0;
for(int i=0;i<n;i++){
if(exists[s[i]]==0)
{
arr[index++] = s[i];
exists[s[i]]++;
}
}
return arr;
}
//driver code
int main(){
string str;
cin >> str;
cout<<removeDuplicates(str,str.length())<<endl;
return 0;
}
The code produces no output at all, however, it works fine if I use char arr[] instead of string class.
You can't use char arr[n] without being n constant or constexpr.
You don't need map. set is sufficient.
Note that map and set remove duplicates already, then you can check if any element is inserted or not to get your new string in the same order of the first, as follows
#include<string>
#include<iostream>
#include<unordered_set>
std::string removeDuplicates(const std::string &s){
std::string arr;
std::unordered_set<char> exists;
for(const auto&el:s)
if(exists.insert(el).second) arr+=el;
return arr;
}
//driver code
int main(){
std::string str;
std::cin >> str;
std::cout<<removeDuplicates(str)<<std::endl;
return 0;
}
std::string support removing elements.
#include <iostream>
#include <string>
std::string removeDuplicates(std::string str) {
for (int i = 0; i < str.size(); i++) {
while (true) {
int j = str.find_last_of(str[i]);
if (i < j) {
str.erase(j, 1);
} else {
break;
}
}
}
return str;
}
int main() {
std::cout << removeDuplicates("ARRUN");
return 0;
}
If a function declaration looks the following way
char* removeDuplicates(string &s,int n);
then it means that the passed object itself will be changed in the function. Otherwise the parameter shall have the qualifier const.
Also it is unclear why the function has return type char *. It looks like the declaration of the function is contradictive.
The second parameter of the function shall have at least the type size_t or that is better std::string::size_type. The type int can not accomodate all values of the type std::string::size_type.
The function could be declared without the second parameter.
A straightforward approach without using intermediate containers that requires dynamic memory allocation can look the following way
#include <iostream>
#include <string>
std::string & removeDuplicate( std::string &s )
{
const char *p = s.c_str();
std::string::size_type pos = 0;
for ( std::string::size_type i = 0, n = s.size(); i < n; i++ )
{
std::string::size_type j = 0;
while ( j < pos && s[i] != s[j] ) j++;
if ( j == pos )
{
if ( i != pos ) s[pos] = s[i];
++pos;
}
}
return s.erase( pos );
}
int main()
{
std::string s( "H e l l o" );
std::cout << "\"" << s <<"\"\n";
std::cout << "\"" << removeDuplicate( s ) <<"\"\n";
return 0;
}
The program output is
"H e l l o"
"H elo"
#Arun Suryan, You pointed out correctly. But you can do it without using vector by using global char array.
Also don't forget to append the newline at the end!
Have a look at the following code:
#include<string>
#include<iostream>
#include<unordered_map>
char* removeDuplicates(std::string &s,int n){
std::unordered_map<char,int> exists;
char* arr = (char*)(malloc(n*sizeof(char)));
int index = 0;
for(int i=0;i<n;i++){
if(exists[s[i]]==0)
{
arr[index++] = s[i];
exists[s[i]]++;
}
}
arr[index] = '\n';
return arr;
}
//driver code
int main(){
std::string str;
std::cin >> str;
std::cout<<removeDuplicates(str,str.length())<<std::endl;
return 0;
}
This might be a bit advanced for newcomers to C++ but another solution makes use of the erase-remove idiom:
std::string removeDuplicates(const std::string& s) {
std::string result = s;
std::unordered_set<char> seen;
result.erase(std::remove_if(result.begin(), result.end(), [&seen](char c)
{
if (seen.find(c) != seen.end())
return true;
seen.insert(c);
return false;
}),
result.end());
return result;
}
It basically uses a set to store characters that have been seen, shuffles the characters to be removed down to the tail (using std::remove_if) and erases the tail from the string.
Working version here.
This works too, a single line solution with an inbuild function.
cout<<str.erase(std::unique(str.begin(), str.end()), str.end());
Simple Answer
#include<bits/stdc++.h>
using namespace std;
string removeduplicate(string key){
set<char>s;
string ans="";
for(int i=0;i<key.size();++i){
if(s.find(key[i])==s.end()){
s.insert(key[i]);
ans.push_back(key[i]);
}
}
return ans;
}
int main()
{
string key="";
cout<<"enter the key:";
cin>>key;
string ans1=removeduplicate(key);
cout<<ans1;
return 0;
}
So, after doing a bit of reading on the Internet I realized that I was trying to return a pointer to the local array in the removeDuplicates() function.
This is what works fine
#include <bits/stdc++.h>
using namespace std;
void removeDuplicates(string &s,int n){
vector<char> vec;
unordered_map<char,int> exists;
int index = 0;
for(int i=0;i<n;i++){
if(exists[s[i]]==0)
{
vec.push_back(s[i]);
exists[s[i]]++;
}
}
for(auto x: vec)
cout << x;
}
//driver code
int main(){
string str;
cin >> str;
removeDuplicates(str,str.length());
return 0;
}
PS: We can make the return type of function to vector as well.

converting strings to integers by using "stringstream "

I am trying to convert strings of data to integers, (to use it for some calculations ) by using stringstream , but it fails when there is a space.
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
int main() {
string line;
vector <string>data;
for (int i = 0; i < 10;i++) {
getline(cin,line);
data.push_back(line);
}
///converting digits to int
vector<int> values;
int n;
char ch=',';
for (int i = 0; i < data.size();i++) {
stringstream stream(data[i]);
while( stream >>n ) {
if(stream >> ch) {
values.push_back(n);
}
else {
values.push_back(n);
}
cout<<n<<" ";
}
cout<<endl;
}
return 0;
}
input : 1,182,08 51 15 --> output : 1 182 8 1 5
there are some digits lost after spaces.
so, what can I do to avoid it?
Complete working code based on seccpur's answer. Visual Studio 2017 Community:
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
#define BUFSZ 100 // Set max size of the numbers as a single string
int convertToIntegers(char *s, vector<int> &values);
int main()
{
int count;
int i;
char data[BUFSZ];
vector<int> values;
strcpy_s(data, "1,182,08 51 15");
count = convertToIntegers(data, values);
// for (auto val : values) // Show the result
// cout << val << '\n';
// *** OR ***
for (i = 0; i < count; i++)
cout << values[i] << '\n';
}
//////////////////////////////////////
// Convert a C string to integers
//
int convertToIntegers(char *s, vector<int> &values)
{
vector<string> numbers;
char *next_token;
char* ptr = strtok_s(s, " -.,;", &next_token);
while (ptr)
{
string str(ptr);
numbers.push_back(str);
ptr = strtok_s(NULL, " -.,;", &next_token); // Next number
}
//
// Convert the resulting strings to integers
//
for (auto str : numbers)
values.push_back(stoi(str));
return (int)values.size();
}
If you know you have exactly one character as a separator, either a space, either a comma, the following code will work:
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
int main() {
string line;
vector <string>data;
for (int i = 0; i < 10;i++) {
getline(cin,line);
data.push_back(line);
}
///converting digits to int
vector<int> values;
int n;
char ch=',';
for (int i = 0; i < data.size();i++) {
stringstream stream(data[i]);
while( stream >>n ) {
char c = stream.get();
//if(stream >> ch) {
// values.push_back(n);
//}
//else {
values.push_back(n);
//}
cout<<n<<" ";
}
cout<<endl;
}
return 0;
}
You are using multiple delimiters in the input ( like whitespace : , ; -) which complicates the matter. Here's a possible snippet using std::strtok:
//Enter a line
string line;
getline(cin, line);
// Convert string to char* so that std::strtok could be used later
char *cstr = new char[line.length() + 1];
std::strcpy(cstr, line.c_str());
vector<string> words;
// split line into multiple strings using multiple delimiters
char* ptr = std::strtok(cstr, " -.,;");
while (ptr)
{
string str(ptr);
words.push_back(str);
ptr = strtok(NULL, " -.,;");
}
delete[] cstr;
// Convert string to int
vector<int> values;
for (auto str : words){
values.push_back(std::stoi(str));
}
// Print the values
for (auto val : values){
cout << val << '\n';
}

insert string into vector character by character

I'm trying to insert the characters of the string into a char vector but place the letters in reverse order . can anyone tell me why this doesn't work
int main()
{
string a = "Hello";
vector<char> arr(5);
for(int i = 4 ; i == 0 ; i--)
{
arr.push_back(a[i]);
cout << arr[i];
}
return 0;
}
im trying to push back the character in reverse order 1 by 1
Their are several problems with your code:
you are creating a vector whose size is initially 5, and then you are attempting to push 5 additional chars into it, for a total of 10 chars. You need to either:
initialize it's capacity instead of its size.
initialize the size as you are, but use arr[4-i] instead of arr.push_back() inside your loop.
your loop is never entered at all, since i == 0 is never true.
Try something more like this instead:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
string a = "Hello";
size_t len = a.size();
vector<char> arr;
arr.reserve(len);
for(int i = len-1; i >= 0; i--) {
arr.push_back(a[i]);
}
for(size_t i = 0; i < len; ++i) {
cout << arr[i];
}
return 0;
}
Alternatively:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
string a = "Hello";
size_t len = a.size();
vector<char> arr(len);
for(int i = len-1; i >= 0; i--) {
arr[len-1-i] = a[i];
}
for(size_t i = 0; i < len; ++i) {
cout << arr[i];
}
return 0;
}
Another way to deal with this in a more C++-ish way is to use iterators instead:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
string a = "Hello";
vector<char> arr;
arr.reserve(a.size());
for(auto iter = a.rbegin(); iter != a.rend(); ++iter) {
arr.push_back(*iter);
}
for(auto ch : arr) {
cout << ch;
}
return 0;
}
Alternatively:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
string a = "Hello";
vector<char> arr(a.size());
auto arr_iter = arr.begin();
for(auto a_iter = a.rbegin(); a_iter != a.rend(); ++a_iter, ++arr_iter) {
*arr_iter = *a_iter;
}
for(auto ch : arr) {
cout << ch;
}
return 0;
}
And then you can get rid of the manual loops altogether:
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;
int main() {
string a = "Hello";
vector<char> arr;
arr.reserve(a.size());
copy(a.rbegin(), a.rend(), back_inserter(arr));
cout.write(arr.data(), arr.size());
return 0;
}
Alternatively:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
string a = "Hello";
vector<char> arr(a.size());
copy(a.rbegin(), a.rend(), arr.begin());
cout.write(arr.data(), arr.size());
return 0;
}
Alternatively:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
string a = "Hello";
vector<char> arr(a.rbegin(), a.rend());
cout.write(arr.data(), arr.size());
return 0;
}
I'm not sure why you're complicating matters when a vector is perfectly capable of taking an iterator in the constructor? The vast majority of your code can therefore be replaced with a simple:
vector<char> arr(a.rbegin(), a.rend());
The complete program below shows this in action:
#include <iostream>
#include <string>
#include <vector>
using std::cout; using std::string; using std::vector;
int main() {
string a = ")-: yug emosdnah a si xaP";
vector<char> arr(a.rbegin(), a.rend());
for (auto ch: arr) cout << ch;
cout << '\n';
}
for(int i = 4 ; i == 0 ; i--)
That means to keep going while i is equal to zero - but i starts out at four, so the for loop terminates immediately.
You probably meant
for(int i = 4 ; i >= 0 ; i--)

C++ array string function

Can someone please show me how to create an array function that reads from file txt string data type
for example:
Read in the following files inside of a function:
colleges.txt
states.txt
Add the colleges/universities to a vector of strings.
Add the states to parallel arrays of strings.
Call the read function from your main function.
Thank you very much :D
Try the following code:
#include<iostream>
#include<string>
#include<fstream>
#include<vector>
void func()
{
std::ifstream fin;
fin.open("colleges.txt", std::ifstream::in);
std::vector<std::string> vec;
std::string line;
while(getline(fin, line))
{
vec.push_back(line);
}
fin.close();
int len = vec.size();
std::string *arr = new std::string[len];
int index = 0;
fin.open("states.txt", std::ifstream::in);
while(getline(fin, line))
{
arr[index++] = line;
}
fin.close();
for(auto e:vec) std::cout<<e<<" ";
std::cout<<"\n";
for(int i = 0; i < len; ++i)
std::cout<<arr[i]<<" ";
std::cout<<"\n";
delete [] arr;
}
int main()
{
func();
return 0;
}
use vectors, Carl!
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
using namespace std;
struct TwoVectors {
vector<string> first ;
vector<string> second;
};
TwoVectors getSomeData() {
TwoVectors ret;
auto collegesReader = ifstream("colleges.txt");
auto statesReader = ifstream("states.txt");
string temp;
while (getline(collegesReader, temp))
ret.first.push_back(temp);
while (getline(statesReader, temp))
ret.second.push_back(temp);
collegesReader.close();
statesReader.close();
return ret;
}
int main() {
auto someData = getSomeData();
for (auto something : someData.first)
cout << something << endl;
for (auto something : someData.second)
cout << something << endl;
return 0;
}

How to access numbers in string and convert it to integer?

I am using stoi function here and it is giving invalid argument error...
Here, the input file is something like "S13S12S11S10S1". I want to save the numbers in an array rank like rank[0]=13 rank[1]=12 and so on...
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main()
{
ifstream fin("input.txt");
string input;
fin>>input;
int count=0;
int val;
int rank[4];
for(int i=0 ; i < input.size(); i++)
{
string s1,s2;
s1=input[i];
s2=input[i+1];
if(s1[0]!='S' && s1[0]!='H' &&s1[0]!='D' && s1[0]!='C')
{
int a=stoi(s1);
rank[count]=a;
if(s2[0]!='S' && s2[0]!='H' &&s2[0]!='D' &&s2[0]!='C')
{
int temp;
int b=stoi(s2);
rank[count]=10+b;
count++;
i++;
}
else{
count++;
}
}
}
for (int count=0; count<=4 ; count++)
{
cout<<rank[count];
cout<<"\n";
}
}
You can tokenize the input string, using 'SHDC' for delimiters. And then use atoi to convert the tokens to integers. I would use a vector to store your rank values, if your input file(s) could have a varying number of tokens.
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;
int main()
{
ifstream fin("input.txt");
string input;
fin >> input;
const char *delimiters = "SHDC";
char *next_token = NULL;
char *token = strtok_s(const_cast<char*>(input.c_str()), delimiters, &next_token);
vector<int> values;
while (token != NULL) {
values.push_back(atoi(token));
token = strtok_s(NULL, delimiters, &next_token);
}
for (int i = 0; i < values.size(); ++i) {
cout << values[i] << endl;
}
}