Read file with variable name C++ - c++

I am trying to open a different file for different levels and need a variable name to do so. I tried the following but gave the error: "no suitable conversion from string to const char"
void loadMap(){
//string levelname;
//levelname = '../Levels/Level' + level;
FILE *file;
file = fopen("../Levels/Level" + level + ".txt", "r"); //THIS LINE IS GIVING THE ERROR
char section[80];
int index = 0;
int x = 0;
int y = 0;
while(true){
fscanf(file, "%s", section);
if(strcmp(section, "[Victor]") == 0){
while(true){
fscanf(file, "%d%d%d", &index, &x, &y);
if(index == -1){
break;
}
victor.x = x;
victor.y = y;
}
}
...
...
//more code

First of all, you should be using std::ifstream, it's the C++ way(tm).
Secondly, concatenation of strings should be done using std::stringstream from the header sstream, here's an example of how this could be accomplished:
#include <iostream>
#include <sstream>
#include <fstream>
int main() {
std::string level = "test";
std::stringstream ss;
ss<<"../Levels/Level"<<level<<".txt";
std::ifstream file(ss.str());
if(!file.is_open()) {
// error
} else {
// continue
}
}

"../Levels/Level" + level + ".txt" is evaluated to string object but fopen() takes const char* as first argument. You can fix it in following way:
fopen(("../Levels/Level" + level + ".txt").c_str(), "r");

FILE *file;
char buf[50];
snprintf(buf, sizeof(buf),"%s%d.txt","../Levels/Level",level);
file = fopen(buf, "r");

Related

how to make 10 copies of initial file, if first file is as-1.txt second should be as-2.txt and so on

Loop isn't making 10 copies and i have no idea how to change file names
#include "iostream"
#include "fstream"
#include "windows.h"
using namespace std;
void main()
{
char str[200];
ifstream myfile("as-1.txt");
if (!myfile)
{
cerr << "file not opening";
exit(1);
}
for (int i = 0; i < 10; i++)
{
ofstream myfile2("as-2.txt");
while (!myfile.eof())
{
myfile.getline(str, 200);
myfile2 << str << endl;
}
}
system("pause");
}
Solution using plain C API from <cstdio>. Easily customizable.
const char* file_name_format = "as-%d.txt"; //Change that if you need different name pattern
const char* original_file_name = "as-1.txt"; //Original file
const size_t max_file_name = 255;
FILE* original_file = fopen(original_file_name, "r+");
if(!original_file)
//file not found, handle error
fseek(original_file, 0, SEEK_END); //(*)
long file_size = ftell(original_file);
fseek(original_file, 0, SEEK_SET);
char* original_content = (char*)malloc(file_size);
fread(original_content, file_size, 1, original_file);
fclose(original_file);
size_t copies_num = 10;
size_t first_copy_number = 2;
char file_name[max_file_name];
for(size_t n = first_copy_number; n < first_copy_number + copies_num; ++n)
{
snprintf(file_name, max_file_name, file_name_format, n);
FILE* file = fopen(file_name, "w");
fwrite(original_content, file_size, 1, file);
fclose(file);
}
free(original_content);
(*) As noted on this page, SEEK_END may not necessarily be supported (i.e. it is not a portable solution). However most POSIX-compliant systems (including the most popular Linux distros), Windows family and OSX support this without any problems.
Oh, and one more thing. This line
while (!myfile.eof())
is not quite correct. Read this question - it explains why you shouldn't write such code.
int main()
{
const int copies_of_file = 10;
for (int i = 1; i <= copies_of_file; ++i)
{
std::ostringstream name;
name << "filename as-" << i << ".txt";
std::ofstream ofile(name.str().c_str());
ofile.close();
}
return 0;
}
That will make 10 copies of a blank .txt file named "filename as-1.txt" "filename as-2.txt" etc.
Note also the use of int main: main always has a return of int, never void

reading a .txt save file in CPP and save the value to local variable

i'm new in C++ (and file input output), I learned how to use fprint to print something from a .txt in a formatted style, but how do I search for a certain value and save that value in a local variable? below is the code for save:
void savestate(state a){ //state is a struct with data I need such as position etc
FILE * save;
int data[]= { a.level, a.goalX, a.goalX, a.monX, a.monY };
save = fopen("game.txt", "wb"); // << might have to use suggestion C
fwrite(data, sizeof(int), sizeof(data), save); // is this actually the correct way to do it?
fclose(save);
}
as for load, I'm stuck with this:
void loadstate(){
FILE* save;
save = fopen("game.txt", "rb");
if(save== NULL) perror("no savegame data");
else{
// don't even know what function I should use
}
and by the way, after I activate the save function, the game.txt is not in a quite readable format. I can open in in my notepad, but it shows something like ÌÌÌÌÌÌÌÌøäÁ_ÌÌÌÌúƒ which makes no sense. any idea? :D
Use text file for this purpose, not a binary file. The saveData function
will create the data.txt file and then the function loadData reads the data from the file. I you want some more explanation leave a comment below.
#include <stdio.h>
#include <stdlib.h>
void saveData() {
FILE* f = fopen("data.txt", "w");
if(f == NULL) {
printf("cant save data");
return;
}
//write some data (as integer) to file
fprintf(f, "%d %d %d\n", 12, 45, 33);
fprintf(f, "%d %d %d\n", 1, 2, 3);
fprintf(f, "%d %d %d\n", 9, 8, 7);
fclose(f);
}
void loadData() {
int data1, data2, data3;
FILE* f = fopen("data.txt", "r");
if(f == NULL) {
printf("cant open file");
return;
}
//load data from file, fscanf return the number of read data
//so if we reach the end of file (EOF) it return 0 and we end
while(fscanf(f, "%d %d %d", &data1, &data2, &data3) == 3) {
printf("data1 = %d data2 = %d data3 = %d\n", data1, data2, data3);
}
fclose(f);
}
int main() {
saveData();
loadData();
return 0;
}
example of writing to a file:
#include<fstream>
#include<iostream>
#include<string>
using namespace std;
int main(){
int i = 78;
string word = "AWord";
ofstream fout("AFile", ios_base::out | ios_base::binary | ios_base::trunc);
fout << i;
fout << endl;
fout << word;
fout.close();
return 0
}
example of reading from a file :
#include<fstream>
#include<iostream>
#include<string>
using namespace std;
int main(){
int ix;
string wordx;
ifstream fin("AFile", ios_base::in | ios_base::binary);
fin >> ix;
while(fin.get() != '\n'){
fin.get();
}
fin >> wordx;
fin.close();
return 0
}

Read multiple .dat files in C++

I used the code below to read one .dat file and find the execution time, it worked very well. I tried to build a loop to read multiple files as I have more than 20 files with different names (I need to keep their names), but it did not work. How can I develop this code to read all files located in a certain folder no matter how many they are? (based on following code)
#include <Windows.h>
#include <ctime>
#include <stdint.h>
#include <iostream>
using std::cout;
using std::endl;
#include <fstream>
using std::ifstream;
#include <cstring>
/* Returns the amount of milliseconds elapsed since the UNIX epoch. Works on both
* windows and linux. */
uint64_t GetTimeMs64()
{
FILETIME ft;
LARGE_INTEGER li;
/* Get the amount of 100 nano seconds intervals elapsed since January 1, 1601 (UTC) and copy it
* to a LARGE_INTEGER structure. */
GetSystemTimeAsFileTime(&ft);
li.LowPart = ft.dwLowDateTime;
li.HighPart = ft.dwHighDateTime;
uint64_t ret;
ret = li.QuadPart;
ret -= 116444736000000000LL; /* Convert from file time to UNIX epoch time. */
ret /= 10000; /* From 100 nano seconds (10^-7) to 1 millisecond (10^-3) intervals */
return ret;
}
const int MAX_CHARS_PER_LINE = 512;
const int MAX_TOKENS_PER_LINE = 20;
const char* const DELIMITER = "|";
int main()
{
// create a file-reading object
ifstream fin;
fin.open("promotion.txt"); // open a file
if (!fin.good())
return 1; // exit if file not found
// read each line of the file
while (!fin.eof())
{
// read an entire line into memory
char buf[MAX_CHARS_PER_LINE];
fin.getline(buf, MAX_CHARS_PER_LINE);
// parse the line into blank-delimited tokens
int n = 0; // a for-loop index
// array to store memory addresses of the tokens in buf
const char* token[MAX_TOKENS_PER_LINE] = {}; // initialize to 0
// parse the line
token[0] = strtok(buf, DELIMITER); // first token
if (token[0]) // zero if line is blank
{
for (n = 1; n < MAX_TOKENS_PER_LINE; n++)
{
token[n] = strtok(0, DELIMITER); // subsequent tokens
if (!token[n]) break; // no more tokens
}
}
// process (print) the tokens
for (int i = 0; i < n; i++) // n = #of tokens
cout << "Token[" << i << "] = " << token[i] << endl;
cout << endl;
}
uint64_t z = GetTimeMs64();
cout << z << endl;
system("pause");
}
For listing files in a directory on Windows, refer to this link:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365200(v=vs.85).aspx
Notes about your code:
don't use fin.eof() to test the end of input, see why: eof of istream in C++
to read multiple files, remember fin.clear() before fin.close if you use the same fin to read multiple files.
UPDATE:
The following code prints out the files name in a directory D:\\Test. If you need absolute path for every file or files in subfolders, change GetFiles to do that. This is pretty straightforward according to the link I provided. The code is test on VS2012 Win7 Pro.
#include <windows.h>
#include <Shlwapi.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
#pragma comment(lib, "Shlwapi.lib")
int GetFiles(const string &path, vector<string> &files, const string &wildcard = "\\*")
{
wstring basepath(path.begin(), path.end());
wstring wpath = basepath + wstring(wildcard.begin(), wildcard.end());
WIN32_FIND_DATA ffd;
HANDLE hFind = INVALID_HANDLE_VALUE;
DWORD dwError = 0;
hFind = FindFirstFile(wpath.c_str(), &ffd);
if (INVALID_HANDLE_VALUE == hFind) {
// display error messages
return dwError;
}
TCHAR buf[MAX_PATH];
do {
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// directory
} else {
PathCombine(buf, basepath.c_str(), ffd.cFileName);
wstring tmp(buf);
files.push_back(string(tmp.begin(), tmp.end()));
}
} while (FindNextFile(hFind, &ffd));
dwError = GetLastError();
if (ERROR_NO_MORE_FILES != dwError) {
// some errors
}
FindClose(hFind);
return dwError;
}
int main()
{
string path("D:\\Documents\\Visual Studio 2012\\Projects\\SigSpatial2013");
vector<string> files;
GetFiles(path, files);
string line;
ifstream fin;
for (int i = 0; i < files.size(); ++i) {
cout << files[i] << endl;
fin.open(files[i].c_str());
if (!fin.is_open()) {
// error occurs!!
// break or exit according to your needs
}
while (getline(fin, line)) {
// now process every line
}
fin.clear();
fin.close();
}
}
I think it's easier:
1- if you factor out the code that reads a file and process its content into its own function: void process_file( char* filename );
2- add a new function to list a directory's content: char** list_dir( char* dir );
3- combine the 2 functions in your main()
this makes for cleaner and more testable code
I agree with the suggestions to encapsulate this.
On Windows the code looks like this
HANDLE h;
WIN32_FIND_DATA find_data;
h = FindFirstFile( "*.dat", & find_data );
if( h == INVALID_HANDLE_VALUE ) {
// Error
return;
}
do {
char * s = find_data.cFileName;
// Your code here
} while( FindNextFile( h, & find_data ) );
FindClose( h );

Reading popen results in C++

I am writing a C++ application and I need to read the result of a system command.
I am using popen() more or less as shown here:
const int MAX_BUFFER = 2048;
string cmd="ls -l";
char buffer[MAX_BUFFER];
FILE *stream = popen(cmd.c_str(), "r");
if (stream){
while (!feof(stream))
{
if (fgets(buffer, MAX_BUFFER, stream) != NULL)
{
//here is all my code
}
}
pclose(stream);
}
I've been trying to re-write this in a different way. I saw some non-standard solutions like:
FILE *myfile;
std::fstream fileStream(myfile);
std::string mystring;
while(std::getline(myfile,mystring))
{
// .... Here I do what I need
}
My compiler does not accept this though.
How can I read from popen in C++?
Your example:
FILE *myfile;
std::fstream fileStream(myfile);
std::string mystring;
while(std::getline(myfile,mystring))
Does't work because although you're very close the standard library doesn't provide an fstream that can be constructed from a FILE*. Boost iostreams does however provide an iostream that can be constructed from a file descriptor and you can get one from a FILE* by calling fileno.
E.g.:
typedef boost::iostreams::stream<boost::iostreams::file_descriptor_sink>
boost_stream;
FILE *myfile;
// make sure to popen and it succeeds
boost_stream stream(fileno(myfile));
stream.set_auto_close(false); // https://svn.boost.org/trac/boost/ticket/3517
std::string mystring;
while(std::getline(stream,mystring))
Don't forget to pclose later still.
Note: Newer versions of boost have deprecated the constructor which takes just a fd. Instead you need to pass one of boost::iostreams::never_close_handle or boost::iostreams::close_handle as a mandatory second argument to the constructor.
Here is something which i wrote long back, may help you. It might have some errors.
#include <vector>
#include <string>
#include <stdio.h>
#include <iostream>
bool my_popen (const std::string& cmd,std::vector<std::string>& out ) {
bool ret_boolValue = true;
FILE* fp;
const int SIZEBUF = 1234;
char buf [SIZEBUF];
out = std::vector<std::string> ();
if ((fp = popen(cmd.c_str (), "r")) == NULL) {
return false;
}
std::string cur_string = "";
while (fgets(buf, sizeof (buf), fp)) {
cur_string += buf;
}
out.push_back (cur_string.substr (0, cur_string.size () - 1));
pclose(fp);
return true;
}
int main ( int argc, char **argv) {
std::vector<std::string> output;
my_popen("ls -l > /dev/null ", output);
for ( std::vector<std::string>::iterator itr = output.begin();
itr != output.end();
++itr) {
std::cout << *itr << std::endl;
}
}

Outputting from file one line at a time

I'm trying to output text from a file one line at a time. I'm currently hardcoding it and I have this so far:
int main(int argc, char *argv[])
{
int x;
int k;
int limit = 5;
FILE *file;
file = fopen("C:\\Documents and Settings\\jon\\My Documents\\Visual Studio 2008\\Projects\\Project1\\Assignment8_2\\Debug\\TestFile1.txt", "r");
if (file == NULL) {
perror("Error");
}
for (k = 1; k <= limit; k++) {
while ((x = fgetc(file)) != '\n') {
printf("%c", x);
}
}
fclose(file);
}
I was wondering where in the code above, if at all, I can check for EOF. I assume I need to do that, but not sure why. Still learning.... Thanks!
If you can bound the maximum length of a line, fgets may be a better way to read each line; but since you mention C++, you might consider using, instead, getline (caveat: fgets also put the \n in the buffer it fills, getline doesn't). Both make easy to check for end of file (fgets returns NULL on eof, getline sets the eofbit on its istream argument, which it also returns).
Maybe you can try this:
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
int main() {
int sum = 0;
int x;
ifstream inFile;
inFile.open("test.txt");
if (!inFile) {
cout << "Unable to open file";
exit(1); // terminate with error
}
while (inFile >> x) {
sum = sum + x;
}
inFile.close();
cout << "Sum = " << sum << endl;
return 0;
}
fgets() for C, getline() for C++.
C:
#include <stdio.h>
#include <stdlib.h>
// adjust as appropriate
size_t const MAX_LINE_LENGTH = 1024;
int main()
{
FILE * in;
char line[ MAX_LINE_LENGTH ];
if ( ( in = fopen( "test.txt", "r" ) ) == NULL )
{
puts( "Failed to open test.txt." );
return EXIT_FAILURE;
}
while ( fgets( line, MAX_LINE_LENGTH, in ) != NULL )
{
printf( "%s", line );
}
fclose( in );
return EXIT_SUCCESS;
}
C++:
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::ifstream in( "test.txt" );
std::string line;
while ( getline( in, line ) )
{
std::cout << line << std::endl;
}
in.close();
return 0;
}
you can call feof() to check for EOF or check if the return code for fgetc() matches EOF.
I'm adding both versions to your code although I'm not sure what the loops (especially the outer one) are supposed to do, but within the context of your sample, EOF checking would look like this..
/* EOF would now terminate both loops, using feof() and fgetc() return to check EOF */
for (k = 1; k <= limit && !feof(file); k++) {
while ((x = fgetc(file))!='\n' && x!=EOF) {
printf("%c", x);
}
}
you should check the eof from the output of fgetc:
...
x = fgetc(file);
while (x != '\n' && x != EOF) {
...
fgetc manual there