C++ iteration, file i/o - c++

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <stdlib.h>
using namespace std;
int main()
{
//Input .txt file
ifstream inputFile ("input.txt");
try
{
int i = 1; //Line iterator
int vertices = 0;
int faces = 0;
string line;
while (getline(inputFile, line))
{
//Take number from line 4, set as variable "vertices"
if (i == 3)
{
getline (inputFile,line);
size_t last_index = line.find_last_not_of("0123456789");
string str = line.substr(last_index);
vertices = atoi(str.c_str()); //Convert to int
cout << "vertices " + str << endl;
}
//Take number from line 11, set as variable "triangles"
if (i == 11)
{
getline (inputFile,line);
size_t last_index = line.find_last_not_of("0123456789");
string str = line.substr(last_index);
faces = atoi(str.c_str()); //Convert to int
cout << "faces " + str << endl;
}
if (i == 13)
{
i++;
break;
}
cout << "line: " + i << endl; //Prints line number
i++;
}
} catch(const char* error) {
cout << "Cannot read file, please try again." << error;
}
return 0;
}
This program is simply trying to read file, take a number from a couple of lines and for each line print "line: " with respective line number. It looks like C++ iterates differently to Java?
For some reason this program outputs:
*ine:
ne:
vertices 752
e:
:
Cannot read mesh, please try again.
faces r
annot read mesh, please try again.
nnot read mesh, please try again.*
I have no idea why.

This line:
cout << "line: " + i << endl;
should be:
cout << "line: " << i << endl;
Your + is adding i to the string constant "line: ", which has the effect of knocking one character off the front each time round the loop (and eventually going off the end, leading to undefined behaviour).
You can't add objects to strings in C++ in the way you're attempting, but you can send multiple objects to cout by repeated use of <<.
You then have the same problem here:
cout << "vertices " + str << endl;
and here:
cout << "faces " + str << endl;

Related

C++ reading command from .txt file

I want to create a little "calculator" but I dont know how can I create.
My problem is, I have an input file (.txt) with codes:
acc +40
acc -14
nop +386
jmp +262
acc -4
nop +25
...
the "acc" adds the number to my variable
the "jmp" is jump to the line (jmp +500 jump foward 500 line)
the "nop" dont do anything
and here is my code but not working (the acc is okay, but the jmp is not)
ifstream file("my.txt");
string cmd;
int num;
int var= 0;
int i = 0;
if(file.is_open())
{
while (file >> cmd >> num)
{
cout << "Var" << var<< endl;
cout << "Command: " << cmd << " Number: " << num<< " ----" << i <<" // Var: " << var<< endl;
++i;
if(cmd == "acc")
{
var= var+ num;
}
if(cmd == "jmp")
{
;
}
}
file.close();
}else {
cout << "error"<< endl;
cin.get();
}
This is a sample code. I hope everything here is in order. I did what Some programmer dude told you. Using vectors, you read all the lines into them and then just iterate.
#include <fstream>
#include <iostream>
#include <string> //addition
#include <vector> //addition
using namespace std;
int main() {
ifstream file("my.txt");
string cmd;
int num;
int var= 0;
int i = 0;
string my_string;//addition
vector<int> numbers;//addition
vector<string> commands;//addition
if(file.is_open())
{
/*this while function reads every line of the file and writes command to the vector of strings named "commands" and the number to the vector of integers named "numbers".*/
while (getline(file, my_string))//while you can read line from "file", read it and put in into string called "my_string".
{
cmd = my_string;
cmd.resize(3);//leaves only first three characters of the string.
commands.push_back(cmd);//adds this "cmd" string to vector "commands"
my_string.erase(0,4);//erases characters from 0 to 4, inclusive, from the string "my_string". So erases first 4 characters, so our command and the space after.
numbers.push_back(stoi(my_string));//adds my_string, converted to int, to vector "numbers". Stoi() converts string to int.
++i;
}
for(i = 0; i < commands.size(); i++)
{
cout << "Var " << var << endl;
if(commands[i] == "acc")
{
//remember about "+=", it's quicker this way :)
var += numbers[i];
}
cout << "Command: " << commands[i] << " Number: " << numbers[i] << " ----" << i <<" // Var: " << var << endl;
if(commands[i] == "jmp")
{
i+= numbers[i];
}
}
file.close();
}else {
cout << "error"<< endl;
cin.get();
}
}
Sorry in advance for any formatting issues. My first answer on stackoverflow...

C++ How to Check what words aren't in 2 similar files

i was trying to find a way to check two different files and get, from the second, all lines that aren't in the first.. but does all the opposite.
I tried the possible to solve this but nothing...
This is the code:
int main(int argc, char *argv[])
{
setlocale(LC_ALL, "");
char username[UNLEN+1];
DWORD username_len = UNLEN+1;
GetUserName(username, &username_len);
stringstream buffer;
buffer << "C:\\Users\\" << username << "\\Desktop\\";
stringstream buffer2;
buffer2 << "C:\\Users\\" << username << "\\Desktop\\Legit.txt";
stringstream buffer3;
buffer3 << "C:\\Users\\" << username << "\\Desktop\\Unlegit.txt";
stringstream buffer4;
buffer4 << "C:\\Users\\" << username << "\\Desktop\\result.txt";
string results = buffer4.str();
int offset;
int num;
num = 1;
string search;
string linea;
string legit;
string unlegit;
string line;
cout << "Is the Legit.txt file at '" << buffer.str() << "'? [Y/N]: ";
cin >> legit;
if (legit == "Y" || legit == "y"){
}else if(legit == "N" || legit == "n"){
return 0;
}else{
cout << "\n.";
return 0;
}
string legitfile = buffer2.str();
cout << "\nIs the Unlegit.txt file at '" << buffer.str() << "'? [Y/N]: ";
cin >> unlegit;
if (unlegit == "Y" || unlegit == "y"){
}else if(unlegit == "N" || unlegit == "n"){
return 0;
}else{
cout << "\n";
return 0;
}
string unlegitfile = buffer3.str();
ifstream file(legitfile.c_str());
if(file.is_open()){
while(getline(file, line)){
ifstream MyFile(unlegitfile.c_str());
if(MyFile.is_open()){
while(!MyFile.eof()){
getline(MyFile,linea);
if((offset = linea.find(line, 0)) != string::npos) {
cout << "\n[" << num << "]" << " Word Found: " << line << "\n";
num++;
fstream result(results.c_str());
result << line << "\n";
result.close();
}
}
MyFile.close();
}
}
file.close();
return 0;
}else{
cout << "\nThe file '" << legitfile << "' does not exist.";
cout << "\nThe file '" << unlegitfile << "' does not exist.";
}
}
As i said, This code checks which words are equals in both (first & second) files and, once found, writes them to a third file, there is a way to do the opposite (check the two files and get the words that aren't equals)? Thank you so much!
I'm new, both in the forum and in C++, sorry if I make any mistakes. (sorry for my bad english too).
The classic solution to this sort of problem is to use a hash table collection to represent all the words in the first file. Then while iterating items from the second file, consult the set constructed of the first file. In C++, the std::unordered_set will do fine.
#include <unordered_set>
using namespace std;
unordered_set<string> firstFileSet;
unordered_set<string> missingFromSecondFileSet;
string line;
while(!firstfile.eof())
{
getline(firstfile,line);
firstFileSet.insert(line);
}
Then for each word in the second file, use a second set collection to keep track of what words are missing.
while(!secondfile.eof())
{
getline(secondfile,line);
if (firstFileSet.find(line) != firstFileSet.end())
{
missingFromSecondFileSet.insert(line);
}
else
{
firstFileSet.erase(line);
}
}
After the above runs, firstFileSet contains all the lines in the first file that were not present in the second. missingFromSecondFileSet contains all the lines in the second file that were not in the first:
for (auto &s : firstFileSet)
{
cout << s << " was in the first file, but not the second" << endl;
}
for (auto &s : missingFromSecondFileSet)
{
cout << s << " was in the second file, but not the first" << endl;
}
There is a program called diff on linux which does just what you are looking to do in C++.
It is written in C so you can just copy its source code =P
for (;; cmp->file[0].buffered = cmp->file[1].buffered = 0)
{
/* Read a buffer's worth from both files. */
for (f = 0; f < 2; f++)
if (0 <= cmp->file[f].desc)
file_block_read (&cmp->file[f],
buffer_size - cmp->file[f].buffered);
/* If the buffers differ, the files differ. */
if (cmp->file[0].buffered != cmp->file[1].buffered
|| memcmp (cmp->file[0].buffer,
cmp->file[1].buffer,
cmp->file[0].buffered))
{
changes = 1;
break;
}
/* If we reach end of file, the files are the same. */
if (cmp->file[0].buffered != buffer_size)
{
changes = 0;
break;
}
}
Taken from ftp://mirrors.kernel.org/gnu/diffutils/diffutils-3.0.tar.gz > src/analyze.c

How do I replace a specific word within a line in a file?

My Text File:
Name G M S
Cart 1 0 1
Jane 0 1 0
What I have so far:
#include <iostream>
#include <string>
#include <fstream>
#include <stdlib.h>
#include <algorithm>
using namespace std;
void scoreChanger();
string line;
int main()
{
string yn;
int ctr = 0;
ifstream infile;
infile.open("WiiTourney.txt");
if (infile.is_open())
{
cout << "This is your current score table: " << endl;
while(getline(infile, line))
{
ctr++;
cout << line << endl;
cout << ctr << endl;
}
cout << endl;
}
else
{
cout << "Unable to open file" << endl;
}
infile.close();
cout << endl;
cout << "Would you like to change the scores? " << endl;
cin >> yn;
transform(yn.begin(), yn.end(), yn.begin(), ::tolower);
if (yn == "yes")
{
scoreChanger();
}
else
{
infile.close();
return 0;
}
return 0;
}
void scoreChanger()
{
string name;
ofstream outfile;
outfile.open("WiiTourney.txt");
if (outfile.is_open())
{
cout << "Who won the game? " << endl;
cin >> name;
transform(name.begin(), name.end(), name.begin(), ::tolower);
if (name == "jane")
{
while(getline(outfile, line))
{
cout << line << endl;
}
}
for (int x = 0; x < line.length(); x++)
{
if (line[x] == 8 && line[x] != 'G')
{
}
}
}
else
{
cout << "Error opening file. " << endl;
exit(1);
}
}
What I want it to do:
Let's say I wanted to be able to add 1 point to the Games column(G) only for Cart. The problem for me is that I only want to change the 1 in the G column and I know that I would encounter problems by just looping through and searching for instances where 1 comes up because there could be multiple 1's in one line. I am also getting the error on the line while(getline(outfile, line)) that says "no matching function for call to 'getline(std::ofstream&, std::string&)'"
Thank you, your help is very much appreciated.
My first thought was that the structure of the table is very uniform, so you could determine the position of a specific score using columns and rows.
Because the names are the only elements with variable length (assuming the scores don't go above 9, because that would give 2 characters), I would first read the first word of every row and input this into an array of names.
From this you can find specific elements using the row and column indices. If C++ doesn't contain a function to get characters based on row and column indices, I would loop through the file and add each character to the corresponding position in a 2-dimensional array.
For example:
characters[0][0]
would return N, from the start of "Names".
And of course to retrieve the score you incorporate the length of the name the specific line to get the value:
characters[names[0].length()+1][1]
This would return the score under G for the first name in the list.

Reading Strings and Ints from the Same File

Given input in the form of
fifteen,7,fourth-four,2,1,six
66,eight-six,99,eighteen
6,5,4,3,2,1
What can I use to read this into a format that I can then parse? The goal is to be able to sort the numbers and then print them back out, in order, in the same format that they were given to me. For example, the following should be printed as
1,2,six,7,fifteen,forty-four
eighteen,66,eighty-six,99
1,2,3,4,5,6
I have an idea of how the sorting should be done, I'm just having trouble figuring out the best way to read in the input. Currently, I'm using just doing this:
#include <iostream>
#include <string>
using namespace std;
int main() {
char word;
char arr[20];
int count = 0;
while (cin >> word) {
if (word == '\n') {
cout << "Newline detected.";
}
cout << "Character at: " << count << " is " << word << endl;
count++;
}
}
This does not work, because there is never a \n read in.
IMO the easiest way to do it would be to use std::istream's getline function with the ',' as the delimiter.
E.g. Something like.
char dummystr[256];
int count = 0;
while (cin.getline(dummystr, 256, ',')) {
cout << "Character at: " << count << " is " << dummystr << endl;
++count;
}
For newline delimiters with comma delimiters on each line (you really should just pick one):
char dummystr[256]; // not max size for the string
int count = 0;
while (cin.getline(dummystr, 256, '\n')) {
std::stringstream nested(dummystr);
char dummystr2[256];
while (nexted.getline(dummystr2, 256, ',')) {
cout << "Character at: " << count << " is " << dummystr << endl;
++count;
}
}

File pointer movement for getline

I have got an input file with following data
2
100
2
10 90
150
3
70 10 80
Now, I am able to read till 4th line ( 10 90) but when reading 5th line(150), the file pointer seems to be stuck at 4th line. I have tried infile.clear() just incase. How do I make sure that file pointer is moving correctly or position it at next line? Appreciate your feedback.
-Amit
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
int main(void) {
int cases;
int total_credit=0;
int list_size=0;
string list_price;
//Read file "filename".
ifstream infile;
infile.open("A-large-practice.in",ifstream::in);
if(!infile.is_open()) {
cout << "\n The file cannot be opened" << endl;
return 1;
}
else {
cout<<"Reading from the file"<<endl;
infile >> cases;
cout << "Total Cases = " << cases << endl;
int j=0;
while (infile.good() && j < cases) {
total_credit=0;
list_size=0;
infile >> total_credit;
infile >> list_size;
cout << "Total Credit = " << total_credit << endl;
cout << "List Size = " << list_size << endl;
//cout << "Sum of total_credit and list_size" << sum_test << endl;
int array[list_size];
int i =0;
while(i < list_size) {
istringstream stream1;
string s;
getline(infile,s,' ');
stream1.str(s);
stream1 >> array[i];
//cout << "Here's what in file = " << s <<endl;
//array[i]=s;
i++;
}
cout << "List Price = " << array[0] << " Next = " << array[1] << endl;
int sum = array[0] + array[1];
cout << "Sum Total = " << sum << endl;
cout <<"Testing" << endl;
j++;
}
}
return 0;
}
The problem is that you're using ' ' (space) as your "line terminator" for getline. So when you're reading the numbers on line 4 into the string s, the first one will be "10" and the second will be "90\n150\n3\n70" -- that is, everything up to the next space. This is almost certinaly not what you want and is leading to your confusion about where you are in the file. The next number you read will be 10, leading you to think you're on line 4 when in fact you're on line 7.
edit
The easiest way to fix this is probably to not use getline at all and just read ints directly from the input:
while (i < list_size)
infile >> array[i++];
This ignores the newlines altogether, so the input might as well be all on one line or split between lines randomly, but as you have an initial number that tells you how many numbers to read, that's just fine.