saving files in c++ at different full paths - c++

I am writing a program in C++ which I need to save some .txt files to different locations as per the counter variable in program what should be the code? Please help
I know how to save file using full path
ofstream f;
f.open("c:\\user\\Desktop\\**data1**\\example.txt");
f.close();
I want "c:\user\Desktop\data*[CTR]*\filedata.txt"
But here the data1,data2,data3 .... and so on have to be accessed by me and create a textfile in each so what is the code?
Counter variable "ctr" is already evaluated in my program.

You could snprintf to create a custom string. An example is this:
char filepath[100];
snprintf(filepath, 100, "c:\\user\\Desktop\\data%d\\example.txt", datanum);
Then whatever you want to do with it:
ofstream f;
f.open(filepath);
f.close();
Note: snprintf limits the maximum number of characters that can be written on your buffer (filepath). This is very useful for when the arguments of *printf are strings (that is, using %s) to avoid buffer overflow. In the case of this example, where the argument is a number (%d), it is already known that it cannot have more than 10 characters and so the resulting string's length already has an upper bound and just making the filepath buffer big enough is sufficient. That is, in this special case, sprintf could be used instead of snprintf.

You can use the standard string streams, such as:
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
void f ( int data1 )
{
ostringstream path;
path << "c:\\user\\Desktop\\" << data1 << "\\example.txt";
ofstream file(path.str().c_str());
if (!file.is_open()) {
// handle error.
}
// write contents...
}

Related

How do I change the value of a variable in an object with file handling?

I am working on a project with oop and file handling and I need a changeQuantity() method where the name of the item and a number(positive or negative) is passed. I want to change the quantity with this method and write the changes to the file.
My Object:
class Item(){
int itemId, quantity;
char title[25], type[10];
float price;
public:
void changeQuantity(char*, int);
};
The changeQuantity() method I am using:
void Item::changeQuantity(char* name, int quan){
fstream file;
file.open("filename.txt", ios::in | ios::out);
//after finding the object to work on
this->quantity += quan;
file.seekp(file.tellp() - sizeof(*this));
file.write((char*)this, sizeof(*this));
}
I tried with this method but it messes up the entire text file. How can I change only the quantity variable and write that change to the file without affecting anything else?????
Any kind of help would be greatly appreciated. Thank You.
PS: What I want to do here is only change the value of the quantity variable stored in the object which is stored in the txt file. The code that I am using messes the txt file.
I removed parameters except the file name from file.open() method. As fstream already has default parameters ios::in | ios::out, I removed that and it worked the way I wanted it to. But it does not work 100% of the time. It still repeats the problem sometimes and I haven't been able to find that out why.
It seems like you are mixing apples and oranges. You read something from a text file of size *this; but you read it into the binary storage of your object, and in binary mode. When it is written out, it is still in the binary format of your object. Ways to do it right:
Open the file in text mode, and read and write everything with, say gets & puts (insecure and error prone). Translate every number from text to binary when reading it in.
It is better to read them into std::string variables; as it is more powerful and less error prone. The classic C++ way to do it is e.g. the example from Input/output with files:
// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
string line;
ifstream myfile ("example.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << line << '\n';
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
You would need to adapt it to read and translate (e.g. from text number format to a variable) each member of your object. I don't know of a way to mass read e.g. lines of text in a text file into an object's members. Once it is in binary format and properly read into your object, you can write our objects out to a binary file like that; but note: they won't be of fixed size, so you will need to write the size of the object out first, and then the object itself; and read the size of the object in and then the object itself.
In short, you are using a binary file access method, when e.g. your ints are text instead of probably 32-bit binaries, and your strings are are \n or \n\r instead of null terminated. Typical ways to handle text input and output of objects are to have one text line for each member, and translate them one at a time; or to read and write them as CSV or JSON - again one at a time for each member; and then looping through the file.
BTW: It is considered bad form to use using std; as in this example. To keep things in the std namespace from interfering with your variables and routines, it is better to use using std::string; etc.; for each thing you want to access from the std namespace.

Are standard text files NULL-terminated?

I am writing a C++ program that reads a file and then sends it to another class as a character array. Because character arrays only get passed by pointer, all size is lost.
The file it'll be reading will be a text file. Are text files null terminated?
Preferably I do not want to use a Vector as I really don't need any of it's features but the size of the array.
No.
Files have a known length, so they do not need any terminator byte.
no text files are not NULL terminated. You need to check for EOF (End Of File)
I think
cin.eof()
is what you are searching. It returns true if the end of file is reached.
No, they are not. But many C/C++ function to read strings from files appends zero termination to returned data.
use eof rather than finding null character ...
for example :
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream iFile("myfile.txt"); // myfile.txt has integers, one per line
while (!iFile.eof())
{
int x;
iFile >> x;
cerr << x << endl;
}
return 0;
}

Length of a char array

I have the code like this:
#include <iostream.h>
#include <fstream.h>
void main()
{
char dir[25], output[10],temp[10];
cout<<"Enter file: ";
cin.getline(dir,25); //like C:\input.txt
ifstream input(dir,ios::in);
input.getline(output,'\eof');
int num = sizeof(output);
ofstream out("D:\\size.txt",ios::out);
out<<num;
}
I want to print the length of the output. But it always returns the number 10 (the given length) even if the input file has only 2 letters ( Like just "ab"). I've also used strlen(output) but nothing changed. How do I only get the used length of array?
I'm using VS C++ 6.0
sizeof operator on array gives you size allocated for the array, which is 10.
You need to use strlen() to know length occupied inside the array, but you need to make sure the array is null terminated.
With C++ better alternative is to simple use: std::string instead of the character array. Then you can simply use std::string::size() to get the size.
sizeof always prints the defined size of an object based on its type, not anything like the length of a string.
At least by current standards, your code has some pretty serious problems. It looks like it was written for a 1993 compiler running on MS-DOS, or something on that order. With a current compiler, the C++ headers shouldn't have .h on the end, among other things.
#include <iostream>
#include <fstream>
#include <string>
int main() {
std::string dir, output, temp;
std::cout<<"Enter file: ";
std::getline(cin, dir); //like C:\input.txt
std::ifstream input(dir.c_str());
std::getline(input, output);
std::ofstream out("D:\\size.txt");
out<<output.size();
}
The getline that you are using is an unformatted input function so you can retrieve the number of characters extracted with input.gcount().
Note that \e is not a standard escape sequence and the character constant \eof almost certainly doesn't do what you think it does. If you don't want to recognise any delimiter you should use read, not getline, passing the size of your buffer so that you don't overflow it.

C++ - Find and replace in text file (standard system libraries)

I am looking for some advice.
My situation:
Application works with text local file.
In file are somewhere tags like this: correct = "TEXT". Unfortunatelly, there can be unlimited spaces between correct, = and "TEXT".
Obtained text is testing in function and may be replaced (the change must be stored in the file). correct = "CORRECT_TEXT"
My current theoretical approach:
With ofstream -- read by line to string.
Find tag and make change in string.
Save strings as lines to the file.
Is there some simplify way (with iterators?) in C++ with using standard system libraries only (unix).
Thank you for your ideas.
Here is a possible solution that uses:
std::getline()
std::copy()
istream_iterator
ostream_iterator
vector
Example:
#include <iostream>
#include <fstream>
#include <iterator>
#include <algorithm>
#include <string>
#include <vector>
struct modified_line
{
std::string value;
operator std::string() const { return value; }
};
std::istream& operator>>(std::istream& a_in, modified_line& a_line)
{
std::string local_line;
if (std::getline(a_in, local_line))
{
// Modify 'local_line' if necessary
// and then assign to argument.
//
a_line.value = local_line;
}
return a_in;
}
int main()
{
std::ifstream in("file.txt");
if (in.is_open())
{
// Load into a vector, modifying as they are read.
//
std::vector<std::string> modified_lines;
std::copy(std::istream_iterator<modified_line>(in),
std::istream_iterator<modified_line>(),
std::back_inserter(modified_lines));
in.close();
// Overwrite.
std::ofstream out("file.txt");
if (out.is_open())
{
std::copy(modified_lines.begin(),
modified_lines.end(),
std::ostream_iterator<std::string>(out, "\n"));
}
}
return 0;
}
I am not sure exactly what the manipulation of the lines should be but you could use:
std::string::find() and std::string::substr()
boost::split()
EDIT:
To avoid storing every line in memory at once the initial copy() can changed to write to an alternative file, followed by a file rename():
std::ifstream in("file.txt");
std::ofstream out("file.txt.tmp");
if (in.is_open() && out.open())
{
std::copy(std::istream_iterator<modified_line>(in),
std::istream_iterator<modified_line>(),
std::ostream_iterator<std::string>(out, "\n"));
// close for rename.
in.close();
out.close();
// #include <cstdio>
if (0 != std::rename("file.txt.tmp", "file.txt"))
{
// Handle failure.
}
}
You can split the task into tiny pieces and figure out how to do each in C++:
open a file as an input stream
open temporary file as an output stream
read a line from a stream
write a line to a stream
match a line to given pattern
replace text in a line
rename a file
Note: you don't need to store in memory more than one line at a time in this case.
It looks a lot like an 'INI file' syntax. You can search for it and you'll have a big load of examples. However, few of them will actually use C++ stdlib.
Here's some advices. (n.b. I assume that every lines you'll need to replace are using the syntax: <parameter> = "<value_text>")
Use the std::string::find method to locate the '=' character.
Use the std::string::substr method to split the string into different chunks.
You'll need to create a trim algorithm to remove every blank characters in front or back of a string. (It can be done with std functions)
With all that you'll then be able to split the string and isolate the parts to compare them do the needed modifications.
have fun !
Are you sure you need to do this within C++? Since you are on Unix, you can call sed which would do this easily with a command such as:
cat oldfile | sed 's/\(correct *= *\)\"TEXT\"/\1\"CORRECT_TEXT\"/' > newfile
You can call unix commands from within C++ if you have to (for example with system("command") from <cstdlib>.

How to read and write a STL C++ string?

#include<string>
...
string in;
//How do I store a string from stdin to in?
//
//gets(in) - 16 cannot convert `std::string' to `char*' for argument `1' to
//char* gets (char*)'
//
//scanf("%s",in) also gives some weird error
Similarly, how do I write out in to stdout or to a file??
You are trying to mix C style I/O with C++ types. When using C++ you should use the std::cin and std::cout streams for console input and output.
#include <string>
#include <iostream>
...
std::string in;
std::string out("hello world");
std::cin >> in;
std::cout << out;
But when reading a string std::cin stops reading as soon as it encounters a space or new line. You may want to use std::getline to get a entire line of input from the console.
std::getline(std::cin, in);
You use the same methods with a file (when dealing with non binary data).
std::ofstream ofs("myfile.txt");
ofs << myString;
There are many way to read text from stdin into a std::string. The thing about std::strings though is that they grow as needed, which in turn means they reallocate. Internally a std::string has a pointer to a fixed-length buffer. When the buffer is full and you request to add one or more character onto it, the std::string object will create a new, larger buffer instead of the old one and move all the text to the new buffer.
All this to say that if you know the length of text you are about to read beforehand then you can improve performance by avoiding these reallocations.
#include <iostream>
#include <string>
#include <streambuf>
using namespace std;
// ...
// if you don't know the length of string ahead of time:
string in(istreambuf_iterator<char>(cin), istreambuf_iterator<char>());
// if you do know the length of string:
in.reserve(TEXT_LENGTH);
in.assign(istreambuf_iterator<char>(cin), istreambuf_iterator<char>());
// alternatively (include <algorithm> for this):
copy(istreambuf_iterator<char>(cin), istreambuf_iterator<char>(),
back_inserter(in));
All of the above will copy all text found in stdin, untill end-of-file. If you only want a single line, use std::getline():
#include <string>
#include <iostream>
// ...
string in;
while( getline(cin, in) ) {
// ...
}
If you want a single character, use std::istream::get():
#include <iostream>
// ...
char ch;
while( cin.get(ch) ) {
// ...
}
C++ strings must be read and written using >> and << operators and other C++ equivalents. However, if you want to use scanf as in C, you can always read a string the C++ way and use sscanf with it:
std::string s;
std::getline(cin, s);
sscanf(s.c_str(), "%i%i%c", ...);
The easiest way to output a string is with:
s = "string...";
cout << s;
But printf will work too:
[fixed printf]
printf("%s", s.c_str());
The method c_str() returns a pointer to a null-terminated ASCII string, which can be used by all standard C functions.