Can I manually type in the file name inside of the terminal?
For example, the program will ask me which file I want to open up. I'll manually type in "test.txt" and it'll open up test.txt. However, my compiler is issuing the following error:
no matching function for call to 'std::basic_ifstream<char>::basic_ifstream(std::string&)'
My code:
int main() {
string input;
cout << "Please enter the name of the file\n";
cout << "Input: ";
getline (cin, input);
ifstream file (input);
if (file.is_open()) {
// blah
} else {
// blah
}
}
How can I manually type in the text file name?
If you're using an older (pre-C++11) compiler, you'll have to use:
ifstream file (input.c_str());
Although the file name was a string-like thing, and C++98 had std::string, they didn't put two and two together (so to speak), so in C++98 the string-like thing to specify the name of a file you wanted to open had to be specified as a char const * (i.e., a C-style string) rather than an std::string.
I predict it's purely a matter of time before supporting only char const * and std::string as the name looks (at least close to) equally silly--once we're accustomed to using ranges, it'll be obvious that it should really just be some range of character-like things.
Related
I'm currently working on this program for a class in my university. I've tried multiple approach with no success. I'm pretty sure it's just a conversion problem, but I want to understand the differences.
What the program supposed to do : We're to create a program that ask the user for two filenames. One will be an input and another will be an output. The program is supposed to read the input and write the line to the output while until the end of the input file is not reached.
My Code :
#include <iostream>
#include <fstream> //included for read/writing files
#include <string> //Included this for getline to read the file
using namespace std;
int main() {
ifstream infile; // Stream to read from input file
ofstream outfile; // Stream to write to output file
char inputfilename[80], outputfilename[80]; //declaring two character arrays to save the file names.
string text;
cout << "What is the name of your input file (text.txt)" ; // Prompting user for input file name
cin >> (inputfilename); // Getting input file
infile.open(inputfilename, ios::in); // Opening the input file.
cout << "What is the name of your output file" ; // Prompting user for output file name
cin >> (outputfilename);
outfile.open(outputfilename, ios::out);
if(!infile) { // If cannot open file
cout << "There was an error opening your file!" ;
return 1;
}
if (!outfile) {
cout << "There was an error opening your file!" ;
return 1;
}
while (infile.eof()==0) {
fgets(text, 80, infile);
fprintf(outfile,"%d. %s\n", text);
}
infile.close(); // Closing input file
outfile.close(); // Closing output file
return 0;
}
What I've tried : I didn't know if it was being affected by how I opened the file. I previously tried.
ifstream infile;
ofstream outfile;
char text, inputfilename[80], outputfilename[80]; <----- 1
cout << "What is the name of your input file (text.txt)" ;
gets(inputfilename); <----- 2
infile.open(inputfilename);
cout << "What is the name of your output file" ;
gets(outputfilename); <----- 2
outfile.open(outputfilename);
1) I switched char I previous tried
char text
char text[80]
char *text[80]
2) Would switching how getting the file name change anything in the while loop(I previous tried getline and gets)? Additionally the "f" in front of fgets/fprints/etc are always associated with a file stream?
Note: My teacher gave us the hint.
"Suppose you read a line from the input file into a string variable called str using the following statement: fgets(str, 80, infile);You can add a line number and save the line with the line number to the output file using the same statement using: fprintf(outfile,"%d. %s\n",Next_line_number++, str);"
from this I tried :
while (infile.eof()==0) {
fgets(text, 80, infile);
fprintf(outfile,"%d. %s\n", text);
}
as well as
while (infile.eof()==0) {
fgets(text, 80, infile);
fputs(text, outFile);
}
and
while (infile.eof()==0) {
getline(infile, text);
fprintf(outfile,"%d. %s\n", text);
}
I also tried making a long and using that to increment the line number. I'm fairly new to programming; if any of the methods I'm using our dated please let me know (on some sites they were saying fgets is dated and not supported on cx11 or some version of C++)! I want to understand the concepts vs just get the programming running. Should note Lines 34-35 are where my code is always erroring out and it's
cannot convert 'std::__cxx11::string {aka std::__cxx11::basic_string}' to 'char*' for argument '1' to 'char* fgets(char*, int, FILE*)'
I figured I was getting this because it has a pointer to the file and I'm asking the user vs having the file declared in the program. This is causing a conversion that causing my error.
fgets(text, 80, infile);
fgets() is a C library function, that expects a char * as its first parameter. It knows absolutely nothing about any C++ class, and not just std::string that you are passing as the first parameter. Neither does fgets() has any clue about the C++ std::ifstream class you're attempting to pass to it as its third parameter. And that's exactly what your compiler's error message states.
You are randomly mixing up C and C++ code, which results in repeated confusion.
char inputfilename[80], outputfilename[80];
You should also use std::strings, instead of arbitrary-sized C style arrays, here.
while (infile.eof()==0) {
This is always a bug, and read this linked article for more information.
fprintf(outfile,"%d. %s\n", text);
Again: fprintf is also a C library function, that knows absolutely nothing about C++ classes like std::string and std::ofstream. In either case, this is a bug because this string has placeholders for two parameters, an integer, %d, and C style string, %s; and you're giving just one parameter here, text. In the event that you were writing C instead of C++ code, this would not've worked either, but that's mostly academic. This is a C++ program, and this C library function has no business doing anything here, in the first place.
When you are reading from a std::ifstream:
You can use std::getline to read an entire line of text into a std::string
Alternatively you can use the >> formatted extraction operator
Or you can use various methods of the std::ifstream object to read from the file and into a suitable buffer
These alternatives are not equivalent (otherwise what would be the point?) and they do different things, and the right one to use depends on what the requirements are.
Similarly, to write to a std::ofstream you can use:
The << formatted output operator.
Various methods of the std::ofstream object itself.
And, in some advanced situations you can take advantage of the iterator library, and implement reading and writing using input and output iterators, too.
The correct approach depends on the individual situation. For more information on how to read and write from files in C++ using these approaches, see any good C++ book. Whichever C++ book actually advised you to use fgets() to read from a std::ifstream and into a std::string: throw it away, and get a better book, from the list linked above. If this is just what you found in some program somewhere on the Internet -- you can't learn C++ this way, by piecing together different parts of different programs, and hope that the results work. To fix all of your compilation errors: remove all that C code that knows absolutely nothing about C++, and replace it with proper C++ code, using any of the options I outlined above, using the examples from the C++ books linked above, as a reference.
I want to create a file with C++ and write something in it. I have two classes, one with a Vererbung::writer(string name) and another subclass called Vererbung1(int zahl). Without the integer it works peferctly but when I want to write the integer to string and paste it after the function it wont work.
this works normally
Vererbung.cpp
void Vererbung::Writer(string name)
{
ofstream text;
text.open ("test.txt", ios::trunc);
text <<"write something\n";
text <<"again2 \n";
text <<"again 3\n";
text << name;
text.close();
}
Vererbung1.cpp
include "Vererbung.h"
void Vererbung1::Writer(int zahl)
{
std::ostringstream ostr;
ostr<< zahl;
name = "\n" "Test\n""Test\n""Test\n" ostr.str();
Vererbung::Writer(name);
}
When I run it in main it says that I need a ';' before ostr.str(); how can I fix this, If I want a integer value to string in a file in it?
This problem is very unclearly stated but, if we assume that name is an std::string, then:
name = "\n" "Test\n""Test\n""Test\n" ostr.str();
This is just a bunch of string literals written next to each other, followed by an std::string expression also just randomly floating there in free space.
Your computer doesn't know what you want it to do.
Although you actually can concatenate string literals in this way (literals are something like "hello world", but not something like aStringVariable), that doesn't apply to arbitrary expressions (and you don't even need it where you've used it).
I think that what you meant was this:
name = "\nTest\nTest\nTest\n" + ostr.str();
I hope that your C++ book teaches this; if not, get a better one.
I want to make a simple program that will allow the user to create/open files and add text to them. This is the code I have currently:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
cout << "Enter file name:" << endl;
char fileName;
cin >> fileName;
ofstream myFile;
myFile.open(fileName, ios::out);
myFile << "This is the file text.\n";
myFile.close();
return 0;
}
I receive the following error at myFile.open(fileName, ios::out):
error: no matching function for call to 'std::basic_ofstream<char>::open(std::__cxx11::string&, const openmode&)'
The simple problem you are having here is that the variable filename that stores the name of the file is of type char. Change it to string so that it works.
On another note, try to break down the error message you got:
no matching function for call to 'std::basic_ofstream::open(std::__cxx11::string&, const openmode&)'
In open(std::__cxx11::string& ... it clearly says that the data type of the file name should be string&. This indicated that you had a data type error, which is true because you have used char instead of string.
Another thing: use char only when you want to accept a single letter as input; when you want to take a word or a sentence, store it in a string variable, and get it from the user using the getline() function. This will make your life easier.
To modify your code, firstly change your variable declaration statement to:
string fileName; // std:: is not required as you have the line "using namespace std"
Secondly, change the input statement of the file name from cin >> filename; to:
getline(cin, fileName);
It should work after these changes.
EDIT: I found the peoblem to your question. You will nave to change the open command to:
myFile.open(fileName.c_str(), ios::out);
Like it says in the error, the function needs a string passed to ot, however, when we take the string as input and store it in the variable fileName, it simply converts the string into a const char *. This is invisible to you when you run the code, but every once in a while, it causes an error.
This should definitely work now.
If you take a look at the error message, the first half of what is in the open parentheses tells you the answer. The user is typing in a char, the file name is expected to be a string. Instead of:
char fileName;
Use:
string fileName;
Ok thanks for the answer Wug! I changed my code but now it's complaining about:
no matching function for call to
std::basic_ofstream::basic_ofstream(std::basic_string)
I'm not sure it makes any difference but i'll just post all of my code it's not that much so far.
I'll try to keep it cleaner from now on.
#include <iostream>
#include <windows.h>
#include <direct.h>
#include <fstream>
using namespace std;
int main()
{ /*Introduction*/
SetConsoleTitle("Journal");
string action, prom0, filename, filepath;
filepath = "C:\\Users\\-\\Desktop\\Projects\\Journal Project\\Logs\\";
cout << "Hi and welcome to Journal! \nHere you can write down your day.\nWrite help for";
cout << "more \nType command to start: ";
/*Choose Action*/
cin >> action;
if (action == "new")
{system("cls");
/*Make new Journal file*/
cout << "Filename: ";
getline(cin, filename);
mkdir("C:\\Users\\-\\Desktop\\Projects\\Journal Project\\Logs");
ofstream journallogs(filepath + filename);
journallogs.close();
}
else {
cout << "Wrong command\n";
};
return 0;}
There are 2 things wrong. The first is what the compiler's complaining about:
ofstream journallogs("C:\\Users\\-\\Desktop\\Projects\\Journal Project\\Logs\\" + getline(cin, filename), ios::out);
std::getline(istream&, string&) returns istream&, and you can't add char * to istream. I recommend taking a look at the documentation for getline(), which might help you understand better how you're supposed to use it. Here's an example anyway:
string filepath = "C:\\Users\\-\\Desktop\\Projects\\Journal Project\\Logs\\";
string filename;
getline(cin, filename);
ofstream journallogs(filepath + filename);
The second problem is that you're reading from cin into filename before calling getline(). When you call getline(), any contents of filename are dropped, so you'll effectively trim the first word off of your filename, which probably isn't what you want. To fix that, remove the extraneous cin >> filename;
Note: indentation is important and helps you read your own code. Put forth the effort to keep your code looking nice.
First, learn this:
Start small and simple.
Add complexity a little at a time.
Test at every step.
develop new functionality in isolation.
Never add to code that doesn't work.
For the rest, I don't use Windows, so I can't be certain my code will work there, but the approach will.
You are trying to 1) get a filename from the user, 2) modify it and then 3) use it to open a file; we will develop these three things in isolation.
Getting a filename from the user. Civilized filenames do not contain whitespace, so they can be read with cin, but if you want to allow whitespace you can use getline instead. Either way, test it.
Modifying the filename. Write code that assigns a value to the filename, just as it does to the path-- do not get the filename from the user, it slows down your testing and is not proper isolation. Now try to append them. If you try filepath + filename, you may get a compiler error. Here's where you must understand the difference between std::string and char[]. A char[] is an array of char, and it (usually) contains a null-terminated sequence of characters; you must read up on arrays and pointers. It is a primitive type, and you cannot simply concatenate two of them with '+', you must use something like strcat, which is dangerous if you haven't done your homework on arrays. On the other hand, std::string is more sophisticated, and can handle '+' and many other operations. If you have a std::string x and you decide you want a char[] after all, you can get one like so: x.c_str().
Opening the file. If I remember right, the ofstream constructor can take a char[], but not a std::string. Test this with a hard-coded string (isolation!).
Once you have these three components working independently, you can hook them together.
So, I'm currently writing a line editor as a learning project on I/O, writing files, and the like. It is written in C++, and I am currently trying to write out to a file of the user's choosing. I have CLI arguments implemented, but I currently have no idea how to implement an in program way of specifying the file to write to.
char *filename;
if (argc >= 2){
filename = argv[1];
} else{
cout << "file>";
cin >> filename;
cin.ignore();
}
This works perfectly well when I use command line arguments; however, whenever I do not, as soon as I start the program, it Segmentation Faults. The place where I use the actual filename is in the save command:
void save(char filename[], int textlen, string file[]){
ofstream out(filename);
out << filestring(textlen, file);
out.close();
}
Which also works perfectly well. Is there any way you can help me? Full source code, for review, is up on https://github.com/GBGamer/SLED
The problem is that char* filename is just a pointer to some memory containing characters. It does not own any memory itself.
When you use the command line argument, the program handles storing that string somewhere, and you get a pointer to it. When you try to read using cin >> filename there isn't actually anywhere to store the read data.
Solution: Replace char* filename with std::string filename (and #include <string>).
Then to open the output file, you need a c-style string (null terminated char array). std::string has a function for this. You would write
std::ofstream out(filename.c_str());
^^^^^
Or, in fact, if you can use a recent compiler with c++11 features, you don't even need to use c_str(). A new std::ofstream constructor has been added to accept a std::string.
Your filename variable points to argv[1] when command line argument is provided, it does not need memory to be allocated but when going in else block, you have not allocated memory to filename. Its just a pointer.
Use malloc to assign filename some memory then take user input.
filename = (char *)malloc(sizeof(char)*(FILE_NAME_LENGTH+1))