C++ reading char values gives different letters sometimes - c++

I have to write a short routine that will write out only upper case letters in reversed order. I managed to muster up code that somehow works, but whenever I test out my code with one specific input:
7 ENTER a b C d E f G
Instead of getting G E C I get
G (special) r E
I can't see what causes the problem, especially because it works for so many other cases. Here's the code:
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
char stringa[n];
int length = 0;
for (int i = 0; i <= n-1; i++) {
char letter;
cin >> letter;
if (isupper (letter)) {
stringa[((n-i) - 1)] = letter;
length = length +1;
} } for ( int i =0; i<=length-1; i++) {
cout << ciag[i]

The main problem is that you are not populating your array correctly.
You are not initializing the content of the array before filling it, so it contains random garbage. Then you are filling specific elements of the array using indexes that are the directly related to each uppercase character's original position in the input, rather than the position they should appear in the output.
Since you are not initializing the array, and the input has mixed lower/upper casing, your array is going to have gaps containing random data:
stringa[0] = G
stringa[1] = <random>
stringa[2] = <random>
stringa[3] = <random>
stringa[4] = E
stringa[5] = <random>
stringa[6] = <random>
stringa[7] = <random>
stringa[8] = C
stringa[9] = <random>
stringa[10] = <random>
stringa[11] = <random>
stringa[12] = <random>
stringa[13] = <random>
stringa[14] = R
stringa[15] = E
stringa[16] = T
stringa[17] = N
stringa[18] = E
stringa[19] = <random>
stringa[20] = <random>
That is what you are seeing appear in your garbled output.
Try something more like this instead:
#include <iostream>
#include <vector>
#include <cctype>
int main()
{
int n;
std::cin >> n;
std::vector<char> stringa(n); // 'char stringa[n];' is not standard!
int length = 0;
for (int i = 0; i < n; ++i)
{
char letter;
std::cin >> letter;
if (std::isupper (letter))
{
stringa[length] = letter;
++length;
}
}
for (int i = length-1; i >= 0; --i)
{
std::cout << stringa[i];
}
return 0;
}
Or:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cctype>
int main()
{
int n;
std::cin >> n;
std::vector<char> stringa(n); // 'char stringa[n];' is not standard!
int length = 0;
for (int i = 0; i < n; ++i)
{
char letter;
std::cin >> letter;
if (std::isupper (letter))
{
stringa[length] = letter;
++length;
}
}
std::reverse(stringa.begin(), stringa.begin()+length);
for (int i = 0; i < length; ++i)
{
std::cout << stringa[i];
}
return 0;
}
Both approaches produces the following array content during the first loop, and then simply output it in reverse order in the second loop:
stringa[0] = E
stringa[1] = N
stringa[2] = T
stringa[3] = E
stringa[4] = R
stringa[5] = C
stringa[6] = E
stringa[7] = G
Alternatively, I would suggest using std::getline() instead of a reading loop to obtain the user's input, and then simply manipulate the resulting std::string as needed:
#include <iostream>
#include <string>
#include <algorithm>
bool IsNotUpper(char ch)
{
return !std::isupper(ch);
}
int main()
{
std::string stringa;
std::getline(std::cin, stringa); // returns "7 ENTER a b C d E f G"
// so std::isupper() will return false for everything not in A-Z
std::setlocale(LC_ALL, "C");
stringa.erase(
std::remove_if(stringa.begin(), stringa.end(), &IsNotUpper),
stringa.end());
// returns "ENTERCEG"
std::reverse(stringa.begin(), stringa.end());
// returns "GECRETNE"
std::cout << stringa;
return 0;
}
Or, if using C++11 and later, you can use a lambda instead of a function for the std::remove_if() predicate:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
std::string stringa;
std::getline(std::cin, stringa);
std::setlocale(LC_ALL, "C");
stringa.erase(
std::remove_if(
stringa.begin(), stringa.end(),
[](char ch){return !std::isupper(ch);}
),
stringa.end());
std::reverse(stringa.begin(), stringa.end());
std::cout << stringa;
return 0;
}

Your algorithm just doesn't make any sense. You are expecting the characters to be in the array with no gaps but you skip an entry in the array when the input isn't a capital letter. Instead, put the capital letters in consecutive slots in the array in the forward direction and then traverse it in reverse order afterwards.

Related

std::cin string to int array with variable length input

I have a task where i need to revert a list of variable length numbers. This could be "1 2 3" or "5 6 7 8 9 10".
The sorting itself works fine.
But I can't figure out how to read the user input (with variable length) and then only execute the reverseSort once.
How can I read the user input into an array where each index is based on the space between the numbers?
Here is my code:
#include <iostream>
#include <string>
using namespace std;
bool sorted = true;
int temp;
int * arr;
int arrLength = 5;
int arrs;
// int arr = {1,2,3,4,5};
void reverseSort(int arr[], int n){
sorted = true;
for (int i = 0; i < n-1; i++){
if (arr[(i + 1)] > arr[i]){
temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
sorted = false;
}
}
if (!sorted){
reverseSort(arr,n);
}
}
int main(void){
// get user input !?!?!?!?!
cin >> arrs;
cout << arrs;
reverseSort(arr,arrLength);
for (int i = 0; i < arrLength; i++){
std::cout << arr[i] << " ";
}
return 0;
}
If you don't know number of inputs you need struct that can be resized. std::vector is good for it. For adding new data you can use member function push_back.
You can read the input line as std::string (by std::getline) and you can open new stream with read data (std::istringstream). Further one can read values from new stream.
And I think you can use std::sort instead of reverseSort (but for 'reverse' you need use std::greater as comparator).
#include <vector>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <algorithm>
int main(void){
std::vector<int> arrs;
// read only one line
std::string input;
std::getline(std::cin, input);
std::istringstream row(input);
int x;
while (row >> x)
{
arrs.push_back(x);
}
//like your reverseSort
std::sort(arrs.begin(), arrs.end(), std::greater<int>{});
for (auto var : arrs) {
std::cout << var << "; ";
}
return 0;
}

How to know the number of digits in an integer

I'm new to programming, and I'm wondering, how can I know the number of digits in an integer that the user enters? For example: the user enters a number like 123456, how can I know that the user enters 6 digits? I don't want to use a for loop to get user input because I don't want the user to enter each digit after a space or enter.
Right now, I'm converting a number to an array of digits so I can have control over them, but the issue is that I don't know how many digits I should loop over, because I don't know how many digits are in the number.
Can I get the user's input as a string and then use string.length and convert it to an array of digits?
#include <iostream>
using namespace std;
int main()
{
int N;
cin >> N;
while(N--)
{
int num;
cin >> num;
int arr[1000];
for (int i=0 ;i<???;i++)
{
arr.[i]=num%10;
num = num /10;
}
}
}
an easier way to do this is to convert it to a string then count the length of said string
#include <iostream>
#include <string>
using namespace std;
int main() {
int n;
cin >> n;
string str = to_string(n);
cout <<"the length of" <<str << "is:" <<str.length() <<"\n";
}
typing in a 41 will print out.
the length of 41 is 2
while (num != 0)
{
arr.[i]=num%10;
num = num /10;
}
is a common pattern that's close to what you already have.
Although you can do what you mentioned in your question and someone suggested in the comments and get the input as a string and use string.length.
Yes, you can read in the user's input as a std::string instead of as an int, and then you can use std::string::size() (or std::string::length()) to get the number of characters in the string, eg:
#include <iostream>
#include <string>
int main()
{
std::string S;
std::cin >> S;
int arr[1000] = {};
for (size_t i = 0; i < S.size(); ++i)
{
arr[i] = (S[i] - '0');
}
return 0;
}
Alternatively:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
std::string S;
std::cin >> S;
int arr[1000] = {};
std::transform(S.begin(), S.end(), arr, [](char ch){ return int(ch - '0'); });
return 0;
}
Either way, if needed, you can check if the std::string represents a valid integer using std::stoi() or std::strtol() or other similar function, or by putting the std::string into a std::istringstream and then reading an integer from it.
Otherwise, you can read the user's input as an int and then convert it to a std::string for processing:
#include <iostream>
#include <string>
int main()
{
unsigned int N;
std::cin >> N;
std::string S = std::to_string(N);
int arr[1000] = {};
for (size_t i = 0; i < S.size(); ++i)
{
arr[i] = (S[i] - '0');
}
// or:
// std::transform(S.begin(), S.end(), arr, [](char ch){ return int(ch - '0'); });
return 0;
}
Otherwise, if you really want to read in an int and loop through its digits directly, you can use something more like this:
#include <iostream>
int main()
{
unsigned int N;
std::cin >> N;
int arr[1000] = {};
size_t i = 0;
while (N != 0)
{
arr[i++] = num % 10;
num /= 10;
}
return 0;
}

Displaying all prefixes of a word in C++

I am trying to do is display all the suffixes of a word as such:
word: house
print:
h
ho
hou
hous
house
What I did is:
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char cuvant[100];
int i,k;
cin>>cuvant;
for(i=0;i<strlen(cuvant);i++)
{
for(k=0;k<i;k++)
{
if(k==0)
{
cout<<cuvant[k]<<endl;
}else
{
for(k=1;k<=i;k++){
if(k==i) cout<<endl;
cout<<cuvant[k];
}
}
}
}
}
What am I doing wrong?
You're over-complicating it. Here's a simpler way:
#include <iostream>
#include <string>
#include <string_view>
int main() {
std::string s;
std::cin >> s;
for (std::string::size_type i = 0, size = s.size(); i != size; ++i)
std::cout << std::string_view{s.c_str(), i + 1} << '\n';
}
If you don't have access to a C++17 compiler, you can use this one:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
int main() {
std::string s;
std::cin >> s;
for (auto const& ch : s) {
std::copy(s.c_str(), (&ch + 1),
std::ostream_iterator<decltype(ch)>(std::cout));
std::cout << '\n';
}
}
Even so, I think it would be better for your learning progress to use a debugger to finger out the problem yourself. Here the problems with your code:
For the i=0 (the first iteration of your outer loop) the for(k=0;k<i;k++) will not be executed at all, as k<0 evaluates to false.
And having a running variable (k) that you change in two for loops that are nested, is most of the time also an indication that something is wrong.
So what you want to do: You want to create each possible prefix, so you want to create n strings with the length of 1 to n. So your first idea with the outer loop is correct. But you overcomplicate the inner part.
For the inner part, you want to print all chars from the index 0 up to i.
int main() {
char cuvant[100];
std::cin >> cuvant;
// loop over the length of the string
for (int i = 0, size = strlen(cuvant); i < size; i++) {
// print all chars from 0 upto to i (k<=0)
for (int k = 0; k <= i; k++) {
std::cout << cuvant[k];
}
// print a new line after that
std::cout << std::endl;
}
}
But instead of reinventing the wheel I would use the functions the std provides:
int main() {
std::string s;
std::cin >> s;
for (std::size_t i = 0, size = s.size(); i < size; i++) {
std::cout << s.substr(0, i + 1) << std::endl;
}
}
For this very simple string suffix task you can just use:
void main()
{
std::string s = "house";
std::string s2;
for(char c : s)
{
s2 += c;
cout << s2 << endl;
}
}
For more complicated problems you may be interested to read about Suffix Tree
Your code is wrong, the following code can fulfill your requirements
#include <iostream>
using namespace std;
int main()
{
char cuvant[100];
int i,k;
cin>>cuvant;
for(i=0;i<strlen(cuvant);i++)
{
for (k = 0; k <= i; ++k)
{
cout<<cuvant[k];
}
cout<<endl;
}
}

Show me a way to sort a char vector in c++

I'm doing this exercise from DCoder, and I'm trying to solve it in C++. But I need a little help. Although I know this should be simple, I just seem to miss something.
I'm given 2 inputs, the first one is the number of letters that will follow, and the second input is these letters. I need to write a code that will give an output of the letter array in alphabetically sorted order.
Example input:
5
Z k a P b
Expected output:
a b k P Z
Can any of you guys show me what the simplest way is to solve my problem?
I tried the std::sort() function in many ways, but it's not helping me much.
Is the std::sort() function even a good way to sort something like this?
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
//Compiler version g++ 6.3.0
int main() {
int n;
cin >> n;
char s;
vector<char> vec;
while (cin >> s){
vec.push_back(s);
}
sort(vec.begin(), vec.end());
for (int i = 0; i <= vec.size(); i++){
cout << vec[i] << " " ;
}
}
My code is supposed to output a c D M, but it's giving D M a c instead.
std::sort() will work fine, but note that it orders values in ascending order by default, and in ASCII uppercase letters appear before lowercase letters. To get around that, you can give std::sort() a custom comparator that performs a case-insensitive comparison, eg:
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cctype>
int main() {
int n;
char c;
std::vector<char> vec;
std::cin >> n;
for (int i = 0; (i < n) && (std::cin >> c); ++i) {
vec.push_back(c);
}
/* alternatively:
std::copy_n(std::istream_iterator<char>(std::cin), n, std::back_inserter(vec));
*/
std::sort(vec.begin(), vec.end(),
[](unsigned char c1, unsigned char c2){ return std::tolower(c1) < std::tolower(c2); }
);
for (size_t i = 0; i < vec.size(); ++i){
std::cout << vec[i] << " ";
}
/* alternatively:
for (char c : vec){
std::cout << c << " ";
}
*/
}
Live Demo
This is the code that worked for me:
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cctype>
using namespace std;
//Compiler version g++ 6.3.0
char my_tolower(char ch)
{
return static_cast<char>(tolower(static_cast<unsigned char>(ch)));
}
int main() {
int n;
cin >> n;
char c;
vector<char> vec;
for (int i = 0; (i < n) && (cin >> c); ++i){
vec.push_back(c);
}
sort(vec.begin(), vec.end(),
[](char c1, char c2){ return my_tolower(c1) < my_tolower(c2); }
);
for (auto &&c : vec){
cout << c << " ";
}
}

sorting array of strings one off

This code is supposed to make a array of strings, randomly order them, and then print the order. Unfortunately it adds a blank line in one of the spaces ( i think this is getline's doing). Any ideas how to fix that? I tried setting array [0] = NULL; it complains about operators...
#include <iostream>
#include <stdio.h>
#include <conio.h>
#include <time.h>
#include <string>
#include <cstdlib>
using std::cout;
using std::endl;
using namespace std;
void swap (string &one, string &two)
{
string tmp = one;
one = two;
two = tmp;
}
int rand_loc (int size)
{
return (rand() % size);
}
int main()
{
srand(time(NULL));
int size;
cin >> size;
string *array = new string[size];
//array[0] = NULL ;
for (int x = 0; x < size; x++)
{
getline(cin, array[x]);
}
//for (int x = 0; x < size; x++)
//{
// swap (array[rand_loc(size)], array[rand_loc(size)]);
//}
cout << endl;
for (int x = 0; x < size; x++)
{
//out << array[x] << endl;
int y = x + 1;
cout<<y<<"."<<" "<<array[x]<<endl;
}
delete[] array;
}
The first call to getline() will immediately hit the newline that the user entered after inputting size, and will therefore return an empty string. Try to call cin.ignore(255, '\n'); before the first call to getline(). This will skip up to 255 (an arbitrarily selected number) characters until a \n is encountered (and the newline will be skipped as well).
Edit: As #Johnsyweb and #ildjarn point out, std::numeric_limits<streamsize>::max() is a much better choice than 255.