Getting user input upon pressing a space - c++

I am trying to tackle this condition where the user has to input a number n. and then entering n numbers after it on the same line. Therefore my program needs to know this number n before the user continues to input so that the programs knows how large of a dynamic array it needs to save these numbers inputted after n. (It is crucial that all of this happens on one line).
I tried the following but it doesn't seem to work.
int r;
cin >> r;
//CL is a member function of a certain class
CL.R = r;
CL.create(r); //this is a member function creates the needed dynamic arrays E and F used bellow
int u, v;
for (int j = 0; j < r; j++)
{
cin >> u >> v;
CL.E[j] = u;
CL.F[j] = v;
}

You can do that as usual on a single line:
#include <string>
#include <sstream>
#include <iostream>
#include <limits>
using namespace std;
int main()
{
int *array;
string line;
getline(cin,line); //read the entire line
int size;
istringstream iss(line);
if (!(iss >> size))
{
//error, user did not input a proper size
}
else
{
//be sure to check that size > 0
array = new int[size];
for (int count = 0 ; count < size ; count++)
{
//we put each input in the array
if (!(iss >> array[count]))
{
//this input was not an integer, we reset the stream to a good state and ignore the input
iss.clear();
iss.ignore(numeric_limits<streamsize>::max(),' ');
}
}
cout << "Array contains:" << endl;
for (int i = 0 ; i < size ; i++)
{
cout << array[i] << ' ' << flush;
}
delete[] (array);
}
}
And here is the demonstration, you can see that the input is one line 6 1 2 3 4 5 6.
Once again, I did not check everything, so take care of that the way you need.
Edit: added reset of the stream after a bad read.

Related

Is integer overflow that evil?

Consider the following code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n, k;
cin >> n >> k;
vector<int> a(n);
int sum = 0;
for (auto &it : a) {
cin >> it;
sum += it;
}
cout << sum << "\n";
for (int i = 0; i < n; i++) {
cout << a[i] << " ";
}
cout << endl;
}
Input like (or anything greater than INT_MAX into k)
5 1234567891564
1 2 3 4 5
makes the program print
0
0 0 0 0 0
What actually happens? We don't use the value of k at all.
There is actually no integer overflow in your code. Well in a wider sense it there is, but in a more narrow sense integer overflow would happen for example with:
int k = 1234567891564;
What actually happens is that in this line
cin >> n >> k;
operator>> tries to read a int but fails. 1234567891564 is never actually assigned to k. When reading the input fails 0 will be assigned. Hence k comes out as 0.
Once the stream is in an error state, all subsequent calls to operator>> will silently fail as well. You should always check the state of the stream after taking input. For example:
if (std::cin >> n) {
// input succeeded use the value
} else {
// input did not succeed.
std::cin.clear(); // reset all error flags
}

Subtract each elements of an array consecutively

I have an array and I want to subtract each of the elements consecutively, ex: {1,2,3,4,5}, and it will result to -13 which is by 1-2-3-4-5.
But I don't declare or make those numbers fixed as they're taken from the input (user). I only make it like, int array[100] to declare the size.
Then, to get the inputs, I use the for loop and insert them to the array. Let's say first input is 10, then array[0] must be 10 and so on.
The problem is, how do I subtract them? I have two options:
The first element of the array (array[0]) will subtract the next element (array[1]) right after the user input the second element, and the result (let's say it's int x) will subtract the next element (array[2]) after the user input it and so on.
I'll have the user input all the numbers first, then subtract them one by one automatically using a loop (or any idea?) *These elements thing refer to the numbers the user input.
Question: How do you solve this problem?
(This program will let the user input for as much as they want until they type count. Frankly speaking, yeah I know it's quite absurd to see one typing words in the middle of inputting numbers, but in this case, just how can you do it?)
Thanks.
Let's see my code below of how I insert the user input into the array.
string input[100];
int arrayInput[100];
int x = 0;
for (int i = 0; i >= 0; i++) //which this will run until the user input 'count'
{
cout << "Number " << i+1 << ": ";
cin >> input[i];
arrayInput[i] = atoi(input[i].c_str());
...
//code to subtract them, and final answer will be in int x
...
if (input[i] == "count")
{
cout << "Result: " << x << endl;
}
}
You can/should use a dynamic sized container like std::vector as shown below:
#include <iostream>
#include <vector>
int main()
{
int n = 0;
//ask user how many input he/she wants to give
std::cout << "How many elements do you want to enter: ";
std::cin >> n;
std::vector<int> vec(n); //create a vector of size n
int resultOfSubtraction = 0;
//take input from user
for(int i = 0 ; i < n ; ++i)
{
std::cin >> vec.at(i);
if(i != 0)
{
resultOfSubtraction-= vec.at(i);
}
else
{
resultOfSubtraction = vec.at(i);
}
}
std::cout<<"result is: "<<resultOfSubtraction<<std::endl;
return 0;
}
Execute the program here.
If you want a string to end the loop then you can use:
#include <iostream>
#include <vector>
#include <sstream>
int main()
{
std::vector<int> vec;
int resultOfSubtraction = 0, i = 0;
std::string endLoopString = "count";
std::string inputString;
int number = 0;
//take input from user
while((std::getline(std::cin, inputString)) && (inputString!=endLoopString))
{
std::istringstream ss(inputString);
if(ss >> number)
{
vec.push_back(number);
if(i == 0)
{
resultOfSubtraction = number;
}
else
{
resultOfSubtraction-= number;
}
++i;
}
}
std::cout<<"result is: "<<resultOfSubtraction<<std::endl;
return 0;
}

Reading values from a file with a different amount of values per column, C++

I try to read values from a data file. However, it has a different amount of values per column which I need to extract.
The list of values looks like this:
8
11
0 0 -50
1000 0 -50
2000 0 0
0 500 0
500 500 0
0 1000 -50
1000 1000 0
2000 1000 150
With the code below I can store all values in the array but I want to store the 8 and the 11 seperatly. Furthermore should the first column (0 to 2000) be stored in one array, the second one (0 to 1000) in a second array and the third one (-50 to 150) in a third array.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
cout << "PROGRAM PIPE NETWORK" << endl;
//Read input data file
int n;
double *array;
cout << "How many data sets do you have?\nDatasets: ";
cin >> n;
ifstream infile("pipedata.dat");
array = new double[n];
for (int i = 1; i < n; ++i)
infile >> array[i];
return 0;
}
I hope some of you can help me and please try to not write a general answer. I am quiet new in this topic.
Greetings.
EDIT 1:
An other attempt is the following, however it works sometimes but I also get erros with data adresses or heap difficulties. Sometimes it works but most of the time my program just stops working.
int main()
{
cout << "PROGRAM PIPE NETWORK" << endl;
// Read input all data files
int n; double *input;
int limit_x, x; double *array_x;
int limit_y, y; double *array_y;
int limit_q, q; double *array_q;
int n_nodes, n_tubes;
cout << "How many data sets do you have?\nDatasets: ";
cin >> n;
ifstream infile("pipedata.dat");
input = new double[n];
for (int i = 0; i<n; ++i) infile >> input[i];
// Assign input values to their variables
// Number of nodes and number of tubes
n_nodes = input[0];
n_tubes = input[1];
cout << "Input values" << endl;
for (int i = 0; i < n; ++i)
{
cout << input[i] << endl;
}
cout << "---------------------------------------" << endl;
cout << "X-Values" << endl;
// Node data x-values
x = n_nodes;
limit_x = n_nodes * 3;
array_x = new double[x];
for (int i = 0; i < limit_x; i += 3) array_x[i] = 0;
for (int i = 0; i < limit_x; i+=3) array_x[i] = input[i+2];
for (int i = 0; i < limit_x; i+=3) cout << array_x[i] << endl;
return 0;
}
Everything works fine with "input" but not with array_x. Also I want to do the exact same thing with 5 other variables. I know it isnt the best solution but I realy dont understand why it does not work.
I don't know what the complications are, but here is an example:
std::vector<int> array_1;
std::vector<int> left;
std::vector<int> middle;
std::vector<int> right;
int temp;
// Read two numbers into an array
data_file >> temp;
array_1.push_back(temp);
data_file >> temp;
array_1.push_back(temp);
// Read columns of data into separate arrays
int left_value, middle_value, right_value;
while (data_file >> left >> middle >> right)
{
left.push_back(left_value);
middle.push_back(middle_value);
right.push_back(right_value);
}
The above is one example of many. It is not optimized.
Another example uses std::getline and std::istringstream, which would comply better with the alignment of the rows.
Edit1: Line by line processing
std::string text_line;
std::istringstream parser;
// Read a line from the file
std::getline(data_file, text_line);
// Extract the numbers from the line:
parser.str(text_line); // Initialize the std::istringstream with the text line.
int value_1 = 0;
parser >> value_1; // Extract the first number of the first line.
// Read the second line from the file
std::getline(data_file, text_line);
// Extract the numbers from the line:
parser.str(text_line); // Initialize the std::istringstream with the text line.
int value_2 = 0;
parser >> value_2; // Extract the first number of the second line.
// After reading 2 lines, the file pointer should be pointing
// at the 3rd line.
// The data format changes at the 3rd line with 3 numbers per line.
// Let's use an array this time, one per column.
const unsigned int ARRAY_CAPACITY = 256;
int column_1[ARRAY_CAPACITY];
int column_2[ARRAY_CAPACITY];
int column_3[ARRAY_CAPACITY];
unsigned int row = 0;
// Read until the data stream fails, usually at EOF.
while (std::getline(data_file, text_line))
{
// ** Very important, check for overflow before using array**
if (row >= ARRAY_CAPACITY)
{
// Either reallocate and copy old array or ...
// Crash the program.
std::cerr << "Array capacity is too small.\n";
exit(1);
}
// Initialize the parser
parser.str(text_line);
// Extract the first value and place into array, directly.
parser >> column_1[row];
// Likewise, the next columns.
parser >> column_2[row];
parser >> column_3[row];
// Advance the column index to the next row (line)
++row;
}

C++ Segmentation Fault with no pointers (HackerRank)

I solved a problem in Hacker Rank.
Input Format. The first line of the input contains an integer N.The next line contains N space separated integers.The third line contains a single integer x,denoting the position of an element that should be removed from the vector.The fourth line contains two integers a and b denoting the range that should be erased from the vector inclusive of a and exclusive of b.
Output Format. Print the size of the vector in the first line and the elements of the vector after the two erase operations in the second line separated by space.
CODE:
#include <vector>
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main() {
int n = 0, x = 0, value = 0;
vector<int> vk, vm;
vk.reserve(100000);
string k, m;
cin >> n;
cin.ignore();
getline(cin, k);
cin >> x;
cin.ignore();
getline(cin, m);
stringstream sk(k);
while (sk >> value)
vk.push_back(value);
stringstream sm(m);
while (sm >> value)
vm.push_back(value);
vk.erase(vk.begin() + x-1);
vk.erase(vk.begin() + vm[0]-1, vk.begin() + vm[1]-1);
cout << vk.size() << endl;
for (int i = 0; i < vk.size(); i++)
cout << vk[i] << " ";
cout << endl;
return 0;
}
But with this test case produce a "Segmentation Fault":
6
1 4 6 2 8 9
2
2 4
Can you help me to review my code and provide some feedback on what is the problem?
EDIT
Thanks to #john for the answer. Here is how it looks without the seg fault:
#include <vector>
#include <iostream>
#include <string>
using namespace std;
int main() {
int n = 0, x = 0, y = 0, z = 0, value = 0;
vector<int> vk;
vk.reserve(100000);
cin >> n;
for (int i = 0; i < n; ++i) {
cin >> value;
vk.push_back(value);
}
cin >> x >> y >> z;
vk.erase(vk.begin() + x-1);
vk.erase(vk.begin() + y-1, vk.begin() + z-1);
cout << vk.size() << endl;
for (int i = 0; i < vk.size(); i++)
cout << vk[i] << " ";
cout << endl;
return 0;
}
You're trying too hard with the your input code. It isn't correct because you seem to be assuming that cin.ignore() will skip the rest of the line, when it only skips the next character (which could be a space). I would guess this is the reason for the seg fault. You can tell how many numbers you have to read after you've read the first one. There is no need to use getline or stringsteam at all.
You don't need the vm vector. It will always contain two values, so just declare two variables. You could also pick much better names for all your variables.
cin >> n;
for (int i = 0; i < n; ++i)
{
cin >> value;
vk.push_back(value);
}
cin >> x >> vm0 >> vm1;

Store a word into a dynamically created array when first encountered

Here is the assignment:
Write a program that reads in a text file one word at a time. Store a word into a dynamically created array when it is first encountered. Create a paralle integer array to hold a count of the number of times that each particular word appears in the text file. If the word appears in the text file multiple times, do not add it into your dynamic array, but make sure to increment the corresponding word frequency counter in the parallel integer array. Remove any trailing punctuation from all words before doing any comparisons.
Create and use the following text file containing a quote from Bill Cosby to test your program.
I don't know the key to success, but the key to failure is trying to please everybody.
At the end of your program, generate a report that prints the contents of your two arrays in a format similar to the following:
Word Frequency Analysis
I 1
don't 1
know 1
the 2
key 2
...
Here is my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int readInFile (string tempArray [], string file, int arraySize);
int main()
{
ifstream inputFile;
string *readInArray = 0,
*compareArray = 0,
filename,
word;
int wordCount = 0;
int encountered = 0;
int j = 0,
*wordFrequency = 0;
cout << "Enter the filename you wish to read in: ";
getline(cin, filename);
inputFile.open(filename.c_str());
if (inputFile)
{
while (inputFile >> word)
{
wordCount++;
}
inputFile.close();
readInArray = new string[wordCount];
readInFile(readInArray, filename, wordCount);
}
else
{
cout << "Could not open file, ending program";
return 0;
}
compareArray = new string[wordCount];
wordFrequency = new int[wordCount];
for (int count = 0; count < wordCount; count++)
wordFrequency[count] = 0;
for(int i = 0; i < wordCount; ++i)
{
j = 0;
encountered = 0;
do
{
if (readInArray[i] == compareArray[j])
encountered = 1;
++j;
} while (j < wordCount);
if (encountered == 0)
{
compareArray[i]=readInArray[i];
wordFrequency[i] += 1;
}
}
for(int k=0; k < wordCount; ++k)
{
cout << "\n" << compareArray[k] << " ";
}
for(int l=0; l < wordCount; ++l)
{
cout << "\n" << wordFrequency[l] << " ";
}
return 0;
}
int readInFile (string tempArray [], string file, int arraySize)
{
ifstream inputFile;
inputFile.open(file.c_str());
if (inputFile)
{
cout << "\nHere is the text file:\n\n";
for(int i=0; i < arraySize; ++i)
{
inputFile >> tempArray[i];
cout << tempArray[i] << " ";
}
inputFile.close();
}
}
Here is my question:
How do you store a word into a dynamically created array when it is first encountered? As you can see from my code made a string array with some of the elements empty. I believe it is suppose to be done using pointers.
Also how do I get rid of the punctuation in the string array? Should it be converted to a c-string first? But then how would I compare the words without converting back to a string array?
Here is a link to a java program that does something similar:
http://math.hws.edu/eck/cs124/javanotes3/c10/ex-10-1-answer.html
Thank you for any help you can offer!!
As to the first part of your question, you are not using a dynamically created array. You are using a regular array. C++ provides implementations of dymnamic arrays, like the vector class http://www.cplusplus.com/reference/vector/vector/
As to the second part of your question, I see no reason to convert it to a c string. The string class in c++ provides functionality for removing and searching for characters. http://www.cplusplus.com/reference/string/string/
The string::erase function can be used to erase punctuation characters found with string::find.
Note: There are other ways of doing this assignment that may be easier (like having an array of structs containing a string and an int, or using a map) but that may defeat the purpose of the assignment.