Separate integers in a file by tabs into an array - c++

Honestly, its a file of 200k integers and have no idea how to error check if the way I am doing it is correct so I'd like some help! There are 10 integers per line and 20k lines total.
Here's my code:
void readFile(int searchValues[VALUES], string fileName, string fileExtension, string filePath){
string fileLine;
ifstream myFile (fileName + fileExtension);
int currentIndex = 0;
if (myFile.is_open()){
while (getline(myFile,fileLine)){
for (int i = 0; i < 10; i++){
searchValues[currentIndex] = stoi(fileLine.substr(0, fileLine.find('\t')));
fileLine = fileLine.substr(fileLine.find('\t') + 1, fileLine.length()-1);
currentIndex++;
}
}
}
}

Here is a working example for 3 integers ... do the same for 10.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
FILE *fl=fopen(argv[1],"rt");
int a,b,c,line=0;
while (3 == fscanf(fl,"%d\t%d\t%d",&a,&b,&c))
{
printf(
"line %d contains ints: %d %d %d\n",
line++,
a,
b,
c);
}
fclose(fl);
}

I'm not sure what is the use of VALUES. Also if you're gonna put all the 200k values inside a single array, then why reading only 10 values? I assume you're gonna put each 10 values in a seperate array for example? Anyways, here is a code that reads VALUES amount of integers and stores them in an array. Also note that the parameter filePath is not used
input.txt:
0 1 2 3 4 5 6 7 8 9
#include <iostream>
#include <string>
#include <fstream>
const int VALUES = 10;
void readFile(int searchValues[VALUES], std::string fileName, std::string fileExtension, std::string filePath){
if (!filePath.empty() && filePath.back() != '/')
filePath.push_back('/');
std::string fullPath = filePath + fileName + '.' + fileExtension;
std::ifstream input(fullPath);
if (input.is_open())
{
int i = 0;
while (i < VALUES && input >> searchValues[i]) i++;
}
}
int main()
{
int arr[VALUES];
readFile(arr, "input", "txt", "");
for (int i : arr)
std::cout << i << ' ';
}
Output:
0 1 2 3 4 5 6 7 8 9

Related

Read line of numeric data into an array, then read next line into a variable. C++

I am pretty new to coding so I am sure this is a stupid question. For a class I need to code an algorithm that determines the least amount of change to make some amount of money in C++.
This code needs to read numbers from a txt file so that the first line is the coin types (aka 1 cent, 2 cents, 4 cents, etc.). The second line is the total number that I want sorted into change. Then third line is a new set of coin types and the fourth line is a new total. The general pattern continues.
The txt file looks like -
1 2 5
10
1 3 7 12
29
1 2 4 8
15
1 7 11
14
I easily created the change algorithm myself, I am having problems getting the first line to be read into an array and then the next line to be read into a variable.
My code for the coinChange algorithm.
int coinChange(int coins[], int total, int size)
{
//Set high minimum
int min = 999999999;
//For all of the coins, see if it equals the value of total
for (int i = 0; i < size; i++) {
if (coins[i] == total) {
//If so return 1
return 1;
}
}
//Loop through
for (int j = 1; j <= total / 2; j++) {
if ((coinChange(coins, j, size) + coinChange(coins, total - j, size)) < min) {
min = coinChange(coins, j, size) + coinChange(coins, total - j, size);
}
}
return min;
}
I have tried using fgets and fscanf with no success so any advice would be very helpful.
If you use c++ as tadman commented already you can use something like that:
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
int main()
{
std::stringstream ss("1 2 5\n10\n1 3 7 12\n29\n");
std::string line;
while(std::getline(ss, line))
{
std::stringstream lines(line);
std::vector<int> values;
std::string string_value;
while(std::getline(lines, string_value, ' '))
values.push_back(std::stoi(string_value));
std::getline(ss, line);
int value = std::stoi(line);
std::cout << "got: ";
for(const auto& v : values) std::cout << v << ", ";
std::cout << value << std::endl;
}
return 0;
}
Try it here http://cpp.sh/33bmy .
This reads a complete line and splits the coin types apart using a std::istringstream. The total amount on the next line is extracted the usual way.
I changed your function signature to take a std::vector and an int. Most of your code should remain the same if you replace your use of size with coins.size().
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
int coinChange(const std::vector<int> &coins, int total)
{
// Set high minimum
int min = 999999999;
//
// Your code here. Don't need a size parameter, use coins.size() instead
//
return min;
}
int main()
{
std::vector<int> coins;
int total;
std::string line;
while (std::getline(std::cin >> std::ws, line) && std::cin >> total) {
std::istringstream iss(line);
for (int coin; iss >> coin; ) {
coins.push_back(coin);
}
coinChange(coins, total);
coins.clear(); // reset vector before the next inputs
}
}
Note: the use of std::ws inside the std::getline call is there to consume any leftover whitespace or newline from a previous input.

Formatting files - C++

I have hit a brick wall trying to format one of my files. I have a file that I have formatted to look like this:
0 1 2 3 4 5
0.047224 0.184679 -0.039316 -0.008939 -0.042705 -0.014458
-0.032791 -0.039254 0.075326 -0.000667 -0.002406 -0.010696
-0.020048 -0.008680 -0.000918 0.302428 -0.127547 -0.049475
...
6 7 8 9 10 11
[numbers as above]
12 13 14 15 16 17
[numbers as above]
...
Each block of numbers has exactly the same number of lines. What I am trying to do is basically move every block (including the headers) to the right of the first block so in the end my output file would look like this:
0 1 2 3 4 5 6 7 8 9 10 11 ...
0.047224 0.184679 -0.039316 -0.008939 -0.042705 -0.014458 [numbers] ...
-0.032791 -0.039254 0.075326 -0.000667 -0.002406 -0.010696 [numbers] ...
-0.020048 -0.008680 -0.000918 0.302428 -0.127547 -0.049475 [numbers] ...
...
So in the end I should basically get a nxn matrix (only considering the numbers). I already have a python/bash hybrid script that can format this file
exactly like this BUT I've switched the running of my code from Linux to Windows and hence cannot use the bash part of the script anymore (since my code has to be compliant will all versions of Windows). To be honest I have no idea how to do it so any help would be appreciated!
Here's what I tried until now (it's completely wrong I know but maybe I can build on it...):
void finalFormatFile()
{
ifstream finalFormat;
ofstream finalFile;
string fileLine = "";
stringstream newLine;
finalFormat.open("xxx.txt");
finalFile.open("yyy.txt");
int countLines = 0;
while (!finalFormat.eof())
{
countLines++;
if (countLines % (nAtoms*3) == 0)
{
getline(finalFormat, fileLine);
newLine << fileLine;
finalFile << newLine.str() << endl;
}
else getline(finalFormat, fileLine);
}
finalFormat.close();
finalFile.close();
}
For such a task, I would do it the simple way. As we already know the number of lines and we know the pattern, I would simply keep a vector of strings (one entry per line of the final file) that I would update as I'm parsing the input file. Once it's done, I would iterate through my strings to print them into the final file. Here is a code that's doing it :
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
int main(int argc, char * argv[])
{
int n = 6; // n = 3 * nAtoms
std::ifstream in("test.txt");
std::ofstream out("test_out.txt");
std::vector<std::string> lines(n + 1);
std::string line("");
int cnt = 0;
// Reading the input file
while(getline(in, line))
{
lines[cnt] = lines[cnt] + " " + line;
cnt = (cnt + 1) % (n + 1);
}
// Writing the output file
for(unsigned int i = 0; i < lines.size(); i ++)
{
out << lines[i] << std::endl;
}
in.close();
out.close();
return 0;
}
Note that, depending of the structure of your input/ouput files, you might want to adjust the line lines[cnt] = lines[cnt] + " " + line in order to separate the columns with the right delimiter.

Algorithm for TSP giving incorrect output

I've spent a few hours trying to figure out what's wrong with my program, but I can't figure it out. This is a minimum tour cost program. (TSP)
c is for city and a is for arc(cost for travel between 2 cities)
Inputs I'm using to test:
c 1
c 2
c 3
c 4
c 5
a 1 2 1400
a 1 3 1800
a 1 4 4000
a 1 5 3500
a 2 3 1200
a 2 4 3400
a 2 5 3600
a 3 4 2300
a 3 5 2700
a 4 5 2100
And here is my code. The above inputs should give 10500 minTour, but its showing 5600.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cassert>
#include <sstream>
#include <cstdlib>
#include <string>
#include <stdint.h>
using namespace std;
static char gFirstCity = 0;
static unsigned graph[50][50] = {0};
static unsigned minTour = 0xffffffff;
void swap (char *x, char *y)
{
char temp;
temp = *x;
*x = *y;
*y = temp;
}
void permute(char* cities, unsigned start, unsigned length)
{
if (start == (length-1))
{
cout << endl;
unsigned cost =0;
cost+= graph[(unsigned)gFirstCity][(unsigned)*cities];
for(unsigned i = 0; i < length-1; i++ )
{
cost+=graph[(unsigned)cities[i]][(unsigned)cities[i+1]];
for(int i = 0; i < length; i++){
cout << (int)cities[i];
}
}
cost+=graph[(unsigned)cities[length-1]][(unsigned)gFirstCity];
for(int i = 0; i < length; i++){
cout << (int)cities[i];
}
if(cost<minTour){
minTour = cost;
}
}
else
{
for (unsigned j = start; j < length; j++)
{
swap((cities + start), (cities + j));
permute(cities, start + 1, length);
swap((cities + start), (cities + j));
}
}
}
int main()
{
string cities;
string line;
char command = 0;
unsigned city = 0;
while (getline(cin, line))
{
sscanf(line.c_str(), "%c %d", &command, &city);
if (command != 'c')
break;
cities.push_back((unsigned char)city);
}
gFirstCity = cities[0];
unsigned to = 0;
unsigned from = 0;
uint32_t cost = 0;
sscanf(line.c_str(), "%c %d %d %d", &command, &to, &from, &cost);
graph[to-1][from-1]=cost;
graph[from-1][to-1]=cost;
while (getline(cin, line))
{
sscanf(line.c_str(), "%c %d %d %d", &command, &to, &from, &cost);
graph[to-1][from-1]=cost;
graph[from-1][to-1]=cost;
}
permute((char*)cities.c_str()+1, 0, cities.length()-1);
cout << minTour << endl;
return EXIT_SUCCESS;
After adding a bit of debugging output to the code, the biggest problem appears to be that your algorithm mixes array indexes and cities inconsistently.
For example, your gStartCity is used as an array index (0-based), but is actually a city number (1-based).
You use array indexes 1-5 when actually obtaining costs, but you assign the costs to array indexes 0-4.
I believe you can get the expected result by changing both sets of graph[][] assignments to:
graph[to][from]=cost;
graph[from][to]=cost;
The definition of graph[][] will allow this without overwriting something else, and you won't live long enough for this algorithm to compute the optimal path for 49 cities, so the difference won't matter (49 cities would require about 6E+62 possible paths; even if you could check a million paths per second, this would only take about 20,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000 years to compute).
Your code is very difficult to read and follow, so I'm not sure how best to fix the fundamental problem that you are off by 1 on most of your array indices, but at least this should get it running closer to the way you expect.

How to merge two files if the buffer size is smaller than the size of the file?

How to merge two files if the buffer size is smaller than the size of the file?
For example, I have two files with sorted integers
1.txt and 2.txt
2 1
5 7
6 8
7 9
I have to merge them in one sorted file but I can't read more than two numbers from each file(that's the task). And I cant have more than 4 numbers in memory at the same time.
Here is my code
#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;
const int bufferSize = 2;
bool readSortFile(ifstream &file, vector<int> &data) {
int tmp;
for (int i = 0; (i < bufferSize && file >> tmp); i++)
data.push_back(tmp);
return file.good();
}
int main() {
ifstream file1("1.txt");
ifstream file2("2.txt");
ofstream out;
vector<int> data1, data2;
bool fileGood1, fileGood2;
fileGood1 = true;
fileGood2 = true;
while(fileGood1 || fileGood2) {
if(data1.size() == 0)
fileGood1 = readSortFile(file1, data1);
if (data2.size() == 0)
fileGood2 = readSortFile(file2, data2);
out.open("temp", ios::app);
merge(data1.begin(),
data1.end(),
data2.begin(),
data2.end(),
ostream_iterator<int>(out, "\n"));
data1.clear();
data2.clear();
out.close();
}
rename("temp", "result.txt");
file1.close();
file2.close();
return 0;
}
The output is 1 2 5 7 6 7 8 9
As mentioned in the comment, you only need 1 number from each file to implement a merge, but you'll probably need to write your own merge logic as opposed to using std::merge. Example pseudo code, you'll need to add eof checks (if end of 1.txt, copy rest of 2.txt and vice versa).
num1 = get number from "1.txt"
num2 = get number from "2.txt"
loop(...){
if(num1 <= num2){
write num1
num1 = get number from "1.txt"
} else {
write num2
num2 = get number from "2.txt"
}
}

Reversing an input from a file (C++)

I'm creating a very basic program that reads in a list of numbers from a text file, prints them in reverse order, then states if that order is the same as the original (like a palendrome).
I have the program able to print in reverse order so far, but I'm not sure how detect if it's the same as the original file. Any help would be greatly appreciated :)
EDIT: Sorry, had to go away. Here's what I have so far. Got it to reverse, just need to check for palindrome. Will read over replies.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
const int ARRYLENGTH=20;
int contnums[ARRYLENGTH];
int contents;
ifstream myFile("problem3.txt");
if(! myFile )
{
cout << "File cannot be found";
exit(EXIT_FAILURE);
}
while(!myFile.eof())
{
myFile>>contents;
for(int i=0;i<ARRYLENGTH;i++)
{
myFile >> contnums[i];
}
}
cout<<contents<<" ";
for (int i = 1; i < ARRYLENGTH; i++)
{
bool same = false;
for (int j = 0; j < i && (same == false); j++){
if (contnums[i] == contnums[j])
same = true;
}
if (!same) {
cout<< contnums[i] << " ";
}
}
cout << "\n";
system("pause");
myFile.close();
}
I just wondered wether comparing 2 lists would work in std library. It works :-)
#include <list>
#include <fstream>
using std::list;
using std::ifstream;
bool foo(const char * fn)
{
list<int> orig;
list<int> rev;
ifstream ifs(fn,std::ifstream::in);
while( ifs.good() && !ifs.eof() )
{
int num =0;
ifs >> num;
orig.push_back(num);
rev.push_front(num);
}
bool equal = (orig == rev);
return equal;
}
static bool test1 = foo("file1.txt");
static bool test2 = foo("file2.txt");
WHERE
file1.txt contains
1 2 3 4 5 6 7 8 9 0 9 8 7 6 5 4 3 2 1 8
and file2.txt contains
1 2 3 4 5 6 7 8 9 0 9 8 7 6 5 4 3 2 1
Try iterating from begin to end and comparing the values with values of an iterator from end to begin.
If you know how many items you have it could simple be done by:
for(int i = 0; i < count/2; ++i) { //count/2 becouse you only have to check half
if(array[i] != array[count-i-1]) { /*not palindrome */ }
}
//palindrome
Simplest way, but i like #Dave's from comment one better since it ueses STL and iterators in nice way. (As long as you are working on STL container).