C++ char* in methods - c++

Listen people, i want to write a method that gets a line from the user, so i wrote this:
static char* getline(){
char temp[0];
cin >> temp;
return temp;
}
I also have a writeline method:
static void writeline(char* text){
cout<<text<<endl;
}
and then i go to the main and wrote this:
writeline(getline());
and it didnt work..
i want to say that when i wrote this:
static char* getline(){
char temp[0];
cin >> temp;
writeline(getline());
return temp;
}
and i wrote in main this:
getline();
it did work!
so what do i need to do?

There are a few things going on here.
First, you have to allocate memory when working with char*; a zero-length array won't be long enough. It's a lot easier to just use std::string which takes care of all the dirty work for you. Further, an array declared with a size in your function is allocated on the stack rather than the heap; once your getline function returns, the memory is no longer valid.
Second, the >> operator for strings reads the next word, not the next line. For that you need the getline method. Here comes the tricky thing: getline doesn't use std::string, so you still need the char*. You just don't want to return one, because then you need to deallocate it unless it's a global (or static) array. So, what you can do is the following:
std::string getline() {
char buf[1024]; // we have a cap on the line size
cin.getline(buf, 1024); // reads a line, up to 1023 characters
return std::string(buf); // makes a copy of buf into a properly-managed string
}
void writeline(const std::string &s) {
cout <<s <<endl;
}
Now you can do
writeline(readline());
and it should work fine. You can see here for more info on cin.getline().

There are two issues with your code.
First, you are trying to read a variable size input into a fixed-size array that is not a sufficient size - temp[0] may only be a single byte long. You are overruning the array and stomping on other data that is on the stack (like the return address.) This could cause a crash or odd behavior when the function returns.
Second, you are returning a local variable from a function. As soon as the function returns, the variable is out of scope and its stack space will be reused. You need to actually allocate memory if you are going to return it from a function.
The reason the second version works is that the stack-based array is still valid during the call to getline(), and since arrays grow downward getline() is immune to any stack corruption that was caused.

I think the problem is that your char temp[0] is defined inside the function (local to the function). Another problem i see is the temp[0], how many characters are you trying to allocate for the text input?

your returning corrupted memory, thats why
static char* getline(){
char temp[0];
cin >> temp;
return temp;
}
change this to
char temp[10000]; // put this outside in a class or global, give it some space
static char* getline(){
cin >> temp;
return temp;
}

There are a few things that are a bit suspect here.
First of all inside the getline() function you are declaring
char temp[0];
Which is an array of characters with no members. That can't possibly be what you intend.
Secondly your declaration of temp is as a variable on the stack. You can't use it as the return value of the function as it will go out of scope when you return.
Finally cin >> will only return a single character. Since your function is called getline I assume you want whole lines.
cin can do that for you using the getline function, but you need to pass it a buffer to put the line into.
See this reference:
http://www.cplusplus.com/reference/iostream/istream/getline/

Related

The memory returned by realloc is filled with random characters. Is this expected?

I am using realloc to expand the initial memory I have declared for a dynamically allocated array. I do not know the dimension of the input so i read it character by character, and when I detect that I exceed the memory that has initially been allocated I call realloc. Here is the Code:
void readLine(char *line, int &len) {
int newSize = expand;
char ch;
while(f >> noskipws >> ch) {
if (ch == '\n')
break;
if (++len >= newSize - 1) {
newSize += expand;
line = (char*)realloc(line, newSize);
}
line[len] = ch;
}
}
My problem is that after the program reallocs 'line' it fills it with various ASCII characters. Is this a normal behaviour?
after the program reallocs line it fills it with various ASCII characters.
realloc does not fill the memory that it returns back with anything. This random garbage is a leftover from whatever was using the memory before. Your code is not supposed to read any of the allocated bytes without writing something into it.
The reason you may see this random data is that your line is left unterminated. Add line[++len] = '\0'; after the loop to fix this problem.
An even bigger problem with your code is that line is a pointer passed to your function by value. This means that any re-assignments that you make will not be propagated to the caller. Moreover, if the caller passed you valid memory and you called realloc on it, the pointer in the caller would be invalidated on successful realloc.
To fix this problem pass line as a reference to pointer:
void readLine(char*& line, int &len) {
...
}
Note: I assume that you are doing this as an exercise in using realloc, because C++ Standard Library has built-in functionality for reading std::strings of arbitrary size.
Another important point is that you should not assign realloc to line right away. Instead, you should assign it to a temporary variable, check for NULL, and assign to line only if it passes the check. This would let you avoid memory leaks in situations when the system runs out of memory.

c++, reading files, segmentation fault

I was working on this function read. The main I used has no problem in file I/O, it connects fine, closes, the files are okay too. However, I am getting a segmentation fault by the end of the reading. I have tried printing out for testing, and the error is reading the last line. It finishes reading the last line for string a, and then x, and then in.good() becomes false too. I have tried resetting in.clear(), also, setting the string a=""; if in.good becomes false. Nothing is working.
read(istream& in){
string a;
int x;
in>>a;
while( in.good() ){
in>>x;
char *ch;
strcpy( ch, a.c_str() );
Word cwd(ch);
anObject.add(cwd,x);
}
}
You see a segfault because you're not allocating space for ch, and then you're attempting to copy a string over it. ch is an uninitialized memory address that doesn't belong to you.
You'll need to allocate space for the string:
char *ch = new[(MAX_SIZE + 1) * sizeof(char)];
But why is it that you need a char * here? Note that you can always pass around a and use a.c_str() if you must have a C string. I'm not sure what Word is, or if it needs it's own copy of a string, but can you use: Word cwd(a.c_str())?
It seems you don't allocate memory storage for char *ch. The moment you define this variable, it is a random value on the stack. Writing a random memory will corrupt the memory and cause seg fault when cleanup the memory(both manually or automatically at function return).

Why does the cin extraction operator cause a segfault?

#include <iostream>
using namespace std;
int main() {
char * c;
cin >> c;
return 0;
}
I'm trying to get a C string line from the user whose length is not known. I know that if I declared c as char c[80] instead of char * c then it wouldn't cause a segfault.
However what if I didn't want to restrict the user to 80 - 1 characters? I could use a really big number but that would just waste space.
I would also really like to know why the above program causes a segfault. From what I understand the cin extraction operator (>>) knows to NULL terminate a C string. What exactly is causing the problem?
The program segfaults because the pointer c is not initialized. You need to allocate memory for the buffer before reading the data into it:
char * c = new char[80];
cin >> c;
cout << c << endl;
delete[] c; // Now you need to delete the memory that you have allocated.
To avoid restricting your input to N characters, use strings. They resize dynamically as you need:
string c;
cin >> c;
cout << c;
// You do not need to manage string's memory - it is done automatically
You've allocated no space at all for the string when you use only char *c;. The variable declaration creates a pointer to char which is uninitialized. Then you use cin to read a string into that space. c could point to anything, and in any case will point to memory that doesn't belong to you.
You'll need to allocate space for the string before you try to fill it from cin.
If you don't want to assume a limit on the string length, you can loop and realloc more space until the input is completely read, but as has been mentioned, if you use std::string instead of C strings, then this will be handled for you.
That is because you did not allocate memory for your string.

Mistake using scanf

could you say me what is the mistake in my following code?
char* line="";
printf("Write the line.\n");
scanf("%s",line);
printf(line,"\n");
I'm trying to get a line as an input from the console.But everytime while using "scanf" the program crashes. I don't want to use any std, I totally want to avoid using cin or cout. I'm just trying to learn how to tak a full line as an input using scanf().
Thank you.
You need to allocate the space for the input string as sscanf() cannot do that itself:
char line[1024];
printf("Write the line.\n");
scanf("%s",line);
printf(line,"\n");
However this is dangerous as it's possible to overflow the buffer and is therefore a security concern. Use std::string instead:
std::string line;
std::cout << "Write the line." << std::endl;
std::cin >> line;
std::cout << line << std::endl;
or:
std::getline (std::cin, line);
Space not allocated for line You need to do something like
char *line = malloc();
or
Char line[SOME_VALUE];
Currently line is a poor pointer pointing at a string literal. And overwriting a string literal can result in undefined behaviour.
scanf() doesn't match lines.
%s matches a single word.
#include <stdio.h>
int main() {
char word[101];
scanf("%100s", word);
printf("word <%s>\n", word);
return 0;
}
input:
this is a test
output:
word <this>
to match the line use %100[^\n"] which means 100 char's that aren't newline.
#include <stdio.h>
int main() {
char word[101];
scanf("%100[^\n]", word);
printf("word <%s>\n", word);
return 0;
}
You are trying to change a string literal, which in C results in Undefined behavior, and in C++ is trying to write into a const memory.
To overcome it, you might want to allocate a char[] and assign it to line - or if it is C++ - use std::string and avoid a lot of pain.
You should allocate enough memory for line:
char line[100];
for example.
The %s conversion specifier in a scanf call expects its corresponding argument to point to a writable buffer of type char [N] where N is large enough to hold the input.
You've initialized line to point to the string literal "". There are two problems with this. First is that attempting to modify the contents of a string literal results in undefined behavior. The language definition doesn't specify how string literals are stored; it only specifies their lifetime and visibility, and some platforms stick them in a read-only memory segment while others put them in a writable data segment. Therefore, attempting to modify the contents of a string literal on one platform may crash outright due to an access violation, while the same thing on another platform may work fine. The language definition doesn't mandate what should happen when you try to modify a string literal; in fact, it explicitly leaves that behavior undefined, so that the compiler is free to handle the situation any way it wants to. In general, it's best to always assume that string literals are unwritable.
The other problem is that the array containing the string literal is only sized to hold 1 character, the 0 terminator. Remember that C-style strings are stored as simple arrays of char, and arrays don't automatically grow when you add more characters.
You will need to either declared line as an array of char or allocate the memory dynamically:
char line[MAX_INPUT_LEN];
or
char *line = malloc(INITIAL_INPUT_LEN);
The virtue of allocating the memory dynamically is that you can resize the buffer as necessary.
For safety's sake, you should specify the maximum number of characters to read; if your buffer is sized to hold 21 characters, then write your scanf call as
scanf("%20s", line);
If there are more characters in the input stream than what line can hold, scanf will write those extra characters to the memory following line, potentially clobbering something important. Buffer overflows are a common malware exploit and should be avoided.
Also, %s won't get you the full line; it'll read up to the next whitespace character, even with the field width specifier. You'll either need to use a different conversion specifier like %[^\n] or use fgets() instead.
The pointer line which is supposed to point to the start of the character array that will hold the string read is actually pointing to a string literal (empty string) whose contents are not modifiable. This leads to an undefined behaviour manifested as a crash in your case.
To fix this change the definition to:
char line[MAX]; // set suitable value for MAX
and read atmost MAX-1 number of characters into line.
Change:
char* line="";
to
char line[max_length_of_line_you_expect];
scanf is trying to write more characters than the reserved by line. Try reserving more characters than the line you expect, as been pointed out by the answers above.

Why does this C++ char array seem to be able to hold more than its size?

#include <iostream>
using namespace std;
typedef struct
{
char streetName[5];
} RECORD;
int main()
{
RECORD r;
cin >> r.streetName;
cout << r.streetName << endl;
}
When I run this program, if I enter in more than 5 characters, the output will show the whole string I entered. It does not truncate at 5 characters. Why is that?
How can I get this to work correctly?
You are overflowing the buffer. Put another char array after streetName and you will likely find that it gets the rest of the characters. Right now you are just corrupting some memory on your stack.
In order to limit the input to the size of the receiving array you need to use the length-limiting facilities provided by your input method. In your case you are using cin, which means that you can specify the limit by using its width method
cin.width(5);
cin >> r.streetName;
Because cin sees streetName as a char * and writes to memory and there is nothing to stop writing to *(streetName + 6) and further. This is a form of buffer overrun
The best code in this case is define streetName as a std::string
i.e.
typedef struct
{
std::string streetName;
} RECORD;
Because you're overruning the end of your buffer and in this particular case you're getting away with it. C and C++ make it very easy to "shoot yourself in the foot", but that doesn't mean that you should.
It's a buffer overrun.
C++ does not perform bounds checking on array accesses, and memory does not simply stop at the end of the array. You are writing data to memory that is not part of the array, the consequences of which are non-deterministic, and may sometimes even appear to work.
It is quite likely that if you placed that code into a function, the program would crash when you tried to return from the function, because one likely possibility is that you will have dumped on the function return address on the stack. You may also have corrupted data belonging to the calling function.
The way to do this correctly in c++ is to use a std::string.
#include<iostream>
#include<string>
....
std::string r;
getline(cin, r);
std::cout << r <<std::endl;
For truncated input(with suitably defined and inited values).
while(cin.peek() != EOF && i < len)
{
cin >> arr[i];
++i;
}
You will want to do something after this to flush the buffer and not leave the rest of the line sitting on the input stream if you plan on doing other things with it.