This question already has answers here:
How to determine if a string is a number with C++?
(36 answers)
Closed 8 years ago.
I am working on program that would calculate with matrixes but i am not sure what is best way how to read matrix line by line from command line.
My goal is this:
Please enter number of lines:
2
Please enter line 1/2:
1 4 5 2
Please enter line 2/2:
1 5 7 8
At the end of this i would like to have array or vector of numbers 1,4,5,2,1,5,7,8.
This is my code:
vector<string>matrix;
string input;
int nrows;
cout << "Enter number of rows:" << endl;
cin >> nrows;
getline(cin, input);
for (int i = 1; i <= nrows; i++) {
cout << "Enter line " << i << "/" << nrows << endl;
getline(cin, input);
matrix.push_back(input);
}
for (int i = 0; i < matrix.size();i++){
cout << matrix.at(i)<<endl;
}
This reads whole line and save it into vector of string and there is much to do to separate just numbers. Is there any way how could I load only numbers in the line ? So for example for the line:
1 a 3 2 4sdsd
I would get numbers 1,3,2,4 ?
Thank for any help.
string process(const string& input) // Removes all characters except <space> and digits [0-9]
{
string ret;
for(int i=0; i<(int)input.size(); i++)
{
if(input[i]==' '||(input[i]>='0'&&input[i]<='9'))
ret+=input[i];
}
return ret;
}
int main()
{
int nrows;
string input;
cout<<"Enter number of rows - ";
cin>>nrows;
cin.get(); // Take the remaining <Enter>
vector<vector<int> > matrix(nrows); // A 2-D vector representing the matrix
for(int i=0; i<(int)matrix.size(); i++)
{
cout<<"Please enter line "<<i+1<<"/"<<nrows<<" -: \n";
getline(cin,input);
stringstream ss(process(input));
int num;
while(ss>>num)
{
matrix[i].push_back(num);
}
}
for(int i=0; i<(int)matrix.size(); i++) // Display the matrix
{
for(int j=0; j<(int)matrix[i].size(); j++)
{
cout<<matrix[i][j]<<" ";
}
cout<<"\n";
}
}
I would use a 2D vector. Also, ask the user for number of columns:
vector<vector<int>> matrix;
int nrows, ncols;
cout << "Enter number of rows:" << endl;
cin >> nrows;
cout << "Enter number of columns:" << endl;
cin >> ncols;
matrix.resize(nrows);
for (int i = 0; i < nrows; i++) {
cout << "Enter line " << (i+1) << "/" << nrows << endl;
int tmp;
while (matrix[i].size() < ncols) {
while (!(cin >> tmp)) { // Not a number. Clear cin
cin.clear();
cin.ignore(1);
}
matrix[i].push_back(tmp);
}
}
One way to do it:
// only allow digits and spaces
string removeNonNumbers(const string& s) {
stringstream ss;
for(int i=0; i<s.length(); ++i) {
if(isdigit(s[i]) || ' ' == s[i])
ss << s[i];
}
return ss.str();
}
vector<int> splitToInts(const string& s) {
vector<int> ret;
stringstream ssin(s);
while (ssin.good()){
string tmp;
ssin >> tmp;
ret.push_back(atoi(tmp.c_str()));
}
return ret;
}
To use it, do this when reading input in your getline loop:
vector<int> numbers = splitToInts( removeNonNumbers(input) );
Related
(C++) I've created a function to open the text file and assign the contents to an array. The first 2 elements in the array are the size of the grid. However, if either or both of the first 2 numbers are double digits, it doesnt read them in as double digits. Is there any way of doing this?
int openMap()
{
std::string fileName;
std::cout << "Please enter the file name with extension that you want to open: ";
std::cin >> fileName;
system("CLS");
std::ifstream file(fileName); //OPENS MAP FILE
int tmp;
int i = 0;
if (!file.is_open()) //CHECKS IF THE MAP FILE HAS OPENED CORRECTLY
{
std::cout << "Error Occured!\nCould not open file.";
return 0;
}
while (!file.eof()) //READS THE MAP FILE AND PASSES THE INFORMATION INTO AN ARRAY
{
file >> tmp;
checkNumber(tmp);
if (valid == true) //IF THE CHARACTER IS NOT A NUMBER THEN IT WONT BE PASSED INTO THE ARRAY
{
tmpArray[i] = tmp;
i++;
valid = false;
}
row = tmpArray[1]; //ASSIGNS THE FIRST 2 NUMBERS OF THE MAP FILE TO ROW AND COL VARIABLES
col = tmpArray[0];
}
return row, col;
}
I would assume I have to rewrite
file >> tmp
in some sort of different way, but not sure how.
Is there a way to scan through the text file until it hits a whitespace?
The text file contents looks like this
6 4 0 0 1 0 0 0 2 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0 3 0
(the 6 or 4 or both can be double digits instead)
Edit:
for (int j = 0; j < row; j++)
{
for (int k = 0; k < col; k++)
{
_map[j][k] = tmpArray[l];
std::cout << _map[j][k] << " ";
l++;
}
}
There's quite a number of bugs in the code, you should probably use a debugger to step through and identify which parts of your program don't behave as expected.
while(!file.eof())
file >> tmp;
checkNumber(tmp);
if (valid == true) //IF THE CHARACTER IS NOT A NUMBER THEN IT WONT BE PASSED INTO THE ARRAY
{
tmpArray[i] = tmp;
i++;
valid = false;
}
row = tmpArray[1]; //ASSIGNS THE FIRST 2 NUMBERS OF THE MAP FILE TO ROW AND COL VARIABLES
col = tmpArray[0];
You set row=tmpArray[1] and col = tmpArray[0] every iteration of the loop which is not only unnecessary but also incorrect, especially since row=tmpArray[1] is being executed at i=0 when nothing has been placed in tmpArray[1] yet.
EDIT: This is a lot smaller, less error prone due to less variables and type conversions, and easier to read:
int row,col;
//Add error checking here
cin >> col;
cin >> row;
cout << "Cols: " << col << " Rows: " << row << endl;
vector<vector<int> >_map(row, vector<int>(col,0));
for(int j=0; j < row; j++)
{
for(int k=0; k < col; k++)
{
int tmp;
cin >> tmp;
//Add error checking for tmp
_map[j][k] = tmp;
cout << _map[j][k] << endl;
}
}
There are some problems with your code. First the return type of your function is int but you are returning multiple values. Here is a complete running code which should solve your problem.
#include <iostream>
#include <fstream>
#include <vector>
std::vector< std::vector<int> > openMap() {
std::string fileName;
std::cout << "Please enter the file name with extension that you want to open: ";
std::cin >> fileName;
std::fstream myfile(fileName, std::ios_base::in);
int row, col;
myfile >> row;
myfile >> col;
int a;
std::vector< std::vector<int> > retval;
for (int i = 0; i < row; i++) {
std::vector<int> v1;
for (int j = 0; j < col; j++) {
myfile >> a;
v1.push_back(a);
}
retval.push_back(v1);
}
return retval;
}
int main(int argc, char * argv[])
{
std::vector< std::vector<int> > _map = openMap();
for(int i = 0; i < _map.size(); i++) {
for (int j = 0; j < _map[i].size(); j++) {
std::cout << _map[i][j] << " ";
}
std::cout << std::endl;
}
return 0;
}
I guess that not so many people will be interested. But please see below a possible solution to your problem.
The code uses modern C++ algorithms.
It is very simple and straightforward.
#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
#include <algorithm>
int main() {
// Ask user, to give a filename
std::cout << "Please enter the file name with extension that you want to open: ";
// Get the filename from the user
if (std::string fileName; std::cin >> fileName) {
// Open the file and check, if it is open
if (std::ifstream sourceFile(fileName); sourceFile) {
// Read the number of rows and columns of the matrix
if (size_t numberOfColumns, numberOfRows; sourceFile >> numberOfColumns >> numberOfRows) {
// Create a matrix with the given number of rows and columns
std::vector<std::vector<int>> result(numberOfRows, std::vector<int>(numberOfColumns, 0));
// Read data from the input stream and put it into the matrix
for (size_t i = 0; i < numberOfRows; ++i) {
std::copy_n(std::istream_iterator<int>(sourceFile), numberOfColumns, result[i].begin());
}
// Print result. Go through all lines and then copy line elements to std::cout
std::for_each(result.begin(), result.end(), [](std::vector<int>& c) {
std::copy(c.begin(), c.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << "\n"; });
}
}
else {
std::cerr << "\n*** Error: Could not open source File\n\n";
}
}
return 0;
}
Most of the components for the array are in place.
I am however wondering what code is missing for the output to match what I am trying to do.
I tried searching for similar array coding. I would like to call the function and for the user to input numbers up to 20 different inputs.
#define size 20
using namespace std;
int i;
void Input(int student[]) {
for(int i = 0; i < size; i++)
cout << "Enter The Marks of Subject 2 of student no " << i + 1 << " ";
cin >> student[i];
}
void display(int student[]) {
for(int i = 0; i < size; i++)
cout << student[i];
}
int main() {
int student[size];
Input(student );
display(student);
return 0;
In your Input function:
void Input(int student[]) {
for(int i = 0; i < size; i++)
cout << "Enter The Marks of Subject 2 of student no " << i + 1 << " ";
cin >> student[i];
}
You not using brackets, so the cin >> student[i]; is outside of the loop. The i from the for loop is no longer in scope, so you are using the i here:
int i;
Which is never given a value, which leads to undefined behavior. Add brackets:
void Input(int student[]) {
for(int i = 0; i < size; i++) {
cout << "Enter The Marks of Subject 2 of student no " << i + 1 << " ";
cin >> student[i];
}
}
So I have a program that reads in a certain number of keys. An example would be
5 1 10 21 9 6 21 11 13 16 20
The text file example would be
Java 2 linux 3 fear 0 pool 2 do 0 red 1 lock. 1 I 0 random 2
I want my program to start at Java and depending on first key, which in this case is 5, would move over 5 elements leading to "red". And so on and so on. However, I have managed to read in all the data and put them into arrays, I am just having trouble figuring out how to move the pointer in the array.
Code:
#include <iostream>
#include <fstream>
using namespace std;
struct pieces {
char word[5];
int jump;
} ;
// Main Function
int main ()
{
// declare variables
int wordCount[2];
int keyCount[2];
int numKeys, numKeys2;
int numWords;
int keyAmount = 1;
int wordAmount = 23;
int keyarr[11];
pieces cypher[wordAmount];
char filename[10];
ifstream inData;
int temp[10];
//prompt user for input file
cout << " Enter file name: ";
cin >> filename;
inData.open(filename);
if(inData.is_open());
{
// read in data
for ( numKeys = numWords = 0; numKeys < keyAmount; numKeys++){
// read in num of words and keys
inData >> wordCount[numKeys] >> keyCount[numKeys];
//read in words followed by jump key
for( numWords = 0; numWords < wordAmount; numWords++){
inData >> cypher[numWords].word >> cypher[numWords].jump;
}
// read in the actual keys
for( numKeys2 = 0; numKeys2 < wordCount[numKeys]; numKeys2++){
inData >> keyarr[numKeys2];
}
}
//print out data
for( int j = 0; j < numKeys; j++){
cout << wordCount[j] << "\n";
cout << keyCount[j] << "\n";
}
cout << "\n";
for ( int i = 0; i < wordAmount; ++i){
cout << cypher[i].word << " ";
cout << cypher[i].jump << " ";
}
cout << "\nKeys: " << "\n";
for(int k = 0; k < 11; k++){
cout << keyarr[k] << " ";
}
cout << "\n";
}
inData.close();
return 0;
}
I'm trying to create a program that reads in numbers from a file into an array, reverse the order of the numbers in the array and then outputs those reversed numbers into a different file. I was able to get the program to work when I already knew how many numbers were in the file but I am having difficulty when I switch my loop to trying to detect the EOF(End of file). When I run this code it will print two of the numbers from the file and the rest are garbage values. Any Help?
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
const int NUMS = 5;
void reverseArray(int number[], int first, int last)
{
int temp;
if (first >= last)
{
return;
}
temp = number[first];
number[first] = number[last];
number[last] = temp;
reverseArray(number, first + 1, last - 1);
}
int main()
{
//Create file objects
ifstream inputFile;
ofstream outputFile;
string inputName;
string outputName;
//Prompt user for file names
cout << "What is the name of the input file?" << endl;
getline(cin, inputName);
cout << "What would you like the output file to be called?" << endl;
getline(cin, outputName);
//open user named files
inputFile.open(inputName);
outputFile.open(outputName);
int numsFromFile;
int numbers[NUMS];
int fileCount = 0;
/*
//read in numbers from a file ********THIS WORKS BUT WHEN I CHANGE IT BELOW IT DOES NOT******
for (int count = 0; count < NUMS; count++)
{
inputFile >> number[count];
}
*/
//Try to read numbers in detecting the EOF
while (inputFile >> numsFromFile)
{
inputFile >> numbers[fileCount];
fileCount++;
}
//print numbers to screen
for (int count = 0; count < fileCount; count++)
{
cout << numbers[count] << endl;
}
//reverse array
reverseArray(numbers, 0, 4);
cout << "Reversed is: " << endl;
//print reversed array
for (int count = 0; count < NUMS; count++)
{
cout << numbers[count] << endl;
}
//output numbers to a file
for (int count = 0; count < NUMS; count++)
{
outputFile << numbers[count] << endl;
}
outputFile.close();
inputFile.close();
return 0;
}
There is a bug in the lines:
while (inputFile >> numsFromFile)
{
inputFile >> numbers[fileCount];
fileCount++;
}
You end up reading and discarding the 1st number, the 3rd number, the 5th number, etc. Change it to:
while (inputFile >> numsFromFile)
{
numbers[fileCount] = numsFromFile;
fileCount++;
}
I've just completed a program which does as follows:
You have t[10][5] and p[10] arrays.
You read dimT and dimP.
You write dimT values in t[][] and dimP values in p[].
For writing values in t[][], you have to fill lines before. The output must be the column which has highest number of matches for the p[] array.
Example:
INPUT -> 14 (dimT) 2 (dimP) 0 1 2 3 4 0 2 7 9 1 0 11 12 0 (t[][]) 0 0 (p[])
So the final matrix display is:
0 1 2 3 4
0 2 7 9 1
0 11 12 0
OUTPUT -> The best matching column is 0 with 2 matches (overlap counted).
I created this program using arrays but it's really horrible, so I'm looking for a better and cleaner solution from some experts possibly, using vectors instead of simple arrays.
Here is my current code. It would be better if I had split it into a function or two more, but it is shorter this way:
#include <iostream>
#include <vector>
using namespace std;
bool IsMatch(vector<double>& col, vector<double>& p, int n)
{
for (size_t i=0; i<p.size() ;i++)
if (col[i+n]!=p[i])
return false;
return true;
}
int main()
{
int dimT;
int dimP;
cin >> dimT;
cin >> dimP;
int lineN = (dimT+5-1)/5;
vector<vector<double> > t(lineN,vector<double>(5));
vector<vector<double> > tTran(5,vector<double>());
vector<double> p(dimP);
t[lineN-1].resize(dimT%5);
//input matrices
for (int i=0; i<dimT;i++) {
double inputVal;
cin >> inputVal;
tTran[i%5].push_back(inputVal);
t[i/5][i%5]=inputVal;
}
for (int i=0; i<dimP;i++)
cin >> p[i];
//print it out
for (int line=0; line<lineN; line++){
for (size_t j=0; j<t[line].size(); j++)
cout << t[line][j] << " ";
cout << endl;
}
//transpose t
/*vector<vector<double> > tTran(5,vector<double>());
for (int line=0; line<lineN; line++)
for (size_t j=0; j<t[line].size(); j++)
tTran[j].push_back(t[line][j]);
//output tTran
for (int line=0; line<5; line++){
for (size_t j=0; j<tTran[line].size(); j++)
cout << tTran[line][j] << " ";
cout << endl;
}
*/
int maxCol=0;
int maxMatchN=0;
for (int col=0; col<5; col++){
int matchN=0;
for (size_t j=0; j<tTran[col].size()-p.size()+1; j++)
if (IsMatch(tTran[col],p,j) )
matchN++;
if (matchN>maxMatchN){
maxMatchN = matchN;
maxCol = col;
}
}
cout << "The best matching column is " << maxCol
<< " with " << maxMatchN << " matches (overlap counted)." << endl;
}
Here is the simpler (all transposed) version I was suggesting in the comments: The point I'm trying to show is that the non transposed copy has no value. You understood it is easier to transpose during input than later. But you kept the non transposed copy as well, and did the output from the non transposed copy and processing from transposed copy.
Take a look at all the extra nonsense that can be skipped if you don't have a non transposed copy. Then compare the output loop directly from the transposed copy to the original output loop. The change to the output loop was trivial and the benefit significant.
int main()
{
int dimT;
int dimP;
cin >> dimT;
cin >> dimP;
vector<double> t[5+1]; // +1 because empty guard vector makes output loop simpler
vector<double> p(dimP);
//input matrices
for (int i=0; i<dimT;i++) {
double inputVal;
cin >> inputVal;
t[i%5].push_back(inputVal);
}
for (int i=0; i<dimP;i++)
cin >> p[i];
//print it out
for (size_t line=0; line<t[0].size(); line++){
for (size_t j=0; line<t[j].size(); j++)
cout << t[j][line] << " ";
cout << endl;
}
int maxCol=0;
int maxMatchN=0;
for (int col=0; col<5; col++){
int matchN=0;
for (size_t j=0; j<t[col].size()-p.size()+1; j++)
if (IsMatch(t[col],p,j) )
matchN++;
if (matchN>maxMatchN){
maxMatchN = matchN;
maxCol = col;
}
}
cout << "The best matching column is " << maxCol
<< " with " << maxMatchN << " matches (overlap counted)." << endl;
}
That empty "guard" vector is a useful trick to know and in more complicated problems avoids a lot of detail and likely mistakes. In this code it just saved needing j<5 && in one spot.