Segmentation fault while using "ifstream" - c++

I'm trying to get a part of text in a file.
I used "ifstream":
#include <fstream>
void func(){
char *myString;
ifstream infile;
infile.open("/proc/cpuinfo");
while (infile >> myString){
if (!strcmp(myString,"MHz"))
break;
}
}
and I get a "Segmentation fault". does anyone know why?

You have not allocated memory for the myString. Use std::string. Or better any other language, python, perl, or unix utils such as grep, awk, sed.

Because the target value should be:
std::string myString;
and not char*. It's possible to use char*, but you have to ensure that it points to something big enough first. (In your case, it doesn't point anywhere—you forgot to initialize it.) And defining “big enough” is non-trivial, given that you don't know the size of the next word until you've read it.

There's a reason why C++ has a string class, you know. It's because using char pointers is cumbersome and error-prone.
infile >> myString
will read from the file into *wherever myString points to. And it is an uninitialized pointer, it points to some random garbage address.
If you absolutely do want to use char pointers instead of strings, you'll have to allocate a buffer you can read data into.
But the sane solution is to replace it entirely by std::string.

Because you did not allocate memory for myString. The quick solution to this is to use std::string instead of the C-style char* strings, which does memory management so you don't have to.
Here's why your error occurs:
When you declare char *myString you are creating a pointer to a character. However you do not initialize this pointer to anything, so it can point absolutely anywhere in memory. When you do infile >> myString you are going to write a bunch of characters at an unspecified location in memory. It just so happens that this location was a vital part of your program, which caused it to crash.

char myString[256] compiles fine just as well too.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void func()
{
char myString[256] ;
ifstream infile;
infile.open("/proc/cpuinfo");
while ( ! infile.eof() )
{
infile >> myString;
cout<<myString<<" \n";
if (! strcmp(myString,"MHz") )
{
infile.close();
break;
}
}
infile.close();
cout<<" \n";
}
int main()
{
func();
return 0;
}

Related

c++: problem while copying string into character array

I am trying to copy contents of a file into fields in a class courseInfo.
this is the code im using:
#include<iostream>
#include<fstream>
#include<vector>
#include<sstream>
#include <bits/stdc++.h>
using namespace std;
class courseInfo
{
public:
char courseCode[8];
char courseName[80];
int ECTS;
};
int main()
{
ifstream fin("courses.txt");
if(!fin.is_open())
{
cout<<"file doesn't exist";
return 0;
}
string line;
vector<courseInfo> courses;
while(getline(fin,line))
{
stringstream linestream(line);
string segment;
vector<string> segmentlist;
while(getline(linestream, segment, ';'))
{
segmentlist.push_back(segment);
}
//cout<<segmentlist.at(0).c_str();
courseInfo c;
//segmentlist.at(0).copy(c.courseCode, segmentlist.at(0).size()+1);
//c.courseCode[segmentlist.at(0).size()] = '\0';
strcpy(c.courseCode, segmentlist.at(0).c_str());
cout<<c.courseCode<<"\n;
strcpy(c.courseName, segmentlist.at(1).c_str());
cout<<c.courseCode;
}
return 0;
}
content of courses.txt file:
TURK 101;Turkish l;3.
output i get:
TURK 101
TURK 101Turkish l
the contents of courseCode changes when i copy something into courseName.
why does this happen?
how do i rectify this?
Note how TURK 101 is exactly 8 bytes.
When you cout << c.courseCode, your program prints characters until it encounters a NUL byte. By accident, the first byte of c.courseName is NUL.
After you read into it, it is no longer NUL and thus printing c.courseCode happily continues into c.courseName.
Some options:
The most obvious (and recommended) solution is to use std::string in your struct instead of fixed-size char arrays.
However, this looks like a homework question, so you probably are not allowed to use std::string.
Use std::vector<char> instead, but that is probably also not allowed.
Make courseCode large enough to contain any possible course code, plus one character for the NUL-terminator. In this case, make courseCode 9 chars large.
Use heap-allocated memory (new char[str.size()+1] to allocate a char *, delete[] ptr to free it afterwards). And then change courseInfo to take regular pointers. Ideally all the memory management is done in constructors/destructors. See the rule of three/five/zero.

scanf function for strings

The problem is simple, the code below does not work. it says Process finished with exit code -1073740940 (0xC0000374). Removing ampersand does not change anything.
int main(){
string x;
scanf("%s",&x);
cout << x;
}
scanf() with the %s format specifier reads bytes into a preallocated character array (char[]), to which you pass a pointer.
Your s is not a character array. It is a std::string, a complex object.
A std::string* is not in any way the same as a char*. Your code overwrites the memory of parts of a complex object in unpredictable ways, so you end up with a crash.
Your compiler should have warned about this, since it knows that a char* is not a std::string*, and because compilers are clever and can detect mistakes like this despite the type-unsafe nature of C library functions.
Even if this were valid via some magic compatibility layer, the string is empty.
Use I/O streams instead.
You cannot pass complex objects through the ... operator of printf/scanf. Many compilers print a warning for that.
scanf requires a pointer of type char* pointing to sufficient storage for an argument of %s. std::string is something completely different.
In C++ the iostream operators are intended for text input and output.
cin >> x;
will do the job.
You should not use scanf in C++. There are many pitfalls, you found one of them.
Another pitfall: %s at scanf is almost always undefined behavior unless you you really ensure that the source stream can only contain strings of limited size. In this case a buffer of char buffer[size]; is the right target.
In any other case you should at least restrict the size of the string to scan. E.g. use %20s and of course a matching char buffer, char buffer[21];in this case. Note the size +1.
You should use cin. But if you want to use scanf() for whatever reason and still manipulate your strings with std::string, then you can read the C-string and use it to initialize your C++ string.
#include <iostream>
#include <cstdio>
#include <string>
using std::cout;
using std::string;
int main()
{
char c_str[80];
scanf("%s", c_str);
string str(c_str);
cout << str << "\n";
}
If you want to use strings, use cin (or getline).
string s;
cin>>s; //s is now read
If you want to use scanf, you want to have a char array (and don't use &):
char text[30];
scanf("%s", text); //text is now read
You can use char[] instead of string
include <iostream>
using namespace std;
int main()
{
char tmp[101];
scanf("%100s", tmp);
cout << tmp;
}

how can I convert istream * to string or just print it?

The below function part of connector/C++, it returns a istream*. if i just try and print it, it shows hex or a memory location because its a * type.
istream *stream = res->getBlob(1);
I tried to read & print it with this:
string s;
while (getline(*stream, s))
cout << s << endl;
But this crashes with access violation though. any other way i can print it or convert to string?
the value of stream before the getline:
stream 0x005f3e88 {_Chcount=26806164129143632 } std::basic_istream > *
so it seems that its valid to me. I think it would be null or 0 if it failed
You can extract and print a std::istream by using its stream buffer:
std::cout << in->rdbuf();
Of course, this will consume the input and you may not be able to get it again. If you want to keep the content, you could write it an std::ostringstream instead and print the content using the str() method. Alternatively, you can directly construct a std::string from a stream, too, e.g.:
std::string content{ std::istreambuf_iterator<char>(*in),
std::istreambuf_iterator<char>() };
BTW, when you printed your stream pointer, you actually used the output operator for void const*: it prints the address the pointer is referring to. In C++03 you could even restore a correspondingly printed pointer by reading a void* using an std::istream: as long as the pointed to object wasn't deleted, you could get a pointer back that way! In C++11 pointer hiding is prohibited, however, to support optional garbage collection which may or may not be added to the language in the future. The guarantee about non-hidden pointers also helps member debuggers, though.
You can use the std::getline function in the while loop to display the data in the istream. Here is an example that I ran and it worked correctly:
#include <iostream>
#include <sstream>
#include <istream>
#include <string>
int main()
{
std::stringstream s1("This is a test string\nWith two lines");
std::istream s2(s1.rdbuf()); //just creates the istream to start with
std::string stt;
while(std::getline(s2,stt)) //can also have delimiter in getline
{
std::cout<<stt<<std::endl;
}
return 0;
}
Run it and it displays:
This is a test string
With two lines
I also tried this so that I was using pointer to the istream like you have:
#include <iostream>
#include <sstream>
#include <istream>
#include <string>
int main()
{
std::stringstream s1("This is a test string\nWith three lines);
std::istream s2(s1.rdbuf()); //just creates istream to start with
std::istream *s3 = &s2; //and use a pointer to istream like code at top
std::string stt;
while(std::getline(*s3,stt,'\n'))
{
std::cout<<stt<<std::endl; //result.
}
return 0;
}
This code ran and gave the same result as I got without using the pointer. I was unable to reproduce your error. So the problem looks like the creation of your istream (e.g. istream *stream = res->getBlob(1);).

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.

How to read in a bunch of strings in C++?

I need to read in a bunch of strings without knowing in advance how many are there and print them as they are read. So I decided to use while(!feof(stdin)) as an EOF indicator.Here is my code:
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
int main(void)
{
char* str;
std::cout<<"\nEnter strings:";
while(!feof(stdin))
{
std::cin>>str;
std::cout<<"\nThe string you entered is"<<str;
}
return 0;
}
The above code for some reason says segmentation fault after I enter the first string.Can someone suggest a fix for that.
You need to allocate some memory for the string you are reading to go into.
All you have currently is a pointer on the stack to some random memory area, which means that as you read characters they will stomp all over other data, or even memory you aren't allowed to write to - which then causes a segfault.
The problem with trying to allocate some memory is that you don't know how much to allocate until the string is read in... (You could just say "300 chars" and see if it's enough. But if it isn't you have the same problem of data corruption)
Better to use C++ std::string type.
str is a pointer to char. It doesn't point anywhere valid when you try to write there.
Try some form of new in C++, or, better yet since you're coding C++, use std::string.
str is declared as char* str, which means it isn't really a string (just a pointer to it, uninitialized BTW), and doesn't allocate any space for it. That's why it seggfaults. Since you program in c++, you can use
std::string str;
and it will work. Don't forget to #include <string>.
A segmentation fault occurs when an application tries to access a memory location that it isn't allowed. In your case the problem is that you are dereferencing a non-initialized pointer: char* str;
A possible solution would be change the pointer to an array, with a suitable size
Something like this may suffice:
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
int main(void)
{
char str[20];
cout<<"\nEnter strings:";
while(!feof(stdin))
{
cin.width(20); //set a limit
cin>>str;
cout<<"\nThe string you entered is"<<str;
}
return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
int main(void)
{
std::string str[300];
std::cout<<"\nEnter strings:";
while(!std::cin.eof())
{
std::cin>>str;
std::cout<<"\nThe string you entered is"<<str;
}
return 0;
}
Should do the trick