C++ pointer issues - c++

i am trying to create a simple (modularized) c++ program that reads the users input and spits it back out.
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void _printOut(char * output)
{
cout << output << endl;
}
char * readUserInput()
{
char userInput[256];
cin >> userInput;
return userInput;
}
int _tmain(int argc, _TCHAR* argv[])
{
_printOut("Enter your name: ");
char * userName = readUserInput();
_printOut("Hello");
_printOut(userName);
system("pause");
return 0;
}
Enter your name:
aaaa
Hello
╠╠╠╠╠╠╠╠
Press any key to continue . . .
if i print out the userInput variable in the readUserInput function it prints out what is inputted. However trying to print out the userInput variable store as userName in the _tmain function results in a incomprehensible sequence of chars being printed out. ie. ╠╠╠╠╠╠╠╠.
By my best guess, this could be caused by pointer issues, but as far as I can tell I am referencing everything correctly.
Debugging this code:
at this line: _printOut("Hello"); in method: _tmain [userName = "abcdefg"]
at this line: _printOut(userName); in method _tmain [userName = "†UX"]
so I am wondering how the value of username is changing when it isn't assigned or manipulated between the two lines.

char * readUserInput()
{
char userInput[256];
cin >> userInput;
return userInput;
}
The char userInput[256]; array only exists during the function call. Once you hit the bottom of the function it ceases to exist, and you return a pointer to some garbage memory.
This is called local scope.
And anyway, what if someone has a reaally long name (longer than 255 characters).
Consider using std::string, which will solve both problems.
std::string readUserInput()
{
std::string inp;
std::cin >> inp;
return inp;
}
and
void printOut (const std::string& toPrint)
{
std::cout << toPrint << '\n';
}
(Also, and this is less important, the name _printOut is not allowed in this context, because of the leading _. See here, although it might go over your head if you are a beginner.)
Edit An even better way to go is to use std::getline to read a whole line at a time into a std::string. However, because of the way they treat spaces, and in particular '\n' newline characters, getline(...) and cin>>... don't play nicely together. It's usually just best to pick one and stick with it throughout your program. Here's how readUserInput() would look:
std::string readUserInput()
{
std::string line;
std::getline(std::cin, line);
return line;
}
This way if a user enters a name containing whitespace (e.g. "BoB T. Fish") you will read the whole name, rather than just "BoB" (and then leaving the rest to confuse you the next time you read).
The reason this can be iffy to mix cin>>... with getline is that cin>>... will read as much as it can up to whitespace, then leave the rest behind. So apart from mayb emissing someone's surname, if they enter a name without spaces, it will just leave the last newline character on the input stream. Then when you come along and do getline, you don't get the next line of user input. You get the empty line that has been left behind. If you had instead used cin>> again, the newline would have been ignored.
e.g. Consider this user input:
Hello\n
World\n
If you do the first read with cin>>, you get "Hello" in your program, and left with
\n
World\n
If you then do the second read with getline, you get "" in your program, and left with
World\n

char userInput[256]; will be destroyed when readUserInput exits, so the pointer you return is invalid.
Use std::string instead.
Or allocate the variable dynamically, or pass an automatic variable as parameter.

userInput variable gets destroyed once it goes out of scope.
Local variables get stored on stack. Once the function execution completes, the variables get destroyed.
Either you need to use dynamically allocated char pointer(Stores on Heap) or std::string

you are using a pointer to a buffer (In stack) which is already out of scope.
Try this:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void _printOut(char * output)
{
cout << output << endl;
}
char * readUserInput()
{
//Allocate in Heap, instead of stack
char* userInput = new char[256];
cin >> userInput;
return userInput;
}
int main(int argc, char* argv[])
{
_printOut("Enter your name: ");
char * userName = readUserInput();
_printOut("Hello");
_printOut(userName);
system("pause");
return 0;
}
A better way would be to use std::string

Your problem here is a scoping issue:
char userInput[256]; defines a local variable that is only valid within its own scope (between ist set of {} brackets).
You essentially return a valid pointer that becomes invalid once you leaves the function, because it's freed.
You're violating a basic rule: never return pointers to local (non-static) variables.
To fix this, make your userInput static or return a new string (create a new string every call using new) or use copyable objects rather than pointers (like std::string).

Related

Strange things with c++ string input

#include <iostream>
#include <cstring>
using namespace std;
const int BUFFER_SIZE = 80;
void getstr(char* &str);
int main()
{
char* str;
while(true)
{
getstr(str);
if (!strlen(str))
break;
}
delete [] str;
return 0;
}
void getstr(char* &str)
{
char temp[BUFFER_SIZE];
cout<<"Enter a string(empty line to quit): ";
cin.get(temp, BUFFER_SIZE);
while(cin.get()!='\n')
continue;
str = new char [strlen(temp)+1];
strcpy(str, temp);
}
I have a string reading loop above and entering an empty line to terminate the loop doesn't work(after entering an empty line program stops responding to any input). But when I replace a loop in getstr with single cin.get() all works fine. What's wrong?
istream::get() sets failbit when empty string is read.
This makes cin.get() return EOF and this because you couldn't break the loop while(cin.get()!='\n').
You can use ios::clear() to clear failbit.
cin.get(temp, BUFFER_SIZE);
cin.clear(); // add this
while(cin.get()!='\n')
continue;
cin.get(char* s, size_t n) Extracts characters from the stream and stores them in s as a c-string, until either (n-1) characters have been extracted or the delimiting character is encountered: the delimiting character being either the newline character ('\n') or delim (if this argument is specified).
The delimiting character is not extracted from the input sequence if found and remains there as the next character to be extracted from the stream (see getline for an alternative that does discard the delimiting character).
A null character ('\0') is automatically appended to the written sequence if n is greater than zero, even if an empty string is extracted.
So here is the problem. cin.get() need to read at least 1 character. You can close stdin by pressing Ctrl+D and Enter, after that, your program will be finished.
And BTW, you are using new N times, but you have only 1 delete. You need to delete the previous buffer
If you are going to use C++, you should really use cin/cout in an objectively consistent manner. For example:
string name;
cout << "What is your name: ";
getline (cin, name);
cout << "Your name is: " << name;
What you are doing is kind of a C/C++ hybrid (char arrays in leu of string objects, but using std namespace).
Now, I know this isn't your question, but what you are doing right now is slightly unorthodox which makes answering your question a bit difficult without putting the code in to and editor and debugging it.
Given the c++11 tag, I assume that you really want C++ code. The great thing is that C++ simplifies this a lot.
#include <iostream>
#include <string>
int main()
{
std::string str;
while(std::getline(std::cin, str) && !str.empty())
{
// do stuff
}
return 0;
}

How to ignore everything after the first character input

I would like to get rid of everything after the first char of a user input.
Everything is working fine, but I'm handling edge cases and if a user types something for example 'nfff' it would cause two functions to occur, when 'n' is entered as an input and when 'f' is entered as an input. I am aware that this can be solved using if (str[0] == 'n') { function() }, but I'd rather not use more memory with string.
Is there a more efficient way to discard everything after the first character?
You can use scanf or getchar.
For example,
char my_char;
scanf("%c", &my_char);
So, this will ignore everything after the first character.
#include <iostream> // std::cin, std::cout
#include <fstream> // std::ifstream
int main () {
char str[2];
std::cout << "Enter str ";
std::cin.get (str,2); // get c-string
std::cout <<str<<std::endl;
return 0;
}
Use istream::get to do the trick! Size of 2 will make sure that str is null terminated.

Error: C++ literal memory mishandling

I have tried a lot to debug my code but it is still not working.The whole code just crashes but there is no allover error I am presenting the code please try to debug that one.
Code:
#include <iostream>
#include<conio.h>
#include<string.h>
#include<fstream>
using namespace std;
void write(char fname[],char text[])
{
strcat(fname,".txt");
ofstream w(fname,ios::app);
w<<text;
w<<"\n";
w.flush();
w.close();
cout<<" sippy "<<fname<<" ";
}
int main ()
{
int login=0;
char t[100],id[100]="Its id ",pass[100]="Its password";
login=1;
strcpy(t,id);
strcat(t,"\n");
strcat(t,pass);
cout<<" finally ";
write("database",t);
getch();
strcpy(t,id);
getch();
cout<<t<<" showing t here";
getch();
cout<<" hope this works for now ";
getch();
cout<<"\nEnter the text"<<endl;
write(id,t);
}
The above mentioned code does not work on tdm gcc code blocks
Edit 1:
Ok so now the major problem has been detected it is a minor bug usually caused because of drawback of a bad programming style. As it is often suggested that if a string is passed to a function then that particular function allocates a new string at the memory of the passed string. Since the passed string is a literal the code editing the newly formed string would try to edit a read only literal memory which is an error
Literals are read only because if compiler finds the use of same literal at some different place then it would be able to use same memory to flash the contents of literal therefore it becomes a necessity to make a literal read only and use of c-style string carefully(rather std::string should be used)
Thanks to all
If you are facing a SegFault I think this line could be the problem :
write("database",t);
because in your write function you use strcat on fname but you pass a read-only string.
Also, I think it might be best to use real c++ instead of c+ like :
#include <string>
#include <iostream>
#include <fstream>
void my_write(std::sting & fname, std::string & text) {
std::string file = fname + ".txt";
std::osftream w(file, std::ios::app);
w << text << "\n";
w.flush();
w.close();
}
int main() {
std::string t = "";
std::string id = "Its id";
std::string pass = "Its password";
std::string fname = "database";
int login = 1;
t = id + "\n" + pass;
my_write( fname, t);
}
I haven't test it but the idea is here.

C++ c_str() doesn't return complete string

I'm doing a C++ assignment that requires taking user input of an expression (eg: 2 * (6-1) + 2 ) and outputting the result. Everything works correctly unless a space is encountered in the user input.
It is a requirement to pass the user input to the following method;
double Calculate(char* expr);
I'm aware the issue is caused by c_str() where the space characters act as a terminating null byte, though I'm not sure how to overcome this problem.
Ideally I'd like to preserve the space characters but I'd settle for simply removing them, as a space serves no purpose in the expression. I get the same result when using string::data instead of c_str.
int main(int argc, char **argv)
{
string inputExpr;
Calc myCalc;
while(true) {
cin >> inputExpr;
if(inputExpr == "q") break;
cout << "You wrote:" << (char*)inputExpr.c_str() << endl; // debug
printf("Result: %.3f \n\n", myCalc.Calculate( (char*)temp.c_str() ) );
}
return 0;
}
c_str works just fine. Your problem is cin >> inputExpr. The >> operator only reads until the next space, so you do not read your equation fully.
What you want to use is std::getline:
std::getline (std::cin,inputExpression);
which will read until it reaches a newline character. See the function description if you need a specific delimiter.
Problem is not with inputExpr.c_str() and c_str as such, c_str() returns pointer to a character array that contains a null-terminated sequence. While reading through cin, you get space or tab etc separating as multiple strings. Check with the content of the string that way to solve the intended operation
First, I think your Calculate() method should take as input a const char* string, since expr should be an input (read-only) parameter:
double Calculate(const char* expr);
Note that if you use const char*, you can simply call std::string::c_str() without any ugly cast to remove const-ness.
And, since this is C++ and not C, using std::string would be nice:
double Calculate(const std::string& expr);
On the particular issue of reading also whitespaces, this is not a problem of terminating NUL byte: a space is not a NUL.
You should just change the way you read the string, using std::getline() instead of simple std::cin >> overload:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string line;
getline(cin, line);
cout << "'" << line << "'" << endl;
}
If you compile and run this code, and enter something like Hello World, you get the whole string as output (including the space separating the two words).

first string in array of strings is being skipped

Somehow when I run this code and it comes to inputting strings, the first string where i=0 is being skipped and it starts entering strings from A[1]. So I end up with A[0] filled with random stuff from memory. Can someone please point at the problem?
cin>>s;
char** A;
A = new char *[s];
cout<<"now please fill the strings"<<endl;
for (int i=0;i<s;i++)
{
A[i] = new char[100];
cout<<"string "<<i<<": ";
gets(A[i]);
}
That code is horrible. Here's how it should look like in real C++:
#include <string>
#include <iostream>
#include <vector>
int main()
{
std::cout << "Please start entering lines. A blank line or "
<< "EOF (Ctrl-D) will terminate the input.\n";
std::vector<std::string> lines;
for (std::string line; std::getline(std::cin, line) && !line.empty(); )
{
lines.push_back(line);
}
std::cout << "Thank you, goodbye.\n";
}
Note the absence of any pointers or new expressions.
If you like you can add a little prompt print by adding std::cout << "> " && at the beginning of the conditional check in the for loop.
Probably because you're using gets()... never use gets()
Use fgets() instead.
gets vs fgets
The problem is that cin>>s; just picks up the number you want and leaves a \n (newline from the enter press) on stdin that gets() picks up in the first iteration. This is not the nicest way to fix it, but to prove it write this line after that line:
int a = fgetc(stdin);
Check out a afterwards to confirm it has a newline.
Well, you probably get an empty string: when reading s you use formatted input which stops as soon as a non-digit is encountered, e.g., the newline used to indicate its input is finished. gets(), thus, immediately finds a newline, terminating the first string read.
That said, you shall never use gets(): It is a primary security problem and the root cause of many potential attack! You should, instead, use fgets() or, better, yet, std::getline() together with std::strings and a std::vector<std::string> >. Aslo, you should always verify that the attempt to input was successful:
if ((std::cin >> s).ignore(std::numeric_limits<std::streamsize>::max(), `\n`)) {
std::string line;
for (int i(0); i != s && std::getline(std::cin, line); ) {
A.push_back(line);
}
}