C++: print data, printf - c++

At the end of the following code I obtain the output and print it on the terminal using cout (at line 60). However, I would like to print it in a text file but I cannot use fprintf in this case.
How could I do it?
This is my code:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
using namespace std;
bool isnotdigit(char c)
{
return !isdigit(c);
}
bool compare(const string s1, const string s2)
{
auto itr1 = s1.begin(), itr2 = s2.begin();
if (isdigit(s1[0]) && isdigit(s2[0]))
{
int n1, n2;
stringstream ss(s1);
ss >> n1;
ss.clear();
ss.str(s2);
ss >> n2;
if (n1 != n2)
return n1 < n2;
itr1 = find_if(s1.begin(), s1.end(), isnotdigit);
itr2 = find_if(s2.begin(), s2.end(), isnotdigit);
}
return lexicographical_compare(itr1, s1.end(), itr2, s2.end());
}
int main()
{
char out_file_name[500];
snprintf(out_file_name, sizeof(out_file_name), "sort.txt");
FILE *out_file;
out_file = fopen(out_file_name, "w");
cout << "Making output file: " << out_file_name << endl;
ifstream in("mydata.txt");
if (in)
{
vector<string> lines;
string line;
while (getline(in, line))
lines.push_back(line);
sort(lines.begin(), lines.end(), compare);
for (auto itr = lines.begin(); itr != lines.end(); ++itr)
cout << *itr << endl;
//fprintf(out_file,);
}
fclose(out_file);
cout << "Output complete" << endl;
return 0;
}

Use std::ofstream and create a file variable:
std::ofstream output_file("output.txt");
if (output_file)
{
output_file << "Hello there.\n";
output_file.flush();
}
Please review your favorite C++ reference in the section about file I/O.
This is one of those areas that differs from the C language.

Related

How to remove an item of Vectors c++

i have this code and i want to find a word in my vector and delete the item that includes that word but, my code will delete from the first line until the item that i want, how can i fix that?
std::string s;
std::vector<std::string> lines;
while (std::getline(theFile, s))
{
lines.push_back(s);
}
//finding item in vector and changing it
for (unsigned i = 0; i < lines.size(); i++)
{
std::size_t found = lines[i].find(name);
if (found != std::string::npos)
{
lines.erase(lines.begin() + i);
}
}
Update 1:
this is my full Code:
I'm opening a file that contains some elements in this format
( David, 2002 , 1041 , 1957 )
( cleve, 2003 , 1071 , 1517 )
( Ali, 2005 , 1021 , 1937 )
i'm getting a user input and finding the line that contains it. then i want to remove that line completely so i import it to a vector and then i can't modify it
#include <iostream>
#include <string>
#include <vector>
#include <stream>
#include <algorithm>
using namespace std;
using std::vector;
int main(){
string srch;
string line;
fstream Myfile;
string name;
int counter;
Myfile.open("Patientlist.txt", ios::in | ios::out);
cout <<"Deleting your Account";
cout << "\nEnter your ID: ";
cin.ignore();
getline(cin, srch);
if (Myfile.is_open())
{
while (getline(Myfile, line))
{
if (line.find(srch) != string::npos)
{
cout << "\nYour details are: \n"
<< line << endl;
}
break;
}
}
else
{
cout << "\nSearch Failed... Patient not found!" << endl;
}
Myfile.close();
ifstream theFile("Patientlist.txt");
//using vectors to store value of file
std::string s;
std::vector<std::string> lines;
while (std::getline(theFile, s))
{
lines.push_back(s);
}
//finding item in vector and changing it
for (unsigned i = 0; i < lines.size(); i++)
{
std::size_t found = lines[i].find(name);
if (found != std::string::npos)
{
lines.erase(lines.begin() + i);
}
}
//writing new vector on file
ofstream file;
file.open("Patientlist.txt");
for (int i = 0; i < lines.size(); ++i)
{
file << lines[i] << endl;
}
file.close();
cout << "Done!";
}
The erasing loop is broken. The proper way is to use iterators and use the iterator returned by erase. Like so:
// finding item in vector and changing it
for (auto it = lines.begin(); it != lines.end();) {
if (it->find(name) != std::string::npos) {
it = lines.erase(it);
} else {
++it;
}
}
Or using the erase–remove idiom:
lines.erase(std::remove_if(lines.begin(), lines.end(),
[&name](const std::string& line) {
return line.find(name) != std::string::npos;
}), lines.end());
Or since C++20 std::erase_if(std::vector):
std::erase_if(lines, [&name](const std::string& line) {
return line.find(name) != std::string::npos;
});
You can use remove_if for this. The predicate argument should check if you can find a word in a line. Then remember to use erase to "shrink" the vector to its new size.
[Demo]
#include <algorithm> // remove_if
#include <iostream> // cout
#include <string>
#include <vector>
int main()
{
std::vector<std::string> lines{"one two three", "three four five", "five six one"};
lines.erase(
std::remove_if(std::begin(lines), std::end(lines), [](auto& line) {
return line.find("one") != std::string::npos;}),
std::end(lines)
);
for (auto& line : lines) { std::cout << line << "\n"; }
}

Skip integers while reading text from file into array

I am trying to create a program where I could read string data from a file and store it into an array, but I want to skip any integers or non-letters and not read them into the array. Any ideas on how to do that?
This is my code:
#include <iostream>
#include <stream>
#include <iomanip>
#include <cstdlib>
#include <algorithm>
#include <cctype>
#include <string>
using namespace std;
void loadData();
int main()
{
loadData();
return 0;
}
void loadData()
{
const int SIZE = 100;
string fileName;
std::string wordArray[SIZE];
cout << "Please enter the name of the text file you want to process followed by '.txt': " << endl;
cin >> fileName;
ifstream dataFile;
dataFile.open(fileName, ios::in);
if (dataFile.fail())
{
cerr << fileName << " could not be opened." << endl; //error message if file opening fails
exit(-1);
}
while (!dataFile.eof())
{
for (int i = 0; i < SIZE; i++)
{
dataFile >> wordArray[i];
for (std::string& s : wordArray) //this for loop transforms all the words in the text file into lowercase
std::transform(s.begin(), s.end(), s.begin(),
[](unsigned char c) { return std::tolower(c); });
cout << wordArray[i] << endl;
}
}
}
Use copy_if:
for (std::string& s : wordArray)
std::copy_if(s.begin(), s.end(), s.begin(),
[](char& c) { c = std::tolower(c); return std::isalpha(c); });
Note that this may not be the most efficient code.
This is a scenario where regexes can come in handy.
They do require forward iterators though, so you need to read in the whole file at once before extracting words.
#include <iostream>
#include <iterator>
#include <fstream>
#include <regex>
std::string read_whole_file(const std::string& file_name) {
std::ifstream file(file_name);
return {std::istreambuf_iterator<char>(file),
std::istreambuf_iterator<char>()};
}
int main()
{
// ...
auto file_data = read_whole_file(filename);
std::regex word_regex("(\\w+)");
auto words_begin =
std::sregex_iterator(file_data.begin(), file_data.end(), word_regex);
auto words_end = std::sregex_iterator();
for (auto i = words_begin; i != words_end; ++i) {
std::cout << "found word" << i->str() << '\n';
}
}

How to skip blank spaces when reading in a file c++

Here is the codeshare link of the exact input file: https://codeshare.io/5DBkgY
Ok, as you can see, ​there are 2 blank lines, (or tabs) between 8 and ROD. How would I skip that and continue with the program? I am trying to put each line into 3 vectors (so keys, lamp, and rod into one vector etc). Here is my code (but it does not skip the blank line).:
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
#include <fstream>
using namespace std;
int main() {
ifstream objFile;
string inputName;
string outputName;
string header;
cout << "Enter image file name: ";
cin >> inputName;
objFile.open(inputName);
string name;
vector<string> name2;
string description;
vector<string> description2;
string initialLocation;
vector<string> initialLocation2;
string line;
if(objFile) {
while(!objFile.eof()){
getline(objFile, line);
name = line;
name2.push_back(name);
getline(objFile, line);
description = line;
description2.push_back(description);
getline(objFile, line);
initialLocation = line;
initialLocation2.push_back(initialLocation);
} else {
cout << "not working" << endl;
}
for (std::vector<string>::const_iterator i = name2.begin(); i != name2.end(); ++i)
std::cout << *i << ' ';
for (std::vector<string>::const_iterator i = description2.begin(); i != description2.end(); ++i)
std::cout << *i << ' ';
for (std::vector<string>::const_iterator i = initialLocation2.begin(); i != initialLocation2.end(); ++i)
std::cout << *i << ' ';
#include <cstddef> // std::size_t
#include <cctype> // std::isspace()
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
bool is_empty(std::string const &str)
{
for (auto const &ch : str)
if (!std::isspace(static_cast<char unsigned>(ch)))
return false;
return true;
}
int main()
{
std::cout << "Enter image file name: ";
std::string filename;
std::getline(std::cin, filename); // at least on Windows paths containing whitespace
// are valid.
std::ifstream obj_file{ filename }; // define variables as close to where they're used
// as possible and use the ctors for initialization.
if (!obj_file.is_open()) { // *)
std::cerr << "Couldn't open \"" << filename << "\" for reading :(\n\n";
return EXIT_FAILURE;
}
std::vector<std::string> name;
std::vector<std::string> description;
std::vector<std::string> initial_location;
std::string line;
std::vector<std::string> *destinations[] = { &name, &description, &initial_location };
for (std::size_t i{}; std::getline(obj_file, line); ++i) {
if (is_empty(line)) { // if line only consists of whitespace
--i;
continue; // skip it.
}
destinations[i % std::size(destinations)]->push_back(line);
}
for (auto const &s : name)
std::cout << s << '\n';
for (auto const &s : description)
std::cout << s << '\n';
for (auto const &s : initial_location)
std::cout << s << '\n';
}
... initial_locations look like integers, though.
*) Better early exit if something bad happens. Instead of
if (obj_file) {
// do stuff
}
else {
// exit
}
-->
if(!obj_file)
// exit
// do stuff
makes your code easier to read and takes away one level of indentation for the most parts.

C++: why is vector implementation not yielding comma-delimited values?

I have a database.txt file with comma-separated values:
Name,ID,Year,Gender
I would like to extract each of these elements.
I've started with this code (I've already looked at all the other similar questions and implemented what they've suggested), but it's not printing each piece:
// reading a text file
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
int main () {
string line;
ifstream myfile ("database.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
std::string str = line;
std::vector<int> vect;
std::stringstream ss(str);
int i;
while (ss >> i)
{
vect.push_back(i);
if (ss.peek() == ',')
ss.ignore();
}
for (i=0; i< vect.size(); i++)
std::cout << vect.at(i)<<std::endl;
//cout << line << '\n';
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
How can I modify it to be able to extract each value: name, ID, year, and gender? What am I doing wrong?
Use this function to split each line:
vector<string> split(const string &s, char delim) {
stringstream ss(s);
string item;
vector<string> tokens;
while (getline(ss, item, delim)) {
tokens.push_back(item);
}
return tokens;
}
and your code be like:
// reading a text file
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
int main () {
string line;
ifstream myfile ("database.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
std::string str = line;
std::vector<string> vect;
vect = split(str, ',') ;
for (int i=0; i< vect.size(); i++)
std::cout << vect.at(i)<<std::endl;
//cout << line << '\n';
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
With the help of a utility function and a data structure you can simplify this quite easily.
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
std::vector<std::string> splitString( const std::string& stringToSplit, const std::string& delimiter, const bool keepEmpty ) {
std::vector<std::string> results;
if ( delimiter.empty() {
results.push_back( stringToSplit );
return results;
}
std::string::const_iterator itSubStrStart = stringToSplit.begin(), itSubStrEnd;
while( true ) {
itSubStrEnd = std::search( itSubStrStart, stringToSplit.end(), delimiter.begin(), delimiter.end() );
std::string temp( itSubStrStart, itSubStrEnd );
if ( keepEmpty || !temp.empty() )
results.push_back( temp );
if ( itSubStrEnd == stringToSplit.end() )
break;
itSubStrStart = itSubStrEnd + delimiter.size();
}
return results;
}
struct DataEntry {
std::string name;
unsigned id;
unsigned year;
std::string gender;
};
int main() {
std::string line;
std::fstream file;
file.open( "database.txt" );
std::vector<DataEntry> entries;
std::vector<std::string> elements;
while( file >> line ) {
elements = splitString( line, "," );
DataEntry entry;
entry.name = elements[0];
entry.id = std::stoul( elements[1] );
entry.year = std::stoul( elements[2] );
entry.gender = elements[3];
entries.push_back( entry );
}
file.close();
for ( auto& e : entries ) {
std::cout << e.name << " " << e.id << " "
<< e.year << " " << e.gender << '\n';
}
std::cout << "\nPress any key and enter to quit.\n";
std::cin.get();
return 0;
}
database.txt
John,12345,2010,M
Jane,54321,2012,F
output
John 12345 2010 M
Jane 54321 2012 F
This makes life it a lot easier just by reading in a single line first; then parsing that line of text and from there doing what you will with that data; either storing it to a struct, printing it, manipulating it etc.
Edit
You need to be aware of the fact that when reading in lines of text, and parsing them if you have something like this in your text file:
John Doe,12345,2010,M
It will not give you what you would expect. I'll leave that for you to figure out.

C++ fstream in >> variableName execution

Here is my code, not sure why no error but return nothing. it is OK if there is no getline function in ReadFile?? And when debugging, another potential problem is whether the map is needed to define the size when map is declared. I am a beginner. any help is appreciated.
#include <iostream>
#include <fstream>
#include<map>
#include<set>
#include<string>
void swap(char &ch1, char &ch2){ //swap the content
char tmp=ch1;
ch1=ch2;
ch2=tmp;
}
std::string ToLower(std::string s){
for(int i=0;i < s.length();i++)
{
if(s[i]<='Z' && s[i]>='A')
{
s[i]-='A'-'a';
}
}
return s;
}
std::string signature(std::string s)
{
s=ToLower(s);
for(int i=0;i<s.length();i++)
{ int minIndex=i;
for(int j=i+1;j<s.length();j++)
if(s[j]<s[minIndex]) minIndex=j;
swap(s[minIndex],s[i]);
}
return s;
}
void ReadFile(std::ifstream &in, std::map<std::string,std::set<std::string>> &m)
{
while(true)
{
std::string word;
in>>word;
if(!in.good())break;
m[signature(word)].insert(word);
}
}
typedef std::map<std::string, std::set<std::string>>::const_iterator MapIterator;
typedef std::set<std::string>::const_iterator SetIterator;
int main(){
std::ifstream in("ospd.txt");
std::map<std::string, std::set<std::string>> m;
ReadFile(in,m);
for (MapIterator iter = m.begin(); iter != m.end(); iter++)
{
std::cout << "Key: " << iter->first << std::endl << "Values:" << std::endl;
for (SetIterator set_iter = iter->second.begin(); set_iter != iter->second.end(); set_iter++)
std::cout << " " << *set_iter <<std:: endl;
}
system("pause");
return 0;}
Updated: the programming is working. Thanks for everybody!!!
Can you try this.
#include <iterator>
using namespace std;
void ReadFile(std::ifstream &in, std::map<std::string,std::set<std::string>> &m)
istream_iterator<string> itr(in);
istream_iterator<string> end;
while(itr != end)
{
string work = *itr;
m[signature(word)].insert(word);
++itr;
}