I want my program to ask the user to input any number and then store it into a std::vector where every single digit is allocated to a separate vector index:
input: 142
output vector: [1, 4, 2]
I tried this:
int main()
{
std::vector<int> v;
int number;
cin >> number;
for(unsigned int i = 100; i > 0; i/=10)
{
v.push_back(number/i);
number -= (number/i)*i;
}
for(size_t i = 0; i < v.size(); ++i)
{
std::cout<<v[i]<<std::endl;
}
}
It works. But what should I do when the input-length is unknown?
Use simply std::string and for each char(which is actually integers) of string convert to integer as follows: SEE LIVE HERE
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::vector<int> v;
std::string number = "123456789987654321";
for(auto& Integer: number)
v.emplace_back(static_cast<int>(Integer - '0'));
for(const auto& it: v) std::cout << it << " ";
}
Output:
1 2 3 4 5 6 7 8 9 9 8 7 6 5 4 3 2 1
In case of entering unwanted characters/ user inputs(for example some negative numbers or even this: +-1234567), you can go for something with try-catch. try to convert the char to int, otherwise skip in the catch block as follows. SEE LIVE HERE
#include <iostream>
#include <vector>
#include <string>
#include <exception>
int main()
{
std::vector<int> v;
std::string number = "+-1234567";
for(auto& Integer: number)
{
std::string Char(1, Integer); // convert to string
try { v.emplace_back(std::stoi(Char)); }
catch(...) { continue; } // any case of exceptions
/* or using much simpler std::isdigit from <cctype>
by which conversion to std::string and try-catch can be avoided.
if(std::isdigit(Integer))
v.emplace_back(static_cast<int>(Integer - '0'));
*/
}
for(const auto& it: v) std::cout << it << " ";
}
Output:
1 2 3 4 5 6 7
Edte: As per #Aconcagua suggested, included the solution with std::isdigit
while(number) {
v.push_back(number%10);
number /= 10;
}
std::reverse(v.begin(), v.end());
Change the for initilization unsigned int i = number rather than unsigned int i = 100. The re-written for statement will be:
for(unsigned int i = number; i > 0; i/=10)
I you want to stay with digits and std::deque is an option you could do the following:
int main()
{
std::deque<int> v;
int number;
cin >> number;
while(number != 0)
{
v.push_front(number%10);
number = number/10;
}
for(size_t i = 0; i < v.size(); ++i)
{
std::cout<<v[i]<<std::endl;
}
return 0;
}
With the modulo operator you simply take the last digit and insert it in the front of the deque. Afterwards you "cut off" that digit with /10.
I used a deque, because you can't push front with vectors.
Related
It might be a really dumb question, but I have tried to look it up, and have googled a bunch, but still can't figure out an easy way...
In C++, saying that using namespace std;:
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
String N;
cin >> N;
}
When user input is 123, N will be "123".
How do I cast '1' to int 1, and '2' to int 2, and '3' to int 3?
I cannot use %.
It would be awesome if I were to use an index approach in the string.
I would like to have a function that receives N and its index as parameters. For instance:
int func(string N, int curr_ind)
{
// change curr_ind of N to a single int
// for instance, "123" and 1, it would return 2.
}
#include <iostream>
#include <string>
int get_digit_from_string(const std::string&s, int idx) {
return static_cast<int>(s[idx] - '0');
}
int main() {
std::string num{"12345"};
for (std::size_t i = 0; i < num.length(); ++i) {
std::cout << get_digit_from_string(num, i) << '\n';
}
}
Just get the character at the index, subtract '0', and cast to int.
The subtraction is necessary, otherwise the character of a digit will be cast to the ASCII value of that character. The ASCII value of '0' is 48.
Output:
❯ ./a.out
1
2
3
4
5
Now, just for fun, let's say you need frequent access to these digits. Ideally, you'd just do the conversion all at once and have these ints available to you. Here's one way of doing that (requires C++20):
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
std::vector<int> get_digits_from_string(const std::string& s) {
std::vector<int> v;
std::ranges::transform(s, std::back_inserter(v),
[](auto c) { return static_cast<int>(c - '0'); });
return v;
}
int main() {
std::string num{"12345"};
std::vector<int> digits = get_digits_from_string(num);
for (auto i : digits) {
std::cout << i << '\n';
}
}
We use the string to create a std::vector where each element is an int of the individual characters. I can then access the vector and get whatever digit I need easily.
Another possibility:
#include <iostream>
#include <string>
int main()
{
std::string input;
std::cin >> input;
// allocate int array for every character in input
int* value = new int[input.size()];
for (int i = 0; i < input.size(); ++i)
{
std::string t(1, input[i]);
value[i] = atoi(t.c_str());
}
// print int array
for (int i = 0; i < input.size(); ++i)
{
std::cout << value[i] << std::endl;
}
delete[] value;
}
Output:
x64/Debug/H1.exe
123
1
2
3
Try this:
int func(string N, int curr_ind)
{
return static_cast<int>(N[curr_ind]-'0');
}
Since the ASCII representation of consecutive digits differs by one, all you need to do to convert a character (char c;) representing a digit to the corresponding integer is: c-'0'
I need to input elements of vector of vector. Size of vectors is not known.
Row input ends with * character, as well as vector input.
EXAMPLE
2 5 1 3 4 *
9 8 9 *
3 3 2 3 *
4 5 2 1 1 3 2 *
*
Code:
#include <iostream>
#include <vector>
int main() {
std::vector < std::vector < int >> a;
int x;
int i = 0, j = 0;
for (;;) {
while (std::cin >> x) {
a[i][j] = x;
j++;
}
if (!std::cin >> x) break;
i++;
}
return 0;
}
This allows me to enter only the first row, and after that the program stops. Could you help me to modify this to allow input of other rows?
There are two problems with your code:
you are indexing into each vector without adding any values to it first, which is undefined behavior. a[i][j] = x; does not make the vectors grow in size. Use vector::push_back() instead.
You are not handling the input of * correctly. x is an int, so when std::cin >> x fails to read a non-integer value, like *, cin is put into an error state and all further reading fails until you clear() the error and ignore() the failed data from the input buffer.
Since your input is line-based, consider using std::getline() to read each line at a time. You can use a std::istringstream to read integers from each line, eg:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <iomanip>
int main() {
std::vector<std::vector<int>> a;
std::string line;
while (std::getline(std::cin, line)) {
std::istringstream iss(line);
iss >> std::ws;
if (iss.peek() == '*') break;
std::vector<int> v;
int x;
while (iss >> x) {
v.push_back(x);
}
a.push_back(v);
}
for(auto &v : a) {
for(int num : v) {
std::cout << num << ' ';
}
std::cout << std::endl;
}
return 0;
}
I have the following file input.txt which contains the values :
0 0
0 1
0 2
0 3
1 1
1 4
2 1
2 4
2 3
I want to insert these values to two arrays. I want them to look like this in the end.
0 0 1 2 3
1 1 4
2 1 4 3
First array will contain the id and second array will contain the elements. I have managed to dynamically allocate memory for these two arrays using the following :
int n,m,i=0,tempNum,lines;
int NumberOfIds=0;
ifstream read("input2.txt");
while(read>>n>>m){
if (i==0){
tempNum=n;
}
if (tempNum != n){
NumberOfIds++;
}
tempNum = n;
i++;
}
lines=i-1;
//printf("%d", j);
int** idElements = new int*[NumberOfIds];
int* ids = new int[NumberOfIds];
int* numberOfIdElements = new int[NumberOfIds];
// Rewinds file
read.clear();
read.seekg(0, ios::beg);
int counter = 0;
NumberOfIds=0;
while(read>>n>>m){
if (tempNum != n){
numberOfIdElements[NumberOfIds] = counter;
NumberOfIds++;
counter = 0;
}
tempNum = n;
counter++;
i++;
}
for(int k = 0; k < NumberOfIds; ++k)
idElements[k] = new int[numberOfIdElements[k]];
Now I am stuck in how to insert the data. Any help would be appreciated.
You can do this with std::vector's fairly easily:
std::vector<std::vector<int>> arr;
while(read>>n>>m){
//if we're too small, push empty rows till we're big enough
while(n + 1 > arr.size()) {
arr.push_back(std::vector<int>());
}
arr.at(n).push_back(m); //push m onto row n
}
Alternatively, if your first column numbers become large (so you wouldn't want to make many empty rows), you can use an std::map:
std::map<int, std::vector<int>> arr;
while(read>>n>>m){
//works because map subscript creates a key/val pair if one doesn't exist
//so if this row doesn't exist, we get a new vector to push_back to
arr[n].push_back(m); //push m onto row n
}
See it in action here: ideone
Here is another approach using a map of sets:
#include <sstream>
#include <string>
#include <iostream>
#include <fstream>
#include <map>
#include <set>
int main()
{
std::map<int, std::set<int>> m;
std::ifstream ifs{"input.txt"};
// read
for(std::string line; std::getline(ifs, line);){
std::stringstream ss{line};
int key;
ss >> key;
for (int val; ss >> val;)
m[key].insert(val);
}
// print
for(auto i : m) {
std::cout << i.first << '\t';
for(auto j : i.second)
std::cout << j << ' ';
std::cout << '\n';
}
}
You might select other containers depending of your requirements for sorting or preserving duplicates.
I have a string contains numbers but also contains spaces between them, i need to convert the string to int and store them in an int array .
Th following function produces a run time error
void fun(string m)
{
string temp;
int j = 0;
int h = 0;
int d;
int arr[10];
for (int i = 0; i < m.length(); i++)
{
while (m[i] != ' ')
temp[j++] = m[i];
d = atoi(temp.c_str());
arr[h++] = d;
}
for (int i = 0; i < sizeof(arr); i++)
{
cout << arr[i];
}
}
I would suggest using a stringstream for this vs. rolling your own implementation.
#include <sstream>
#include <iterator>
#include <iostream>
int main()
{
std::stringstream ss("1 2 3 4 5 6 7");
auto head = std::istream_iterator<int>(ss);
auto tail = std::istream_iterator<int>();
while(head!=tail)
{
std::cout << *head << "\n";
++head;
}
return 0;
}
if you're receiving the string in a method you can easily adapt the function above to create an empty stringstream and then pass it the string.
#include <sstream>
#include <iterator>
#include <iostream>
int main()
{
std::string astring = "1 2 3 4 5 6";
std::stringstream ss;
ss << astring;
auto head = std::istream_iterator<int>(ss);
auto tail = std::istream_iterator<int>();
while(head!=tail)
{
std::cout << *head << "\n";
++head;
}
return 0;
}
You are making several mistakes in your code.
You have not initialized temp to contain anything, but you are trying to index into its characters. Instead of temp[j++] = m[i], you need to use temp += m[i]; or temp.push_back(m[i]); or temp.append(&m[i], 1);. Or consider using an std::ostringstream to gather the characters, and then call its str() method to extract the final std::string value.
you are not incrementing i in your while loop. As soon as the for loop reaches a non-whitespace character, your while loop will end up running endlessly, continuously (and unsuccessfully) trying to append the same character to temp.
you are not doing any bounds checking to make sure your for loop does not exceed arr's max capacity of 10 numbers.
you are misusing sizeof(). sizeof(arr) returns the number of bytes that arr occupies in memory (10 * sizeof(int), which is 20 or 40 bytes, depending on your compiler's implementation of int). It is not the number of elements in the array (10). So you will exceed the bounds of the array trying to display 20/40 numbers instead of 10 numbers.
Your code is more complicated than it needs to be. You can use a std::istringstream for parsing and let it ignore whitespace for you. Use std::vector or other dynamically-sized container to receive the parsed numbers.
#include <sstream>
#include <vector>
void fun(string m)
{
std::istreamstream iss(m);
std::vector<int> vec;
int num;
vec.reserve(10); // optional
while (iss >> num) {
vec.push_back(num);
}
for (int i = 0; i < vec.size(); ++i) {
std::cout << vec[i];
}
/*
alternatively:
for (std::vector<int>::iterator iter = vec.begin(); iter != vec.end(); ++iter) {
std::cout << *iter;
}
*/
/*
alternatively (C++11 and later):
for (auto i: vec) {
std::cout << i;
}
*/
/*
alternatively (C++11 and later):
std::for_each(vec.begin(), vec.end(), [](int &n){ std::cout << n; });
*/
}
You cannot do for (int i = 0; i < sizeof(arr); i++)
The sizeof() operator gives you the size of something in bytes, which for an array of 10 ints probably amounts to 40. You need to use something like this:
#define COUNTOF(x) ((x)/sizeof((x)[0]))
for (int i = 0; i < COUNTOF(arr); i++)
The problem is in your while loop, J is 0 the first iteration through the While loop and gets incremented the first time it's called while also trying to assign it to the next letter.
Despite this issue I'd suggest using a string stream for this problem like others have said.
Here's a good reference.
My problem looks like this:
At the beginning u have to insert an amount of numbers.
Next program counts the sum of digits of the number that u inserted in step one.
All scores are inserted in vector called vec
The problem is this: At the end of the program all numbers that You inserted in steps 1, must be sorted depends of theirs sums of digits(Sorting in increasing order).
And ATTENTION please! For example if two of numbers(e.g. 123 and 12300) have the same sum of digits you have to sort them by the lexicographic order.
I don't want to create function build by myself but I would like to use “sort” function from library but I have problem with that..Is it possible to use sort function also to sorting by the lexicographic order? Can someone can help me?
Example input:
6
13
36
27
12
4
123
Expected output:
12
13
4
123
27
36
My code:
#include<iostream>
#include<cmath>
#include<string>
#include<vector>
#include<sstream>
#include<algorithm>
using namespace std;
int main()
{
vector<vector<int> > vec;
int num;
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> num;
vector<int> row;
row.push_back(num);
//conversion int to string:
ostringstream ss;
ss << num;
string str = ss.str();
int sum = 0;
for (int g = 0; g < str.length(); g++){
int pom = str[g] - '0';
sum += pom;
}
row.push_back(sum);
vec.push_back(row);
row.clear();
}
//sort(vec[0][0], vec[vec.size()][0]);
for (int i = 0; i < vec.size(); i++){
for (int j = 0; j < 2; j++){
//cout << vec[i][j] << " ";
}
cout << vec[i][0] << endl;
}
system("pause");
return 0;
}
You could store each number as a string, but also pre-compute its digit-sum and keep both in a pair<int,string>, then put them into a vector<pair<int,string> and sort it. No need for a custom comparator, the one for std::pair does exactly what you want.
// note: std::pair<std::string,int> would not work
typedef std::pair<int,std::string> number;
std::vector<number> numbers;
// fill numbers such that number::first holds the digit sum
// and number::second the number as string.
// this is similar to your code
std::sort(numbers.begin(), numbers.end());
// now numbers are ordered as you want them
Just pass a suitable comparison function (or functor, e.g. a lambda would be natural) to std::sort.
Since you want to compare on sum of digits first and then lexicographically to break ties, it will be convenient to convert your input numbers to strings.
From there you can define a custom comparator to achieve the desired behavior:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int sumDigits(string s)
{
int sum = 0;
for (unsigned int i=0; i<s.length(); ++i)
{
sum += s[i] - '0';
}
return sum;
}
bool digitSumComparator(int i, int j)
{
int iSum = sumDigits(to_string(i));
int jSum = sumDigits(to_string(j));
if (iSum == jSum)
{
return iStr < jStr;
}
else
{
return iSum < jSum;
}
}
int main()
{
vector<int> v {6,13,36,27,12,4,123};
sort(v.begin(), v.end(), digitSumComparator);
for (vector<int>::iterator it=v.begin(); it!=v.end(); ++it)
{
cout << *it << ' ';
}
cout << '\n';
return 0;
}
Output:
$ g++ -std=c++11 digitsumsort.cpp
$ ./a.out
12 13 4 123 6 27 36