Segmentation fault when trying to get string from input - c++

#include <iostream>
using namespace std;
int main() {
char *s;
printf("enter a word \n");
scanf("%s", s);
int i;
for (i = 0; s[i] != '\0'; i++) {
}
printf("length is = %d", i);
return 0;
}
When I compile this program, a segmentation fault occurs.
Can anyone plz tell me, what is the problem in this code?

char *s;
Is unitialized, you can't assign an input stream to it until it is.
char s[100]; //space for 99 characters plus null terminator
or
char* s = malloc(100); //each char has the size of one byte
These are C tools, for C++, however, you can/should use std::string, with std::cin instead of scanf.
std::string s;
std::cin >> s;
If you must use C tools, scanf("%s", s); is not the most safe method, if you don't pass the size of the char array container, changing specifier %s to %100s or changing it altogether to a safer function like fgets(s, sizeof(s), stdin); is a better option.

char *s;
You created a pointer, though it does not point to anything (it is uninitialized).
scanf("%s",s);
You try to read data into the string pointed-to by s, but no such thing exists.
💥!
Allocate some memory and have s point to it… or, better yet, use std::string and std::cin.

char *s;
printf("enter a word \n");
scanf("%s",s);
scanf with %s does not allocate memory, instead it reads into the buffer you provide it (e.g. s = malloc(100);. How big does that buffer need to be to avoid a buffer overflow? Unfortunately it can be however long until a whitespace character, so is inherently unsafe.
You can specify a max up front (not including null terminator!), but to handle variable size you then need to dynamically build the format string which gets complicated. As does what to do if the user enters a string too long.
char s[100];
scanf("%99s", s);
Since you tagged C++, you can use std::string and IO streams (e.g. std::cin for console input) which will handle all the memory allocation for you.
std::string s;
std::cout << "enter a word" << std::endl;
std::cin >> s;
In the case of C, you might use fgets(str, num, stream), this lets you specify the max length and avoid overflow in a simple manner.
char s[128];
fgetsf(s, 100, stdin);
Or with the POSIX 2008 scanf it can allocate the memory, but I don't believe this is universally supported, e.g. by Microsoft Visual Studio.
char *s = 0;
scanf("%ms", &s); // pass a pointer to a pointer!
free(s); // needs to be freed later!

Related

Reading unlimited length input line without using string

I would like to read unlimited length line of text from the input. I wish not to use string or any of it.
I tried that but it seems does not work. I always get the same output.
I do not want to use: string, the input has to be of any length.
#include <iostream>
#include <stdio.h>
using namespace std;
char * getline(){
char * buf = new char[10];
int result = scanf("%as\n", &buf);
if (result < 0) {
if (NULL != buf)
delete []buf;
return NULL;
}
return buf;
}
int main(){
char* haha = getline();
cout <<haha << endl;
return 0;
}
char * buf; just creates the pointer variable, but does not allocate memory.
use: buf = new char[...].
Obviously, since your computer has not got unlimited memory, you will need to specify a size instead of ...
And delete it as: delete [] buf
But, I think the best solution is:
std::string s;
std::cin >> s;
You can't read into a buffer that doesn't exist! Here buf points to an undefined location in memory, and the most likely outcome of this code is a crash. You must allocate some space (using new[]) before you can read data into it; and of course, that space must be of some well-defined size. You can always allocate a new, large buffer at any time, and copy the contents of the smaller one into it; this is how you "grow" memory blocks in C++, and it's how string works internally.

Segmentation Fault in C++ most probably in strtok operation

I was writing a postfix evaluation program which could handle multiple digits. Therefore I first read the inputs to a character array, and split them to array of (character array). Whenever I run my program, it gives a segmentation error (g++ on Ubuntu 13.10)
Here's my function to split
int split(char str[], char *ret[]){
int c=0;
char * pch;
pch = strtok (str," ");
while (pch != NULL)
{
//printf ("%s\n",pch);
strcpy(ret[c], pch); c++;
//cout<<ret[c];
pch = strtok (NULL, " ");
}
return c;
}
And part of my main()
char* s;
s = new char[200];
cout<<"Enter Postfix Expression:\n > ";
cin.getline(s,200);
char* st[200];
//int size=3;
int size = split(s, st); // < Is what I'm passing correct?
I could not understand why the segfault occurred. Any suggestions?
EDIT: Thanks to yugnum for the answer. The following did the trick
...
ret[c] = new char[strlen(pch)];
strcpy(ret[c], pch); c++;
...
char* st[200];
int size = split(s, st);
int split(char str[], char *ret[]){
...
strcpy(ret[c], pch);
...
}
this is what is wrong, you just pass bunch of uninitialized pointers to strcpy while it requires pointer that points to valid allocated memory.
You need to define st as 2D array, so split function will return an array of split strings
For example:
char st[20][200]
and then:
int split(char str[], char *ret[][]){
So you'll have 20 of 200 byte char array.
But it's not safe at all, I suggest you considering something else like vector or std::string. Also you need to allocate your array before strcpy.
Then
strcpy(ret[c], pch);
with c as counter, will copy split new string to your char array.
But consider std::string, which is best choice

C++ char* problems [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
#include<iostream>
using namespace std;
int main()
{
char *name="Siva",*str;
for(int i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
cout<<str;
return 0;
}
The first program gives output Sivaœ> i.e siva with some garbage values....
But the second program show segmentation fault...Please help me to find out
exact answer...
#include<iostream>
using namespace std;
int main()
{
int i=0;
char *name="Siva",*str;
for(i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
cout<<str;
return 0;
}
char *name="Siva",*str;
for(int i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
str is a pointer, but it doesn't yet point to anything.
Since you're in C++, you should be using std::string:
#include<iostream>
#include <string>
using namespace std;
int main()
{
char *name="Siva";
std::string str;
for(int i=0;i<strlen(name);i++)
{
str += name[i];
}
cout<<str;
return 0;
}
Even better, get rid of the hand-written loop:
#include <algorithm>
int main()
{
char *name="Siva";
std::string str;
std::copy (name, name + strlen (name), std::back_inserter (str));
cout<<str;
return 0;
}
Better even still, there's no reason in this particular example why you need to do any of that at all:
char* name = "Silva";
std::string str = name;
cout << str;
By the way, string literals in C++ are inherently const:
const char* name = "Silva";
If you really must use a char*, first I would strongly question why, and then I would tell you to do this:
int main()
{
const char *name="Siva";
char* str = new char [strlen (name)+1]; // +1 for the null terminator
strcpy (name, str);
cout << str;
delete [] str;
return 0;
}
I would even more strongly question your need to copy it byte-by-byte:
int main()
{
const char *name="Siva";
char* str = new char [strlen (name)+1]; // +1 for the null terminator
for (size_t i = 0; i < strlen (name); ++i )
str [i] = name [i];
str [strlen (name)] = '\0';
cout << str;
delete [] str;
return 0;
}
You have undefined behaviour here:
str[i]=name[i];
str has not been initialized to anything. You are writing to places you shouldn't.
There are two problems with this.
The pointer str doesn't point to allocated memory, so writing through it is undefined behavior.
Even if it did point to valid memory, you're not writing the correct amount of data. When copying a string, you need to copy the 0 byte at the end which marks the end of the string; so the upper limit of your loop should bt strlen(name) + 1. Or you could use a library method like strdup() instead of your own for loop.
The reason the "working" version prints some garbage characters is that there's no 0 at the end of the copied string to tell iostreams to stop printing. The reason the "working" one doesn't crash, and the other one does, is pure dumb luck: the garbage in str, by chance, points to memory you're allowed to write to, while in the crashing program, it points to memory you're not allowed to write to. Simple as that.
It is because you have no memory allocated for str. (it will cause an undefined behavior)
You can mix that by using a merory allocation function like in this example :
#include<iostream>
using namespace std;
int main()
{
char *name="Siva",*str;
// Allocate memory with malloc
str = (char*)malloc( (strlen(name)+1) * sizeof(char) );
for(int i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
str[strlen(name)] = 0;
cout<<str;
// Free the allocated memory
free(str);
return 0;
}
As you are using c++, you can do :
#include<iostream>
using namespace std;
int main()
{
char *name="Siva",*str;
// Allocate memory with new
str = new char[strlen(name) + 1];
for(int i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
str[strlen(name)] = 0;
cout<<str;
// Free the allocated memory
delete []str;
return 0;
}
EDIT :
The reason you have some weird caracters at the end of your ouput is that because you string is not terminated with a '\0', it will continue to print it. (This will occur only if you don't have a segmentation fault )
There are a couple problems with your code.
Firstly, *str is not allocated, so it starts off by pointing to whatever bit of memory the pointer value happens to start off as.
Secondly, strlen() returns the length of the string excluding the terminating null character. So what you are doing is copying all the values of name into some random bit of memory, not terminating it, then telling the system to print that off, which could be any length.
str[i]=name[i]; is illegal, causes Undefined behavior, because you have not allocated memory for str.
Before for loop allocate memory for destination string str:
str = malloc (strlen(name) + 1 );
Also you forgetting string termination, after for-loop add terminate string str[i] = '\0';
Undefined behavior refers to computer code whose behavior is unpredictable.
You code should be:
char *name="Siva", *str;
str = malloc (strlen(name) + 1 ); // mistake
for(int i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
str[i] = '\0'; // forgetting
To understand further you can read this answer: strcat() implementation works but causes a core dump at the end
Your problem is using char arrays and pointers to represent strings in language which has proper string type.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string name = "Siva", str;
str = name;
cout << str;
return 0;
}
Problem is with str[i]=name[i] you must know that C++ does not care for memory leaks
as Java or some others. So you must allocate memory to a variable or pointer in order to avoid these problems. Already there are number of answers, you can also try
str=new char[strlen(name)+1];
and do not forget to terminate the char array with null when you done copy. In this case
str[strlen(name)]='\0';

Concatenating two strings iteratively in C++

I know a string concatenation question has been asked to death in SE. But to the best of my knowledge,I've gone through all the questions that could help me, in vain.
This is what I am hoping to accomplish with this program:
Initially I have a=0 and b=1, for n=0 and n=1 respectively.
For the next input i.e from n=3 onwards, my result should be concatenation of the previous two strings. (Like a Fibonacci sequence; only the addition is replaced by concatenation)
So,for example:
For n=3, my output should be "10".
For n=4, my output should be "101"
For n=5, my output should be "10110"
There is no logical problem with the code I've written,but I'm getting a SIGSEGV error and I don't see why.
#include <iostream>
#include<new>
#include<string.h>
using namespace std;
int main()
{
long int n,i;
char *a="0";
char *b="1";
char *c=new char[100000];
cout<<"Enter a number n:";
cin>>n;
for(i=0;i<n;i++)
{
strcat(b,a);
strcpy(a,b);
}
cout<<"\nRequired string="<<b;
}
What am I doing wrong?
strcat(b,a); invokes undefined behaviour because b points to a string literal.
char * strcat ( char * destination, const char * source );
Concatenate strings
Appends a copy of the source string to the destination string.
Since this is C++, I suggest you use std::string and the + operator. Or a std::stringstream.
The problem that you are observing has to do with undefined behavior: you are writing to the memory that has been allocated to a string literal.
To avoid the issue, you should switch to using C++ std::string: it makes your code a lot simpler by taking memory management out of the picture.
string a("0");
string b("1");
int n = 10;
for(int i=0;i<n;i++) {
string tmp(a);
a = b;
b = tmp + b;
}
cout<<"Required string="<<b;
char *a="0";
char *b="1";
"0" and "1" are string-literals (a has address of "0" and b has address of "1"), change of its contains is undefined behaviour.
strcat(b,a);
strcpy(a,b);
UB.
Since you use C++ better use std::string or std::stringstream.
You have declared a and b as
char *a="0";
char *b="1";
These are pointers to constant strings. This means that the memory allocated to these pointers is fixed. When you write past this block of memory, Bad Things(TM) will happen.
You are using strcat but your destination string is a string literal. strcat is then attempting to write past that strings terminating null character and that is where the seg fault comes in. Just don't try to modify string literals at all. Since you have the luxury of using C++ unless this is a learning exercise you would be much better off using std::string.
You can use this code instead, I am showing to you that you need to think of the inital values of n = 1, 2
also you should handle wrong inputs with n < 0
and avoid dynamic allocation as you seems to use new for no obvious reason and you forgot to free the memory with delete at the end.
#include <iostream>
#include<new>
#include<string.h>
using namespace std;
int main()
{
long int n,i;
char a[10];
char b[10];
char c[10];
//char *c=new char[100000];
cout<<"Enter a number n:";
cin>>n;
strcpy(a, "0");
strcpy(b, "1");
if (n == 1)
strcpy(b, a);
else if (n > 2)
{
for(i=2;i<n;i++)
{
strcpy(c, a);
strcat(c, b);
strcpy(a, b);
strcpy(b,c);
}
}
else if (n != 2)
cout<<"\nInvalid input!";
cout<<"\nRequired string="<<b;
}

C++ Append character to std::string from int

I've got a character from the keyboard, by integer:
int c = getch();
an I want to append it to a string only if it isn't a return:
void somefunction()
{
std::string str = "you pressed: ";
int c;
while ( 1 )
{
c = getch();
if ( c == 10 ) break;
char* ch;
sprintf(ch,"%c",c);
str += std::string(ch);
}
}
however, this creates a segmentation error when the scope of somefunction is left. I'm geussing that when the dtor for str is called the pointer to ch isn't available any more.
How can I remedy this?
This is much easier than you think:
str.push_back(c);
You are getting segmentation fault, because you are trying to sprintf string into unknown (not yet allocated) memory:
char* ch;
sprintf(ch,"%c",c);
possible fix of your code would be to replace char* ch; with char ch[2]; which would cause ch to become an statically allocated array with an automatic storage duration.
But note that since you are programming in C++ it would be wiser to use streams and methods of std::string rather than C-style (char*) strings and C-style functions like sprintf.