So I need to read a grid from a file,the grid's width and lengths is always the same.The problem is when I try to cout it on the last line it only shows about a half of it.
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
ifstream TestIn("test");
int main()
{
char Grid[1000][1000],s[1000];
int LungimeX,LungimeY,i,j;
TestIn.getline(s,1000);
//finding the length
LungimeX=strlen(s);
cout<<LungimeX<<endl;
//finding the width
while (!TestIn.eof()) {
TestIn.getline(s,1000);
LungimeY++;
}
cout<<LungimeY;
//reset .eof
TestIn.clear();
TestIn.seekg(0, TestIn.beg);
//get the grid into the array
for(i=1;i<=LungimeY;i++) {
for(j=1;j<=LungimeX;j++) {
TestIn.get(Grid[i][j]);
}}
for(i=1;i<=LungimeY;i++){
for(j=1;j<=LungimeX;j++){
cout<<Grid[i][j];
}}
return 0;
}
So yeah,any ideas how to fix this?
LungimeY isn't initialized
Need to read (to skip) the header line after the file rewind
Need to skip CR and/or LF characters after each line read when filling the array
You were not ignoring the newline character LungimeX is the length of the line not including the new line character. a simple solution could be when reading the file if newline character is encountered read the next character.
#include
#include
#include
using namespace std;
ifstream TestIn("test");
int main()
{
char Grid[1000][1000],s[1000];
int LungimeX,LungimeY,i,j;
TestIn.getline(s,1000);
//finding the length
LungimeX=strlen(s);
cout<<LungimeX<<endl;
//finding the width
while (!TestIn.eof()) {
TestIn.getline(s,1000);
LungimeY++;}
cout<<LungimeY;
//reset .eof
TestIn.clear();
TestIn.seekg (0, TestIn.beg);
//get the grid into the array
for(i=1;i<=LungimeY;i++){
for(j=1;j<=LungimeX;j++){
TestIn.get(Grid[i][j]);
if(Grid[i][j] == '\n') //check new line character
TestIn.get(Grid[i][j]);
}}
for(i=1;i<=LungimeY;i++){
for(j=1;j<=LungimeX;j++){
cout<<Grid[i][j];
}
cout<<endl;
}
return 0;
}
And yes Please use 0 indexing in C++ you are wasting memory this way.
What about this kind of more C++ approach ?
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::string fname("test.txt");
std::ifstream f(fname.c_str());
std::vector<std::string> lines;
std::string line;
while(std::getline(f, line))
lines.push_back(line);
unsigned long int num_rows = lines.size();
unsigned long int num_cols = 0;
if(num_rows > 0)
num_cols = lines[0].length();
std::cout << "num_rows = " << num_rows << std::endl;
std::cout << "num_cols = " << num_cols << std::endl;
for(unsigned long int i = 0; i < num_rows; ++i)
{
for(unsigned long int j = 0; j < num_cols; ++j)
std::cout << lines[i][j];
std::cout << std::endl;
}
return 0;
}
Related
Say the strings is "Asah1234&^%736hsi)(91",
than storage 1234,736,91 in three arrays
In general,i want to put each continuous nums in each array.
Queations: how many arrays i will need,what's the size of each group of numbers,how to make the loop.
I want to write a fuction to do it.
#include<iostream>
using namespace std;
void splitString(string str)
{
string num;
for (int i = 0; i < str.length(); i++)
{
if (isdigit(str[i]))
num.push_back(str[i]);
}
cout << num << endl;
}
int countnum( string str)
{
string num;
int sum = 0;
for (int i = 0; i < str.length(); i++)
{
if (isdigit(str[i]))
sum++;
}
cout << sum << endl;
return 0;
}
int main()
{
const int MAXLEN = 100;
char str[MAXLEN];
printf("please enter strings:");
scanf_s("%s", str, MAXLEN);
splitString(str);
countnum( str);
return 0;
}
Maybe I have a misunderstanding here. Then please comment and I will delete the answer.
This is a standard task and will be solved with a regex. It is just the definition of a variable and initialzing this variable with its range constructor. So, a one-liner.
There is no further statement needed.
Please see:
#include <iostream>
#include <string>
#include <regex>
#include <vector>
std::regex re{ R"(\d+)" };
int main() {
// The input string with test data
std::string test{"Asah123&^%736hsi)(918"};
// Define a variable numbers and use the range constructor to put all data in it
std::vector numbers(std::sregex_token_iterator(test.begin(), test.end(), re), {});
// Show the result on the screen
for (const auto& n : numbers) std::cout << n << "\n";
return 0;
}
For a project I am currently working on, I have to read from a file and depending on the certain character in the file, output either a 1 or 0 to an array.
So here is an example of file input:
* * *
* * *
** ** **
*** *
And here is the function I have written to handle this:
void input (int cellGrid[][MAX]) //takes info from a .txt and puts it into an array
{
ifstream infile; //declare a file variable
int row;
int column;
int number;
infile.open("life.txt"); //open a file
while(infile>>row>>column) { //inserts bacteria places into array
cout << row << " " << column << endl;
cellGrid[row][column]=1; //makes it equal one if bacteria is present
}
infile.close(); //closes file
}
My thinking was that the function needs to see if there is a character that exists and if so, place a 1 in its respective position ([row][column]) in the array. However with this current code, nothing is input into my array.
Generally in C++ use std::vector wherever possible.
Array example:
You have to go through the file and record position of each *. Then set it to 1 for that position. Something like the following (we use getline and i as counter for rows, then we loop through the line using j as counter for columns):
#include <fstream>
#include <string>
using namespace std;
void input(int cellGrid[][100]) {
ifstream infile;
infile.open("life.txt");
int i = 0;
for (string line; getline(infile, line); ++i)
{
for (size_t j = 0; j < line.size(); ++j) {
if (line[j] == '*') {
cellGrid[i][j] = 1;
}
}
}
infile.close();
}
Vector example #1:
Here you can find a solution using std::vector. It will be always in a size rows x columns. One thing it requires is to pass default constructed vector and not constructed with vector(size_type count); c-tor. You can write your own version that doesn't have this problem:
#include <fstream>
#include <string>
#include <vector>
using namespace std;
void input(vector<vector<int>> &cellGrid) {
ifstream infile;
infile.open("life.txt");
int i = 0;
for (string line; getline(infile, line); ++i)
{
cellGrid.push_back(vector<int>(line.size()));
for (size_t j = 0; j < line.size(); ++j) {
if (line[j] == '*') {
cellGrid[i][j] = 1;
}
}
}
infile.close();
}
int main() {
vector<vector<int>> cellGrid;
vector<vector<int>> cellGrid2(100);
input(cellGrid);
//input(cellGrid2); - THIS WILL THROW AN EXCEPTION
return 0;
}
Vector example #2:
It would be even better for you function to return a newly created and populated vector:
#include <fstream>
#include <string>
#include <vector>
using namespace std;
vector<vector<int>> input() {
ifstream infile;
infile.open("life.txt");
vector<vector<int>> cell_grid;
int i = 0;
for (string line; getline(infile, line); ++i)
{
cell_grid.push_back(vector<int>(line.size()));
for (size_t j = 0; j < line.size(); ++j) {
if (line[j] == '*') {
cell_grid[i][j] = 1;
}
}
}
infile.close();
return cell_grid;
}
int main() {
auto vec = input();
return 0;
}
My thinking goes like this:
set row to 0
while can read a line from file
set column to 0
for each character on line
if character is '*'
set cellGrid(row,column) to 1
else
set cellGrid(row,column) to 0
increment column
increment row
You may want additional logic to trap row or column trying to go out of bounds or characters that aren't ' ' or '*'.
I am a new in C++ and have difficulties in importing specific data (numbers) from the file.
My input looks like:
Open High Low Close
1.11476 1.11709 1.10426 1.10533
1.10532 1.11212 1.10321 1.10836
1.10834 1.11177 1.10649 1.11139
1.09946 1.10955 1.09691 1.10556
1.10757 1.11254 1.09914 1.10361
1.10359 1.12162 1.10301 1.11595
1.09995 1.10851 1.09652 1.10097
I use the following code which works fine for me to read the second column entirely, however I need to read specific data only. For example the third row/ third column which is 1.10649How can I read specific data? Do I need to use the string to get the row/column and then convert it to int in order to read it in a vector? I am open for any suggestions and would be greatly appreciated if any could help me with this issue.
// Data import 2nd Column
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <vector>
using namespace std;
int main()
{
const int columns = 4;
vector< vector <double> > data;
ifstream market_data("market_data.txt");
if (market_data.is_open()) {
double num;
vector <double> line;
while (market_data >> num) {
line.push_back(num);
if (line.size() == columns) {
data.push_back(line);
line.clear();
}
}
}
vector <double> column;
double col = 2;
for (double i = 0; i < data.size(); ++i) {
column.push_back(data[i][col - 1]);
cout << column[i] << endl;
}
system ("pause");
return 0;
}
You need to use a integer value for indexing (size_t to be precise), change
for (double i = 0; i < data.size(); ++i) {
to
for( size_t i = 0; i < data.size(); ++i) {
// ^^^^^^
Otherwise everything seems fine from your code sample.
If your numbers will always contain 7 characters (i assume it's not binary file), then you could make this simple.
Use seekg() method of ifstream.
Each number fills 10 characters (7 of number, 3 spaces). So, if you have table ROWS x COLUMNS, then to get specific number, you can do this:
const int ROW_LEN = 4
const int DATA_LEN = 10
...
int row,column;
double num;
std::cin >> row; //assume first row is 0
std::cin >> column //assume first column is 0
marked_data.seekg((column*ROW_LEN + row)*DATA_LEN);
marked_data >> num // here is your number
Thank you for replies.. I have solved the issue. So instead of:
vector <double> column;
double col = 2;
for (double i = 0; i < data.size(); ++i) {
column.push_back(data[i][col - 1]);
cout << column[i] << endl;
}
enough to write:
cout << data[2][2] << endl;
I need to traverse a file in a vertical manner. If suppose the file contents are:
adg
beh
cfi
It should print the file as:
abc
def
ghi
The length for each line will be same(i.e. all lines will be of length 3 for above example). I have written a code but it doesn't traverse the file as required.
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main()
{
fstream fs;
fs.open("asd.txt",ios::in);
string str;
char *ch = new char();
int lineLen = 0, k = 0;
if(getline(fs,str))
{
lineLen = str.length();
}
fs.seekg(0);
if(lineLen > 0)
{
for(int i = 0;i<lineLen;i++)
{
fs.seekg(i+k*lineLen);
while(fs.read(ch,1))
{
k++;
fs.seekg(i+k*lineLen);
cout<<*ch;
}
k = 0;
}
}
fs.close();
cin.ignore();
}
I am a bit new to file handling and couldn't find the mistake. Also, is there a better approach for this to be followed?
Pretty much your way with some little tweaks
//lines = no. of lines in file
fs.seekg(0, fs.beg);
fs.clear();
if(lineLen > 0)
{
for(int k = 0; k < lineLen; k++) {
for(int i = 0;i<lines;i++){
fs.seekg(k+i * (lineLen + 2), fs.beg); //use lines + 2
if(fs.read (ch,1));
cout << *ch;
}
cout << endl;
}
Untested pseudo-code that may give you some ideas. Basically, load the whole file into a 2d vector of characters for easy access. It will use more memory than reading directly from the file but this won't matter unless the file is very big.
vector<vector<char>> filemap;
string line;
while (getline(filestream, line))
{
filemap.push_back(vector<char>(line.begin(), line.end()));
}
for (int x = 0; x < XSIZE; x++)
{
for (int y = 0; y < YSIZE; y++)
{
filestream << filemap[y][x]; // note x/y are opposite way round in 2d vectors
}
filestream << '\n';
}
You might find this task much simpler if you were to use mmap(2). There may be a C++ equivalent or wrapper, but I'm afraid I'm not much of an expert on that front. Hopefully someone will come along with a better answer if that's the case.
Here's a quick C (not ++) example. I'll see if I can google around and C++ify it some more:
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
int main(void)
{
int fd = open("input", O_RDONLY);
struct stat s;
fstat(fd, &s);
// map the file as one big string
char *c = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0);
// calculate sizes
int columns = strchr(c, '\n') - c; // first newline delimits a row
int stride = columns + 1; // count the newline!
int rows = s.st_size / stride; // all rows are the same length
for (int x = 0; x < columns; x++)
{
for (int y = 0; y < rows; y++)
{
putchar(c[y*stride + x]);
}
putchar('\n');
}
munmap(c, s.st_size);
close(fd);
return 0;
}
Edit: A quick search around didn't turn up a much better way to handle this in C++ as far as I could tell. I mean, I can add a typecast on the mmap line and change the putchar calls to std::cout, but that doesn't really seem like it makes any difference.
Instead of trying to seek() repeatedly in the source file it is much easier and faster to simply read in the whole source file then generate output from the in-memory contents.
This sounds an awful like like a class assignment, so I won't simply write the answer for you. However this should point you in the right way -- Some PseodoCode is included
To avoid pain, it should presumably be safe to assume some upper bound on line length and max lines, i.e.,
const int MaxLines = 100;
const int MaxLength = 80;
int lineno, linelength;
// array of char pointers for each line
char *lines[] = (*lines[])malloc(Maxlines * sizeof(char*));
// ReadLoop
lineno = 0;
while (not eof)
{
getline(buffer);
if (++lineno++ == 1)
{
linelength = strlen(buffer);
}
else
{
if (linelength != strlen(buffer))
{
cout "Line # " << lineno << " does not match the expected length";
exit();
}
}
lines[lineno] = malloc(strlen(buffer)+1));
strcpy(lines[lineno], buffer);
}
int cc, linecnt = lineno;
// now all data in memory, output "vertical data"
for (cc = 0; cc < linelength; ++cc)
{
for (lineno=0; lineno<<linelength; ++lineno)
{
cout << lines[xx][yy]; // xx && yy left you to figure out
}
cout "\n";
}
Provided that your file is not enormous, there's no reason not to just slurp the whole thing into memory. There may be a more idiomatic way to do this in C++, but the following works:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
int main(int argc, char *argv[])
{
std::fstream infile("foo.txt");
std::vector<std::string> lines;
std::string line;
while(std::getline(infile,line)) {
lines.push_back(line);
}
int m=lines.size();
int n=lines[0].length();
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
std::cout << lines[j].at(i);
}
std::cout << std::endl;
}
return 0;
}
Problems arise when all the lines in the file are not the same length, of course.
And now, a version that “doesn't use any extra memory” (of course, it does, but not much):
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <algorithm>
int main(int argc, char *argv[])
{
std::fstream infile("foo.txt");
std::vector<std::string> lines;
std::string line;
std::getline(infile, line);
int n = line.length();
int m = 1+std::count(std::istreambuf_iterator<char>(infile),
std::istreambuf_iterator<char>(), '\n');
infile.clear();
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
infile.seekg(j*m+i);
std::cout << char(infile.peek());
}
std::cout << std::endl;
}
return 0;
}
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.