segmentation fault while reading from a file - c++

I have a problem with the following code:
#include <iostream>
#include <stdio.h>
#include "ISBNPrefix.h"
using namespace std;
int main() {
FILE* file = NULL;
int area = 0, i = 0;
long s;
file = open("swagger.txt");
fscanf(file, "%ld", &s);
cout << s << endl;
}
and here's ISBNPrefix.cpp:
#include <iostream>
#include <stdio.h>
#include "ISBNPrefix.h"
using namespace std;
FILE* open(const char filename[]) {
FILE* file = NULL;
file = fopen("filename", "r");
if (file != NULL)
return file;
else return NULL;
}
my ISBNPrefix.h
FILE* open (const char filename[]);
And the content of swagger.txt is: 123456789
When I try to run it to test if it copies the 123456789 into my variable i get a segmentation fault!

You have problem in your function for opening a file:
FILE* open(const char filename[]) {
FILE* file = NULL;
file = fopen("filename", "r"); <-- here
it should be file = fopen(filename, "r");
Also you designed open function to return NULL if there is no file, but then you don't check its return value once you call it:
file = open("swagger.txt");
if (file == NULL) ... <-- you should check the return value
fscanf(file, "%ld", &s);
Also note that fopen and fscanf are C-style functions. Since you are using C++, there are other more convenient means how to read data from a file. Have a look at std::ifstream. Also when you work with C headers in C++, you should include their C++ wrappers: cstdio, cstdlib, etc.

You need fopen for a start. Where does ISBNPrefix.cpp come into the picture?

Related

Does't work fopen_s(&file, "filename", mode) in visual studio 2019 C_language

So this is my first question here. If you could help me, that would be much appreciated. This code is about my thesis. I'm trying to write to a file and it works but trying to read another file is not reading. I can't make it work. "file does not open" appears on the screen. Help me please, for read to file.
#include <cstdio>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main()
{
FILE* myfile;
errno_t errorcode = fopen_s(&myfile, "output.txt", "w");
if (myfile == NULL)
{
printf("Error");
}
FILE* data;
errno_t err = fopen_s(&data, "C:\SA\input.txt", "r");
//errno_t err = fopen_s(&data, "input.txt", "r");
if(data==NULL)
{
printf("file does not open");
}
return 0;
getchar();
}
The original code posted had 2 major issues:
"C:\SA\input.txt" should be "C:\\SA\\input.txt" or simply "C:/SA/input.txt". Microsoft's legacy systems use \ as a path separator which must be escaped in C strings as \\ (and in many other languages too). The traditional path separator on POSIX systems is / and it is also supported in Windows.
if(data==NULL); is a test with an empty statement, hence nothing happens.
Note that you should not use C++ headers such as <iostream> in a C program.
Here is a simplified version:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
FILE *myfile;
errno_t err = fopen_s(&myfile, "output.txt", "w");
if (err) {
fprintf(stderr, "Cannot open file %s: %s\n",
"output.txt", strerror(err));
return 1;
}
FILE *data;
err = fopen_s(&data, "C:\\SA\\input.txt", "r");
if (err) {
fprintf(stderr, "Cannot open file %s: %s\n",
"C:\\SA\\input.txt.txt", strerror(err));
return 1;
}
getchar(); // keep terminal window open
return 0;
}

Read file with variable name 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");

Segmentation fault executing file writing using FILE pointer

I get a "Segmentation fault" for the following C++ code:
#include <cstdio>
int main(int, char**) {
FILE *fp;
fp = fopen("~/work/dog.txt", "w");
fprintf(fp, "timer, timer3, timer5, timer6, timer7");
fclose(fp);
}
Your path is invalid and will never work, thus fopen sets fp to NULL and you get a segfault. Hint: the ~ character is expanded by the shell, you can't use it in an argument to fopen.
A correct, safe implementation of what you're trying to do might look as follows. This is tested. It's also the reason why sane people don't write in C unless they have no other way of doing it :)
// main.cpp
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
int main(int, char**)
{
const char * home = getenv("HOME");
if (home == NULL || strlen(home) == 0 || access(home, F_OK) == -1) abort();
const char * subPath = "/work/dog.txt";
char * path = (char*)malloc(strlen(home) + strlen(subPath) + 1);
if (path == NULL) abort();
strcpy(path, home);
strcat(path, subPath);
FILE *fp = fopen(path, "w");
if (fp != NULL) {
fprintf(fp, "timer, timer3, timer5, timer6, timer7");
fclose(fp);
}
free(path);
}
A few things:
you need to check fp for NULL before using it, else you'll get a segfault whenever the file isn't found.
you need to resolve the full path before passing it to fopen (fopen doesn't know what to do with "~")
example:
FILE *fp = NULL;
char path[MAX];
char *home = getenv ("HOME");
if ( home )
{
snprintf(path, sizeof(path), "%s/work/dog.txt", home);
// now use path in fopen
fp = fopen(path, "w");
if ( fp )
{
fprintf(fp, "timer, timer3, timer5, timer6, timer7");
fclose(fp);
}
else
{
std::cout << "your dog is missing" << std::endl;
}
else
{
std::cout << "You are homeless" << std::endl;
}
Segfault happens is the file you're trying to open does not exist. This has nothing to do with Qt.
Test for the nullity of 'fp' and handle the error correctly. Something like
FILE *fp = fopen("/path/to/work/dog.txt", "w");
if (fp == NULL)
{
printf("File does not exist.\n");
// throw exception or whatever.
}

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;
}
}

C++ File IO - can't find methods for File IO related stuff

#include "Shader.h"
#include <cstring>
#include <iostream>
#include <cstdlib>
using namespace std;
static char* textFileRead(const char *fileName)
{
char* text;
if (fileName != NULL)
{
FILE *file = fopen(fileName, "rt");
if (file != NULL)
{
fseek(file, 0, SEEK_END);
int count = ftell(file);
rewind(file);
if (count > 0)
{
text = (char*)malloc(sizeof(char) * (count + 1));
count = fread(text, sizeof(char), count, file);
text[count] = '\0';
}
fclose(file);
}
}
return text;
}
This is what I have for a shader program found in a tutorial I'm trying to follow. When I build this to check for errors, I get errors saying fopen(), fseek(), ftell(), rewind(), and fclose() isn't declared in this scope. How can I get rid of these errors?
You're using C file IO in a C++ program.
You included iostream.h, so use it.
http://www.cplusplus.com/reference/iostream/
You need add the header file for standard IO as follows:
#include <stdio.h>
or (c++ preferred)
#include <cstdio>