Char array gets cleared after function gets() on C++ - c++

I'm trying to learn C++. Sometimes I get confused by C style strings and its functions. I've been using
char var[1];
fflush(stdin);
gets(var);
to write a string into a char array. I don't know if thats the most efficient way but thats how I've been taught.
Now, I'm making a console program in which I read some variables that way and make things with them. It's all working fine but I have a char array, estudios[1] and I have to compare it with strcmp (I'm not talking about the strcmp(estudios, "N") != 0 I wrote below) to a specific value and i found that te result of the comparation was always the same no matter the value estudios had. I realized that after this chunk of code:
if (strcmp(estudios, "N") != 0){
cout << "Estudios completos o incompletos?" << endl;
fflush(stdin);
gets(indicador);
}
Let's say that the value of estudios is "P". Before the code i showed the value of estudios is "P" but after it it changes it value to "". To be more precise it changes after the gets(indicator);
Why does that happen? Is it supposed to do that? Sorry for such a newbie question

Don't use gets. It is dangerous. It shouldn't be used at all. It has been removed from both C and C++ standards. Don't use gets.
I have a char array, estudios[1]
strcmp(estudios, "N") != 0
A character array of length 1 can only contain the null terminated string of length 0. The string "N" contains two characters: 'N' and '\0' which is the null termination character.
If estudios[0] is anything other than the null termination character, then it doesn't contain a null terminated string, and passing it to strcmp will violate the pre-conditions of the function and the behaviour of the program will be undefined.
Why does that happen?
The behaviour of the program is undefined.
Is it supposed to do that?
You aren't supposed to pass non-null-terminated strings into strcmp.
Here is a fixed program that probably does what you're trying to do (your example is incomplete, so I'm guessing):
std::string indicator;
char c;
std::cin >> c;
if (c != 'N') {
cout << "Estudios completos o incompletos?" << endl;
std::cin >> indicador;
}

Related

strcpy() is not copying properly c++

Recently I made a program, it has a character array board[8][8][2];
It is basically meant to be a 8X8 board which can store '2' lettered strings. I am not providing the complete code.
But here is the problem.
for (j = 0; j < 8; j++) {
strcpy(board[1][j], P[j].sym);
}
cout << board[1][1] << endl;
Here P[1].sym="P1" and P[0].sym="P0" and P[2].sym="P2"
Therefore P[j].sym is basically a two letter string and board[1][j] should also be a two letter string.
But the output for
cout << board[1][1] << endl;
is given as P1P2P3P4P5P6P7
and the output for
cout << board[1][0] << endl;
is given as P0P1P2P3P4P5P6P7
For
cout << board[1][5] << endl;
P5P6P7 is the output.
To remove any doubt the whole board[8][8][[2] is already initialised
and all of P[j].sym are already initialised.
If it helps here is the code for the initialisation of P:
#include <iostream>
#include <string.h>
using namespace std;
class Game
{
public:
char board[8][8][2];
char *****possibilities;
};
class Pawn : virtual public Game {
public:
char sym[2];
int possiblec[4][2];
Pawn() { }
Pawn(int i) {
char a[2];
a[0] = 'P';
a[1] = (char)(i + 48);
strcpy(sym, a);
}
};
And here somewhere else in the program I did
Pawn P[8];
It calls the constructor and then later on I called the parameterised contructor explicitly.
for (int i = 0; i < 8; i++) {
P[i] = i;
}
After this I checked for different values of P[j].sym and all of them return the perfect values I wanted.
But not when I'm using strcpy() What is the problem here. This program is just a practice program to get a hang of it.
Character arrays in C++ ( and C ) are terminated with a Null character ('\0' ) . So, even if you need to store just two characters in your string, you must have an extra space to store the Null character.
A character array which does not terminate with a Null character can lead to a lot of other problems. It is a wrong practice.
If your character array does not terminate with a Null character, you will get a lot of problems when you call functions such as strcpy() , strcat() , etc...
So, you should change
char board[8][8][2]
to
char board[8][8][3]
And if you have any other strings just like this one, then leave one extra space in them as well.
The reason your code behaved as such is because you got lucky.
Functions such as strcpy() , strcat() all continue to copy ( or append ) until they encounter a Null Character ( which is numerically equal to zero ). So, it continues to do so until the Null character is encountered. But if there is no Null character, then you will most probably get Undefined Behavior. In your case, you just got lucky.
I will show you a brief working of strcpy() ( from here )
char * strcpy(char p, const char * q) {
while (*p++=*q++);
//there's also a return p; statement at the end
}
That is the function.
the while loop executes until it encounters false, and the equivalent for false is 0. So, when it encounters a Null character ( which is also numerically equal to 0 ), the while loop terminates and the copying is complete, and the function ends. So, if there is no Null character at the end, it will give you undefined Behavior.
You can refer man for more info about them
You should always reserve one extra character because strings in C and C++ are null terminated, which that they need one extra character to sign the end of the string.
So, please, change
board[8][8][2]
to
board[8][8][3]
as well as sym[2] to sym[3], a[2] to a[3] (generally add one to the length of all strings) and try again.
By looking at the manual pages for strcpy:
Copies the C string pointed by source into the array pointed by
destination, including the terminating null character (and stopping at
that point).
This means that that function will stop only when it encounters the null character. That's why it would fail if there wasn't any present. But, by setting one character at a time, there's obviously no such problem visible (it will become visible later on, if you try to execute a function that stops only when it encounters a null character and there are plenty of them).
Strings are null ('\0') terminated in C++. When you pass in an character array to printf it stops printing at the null character. I'm guessing the only reason it stopped printing at P7 is because you got lucky and the next memory location happens to be storing Null. You need to make your char arrays at least 1 character longer than the string you want to store.

how to insert a word and use it to make comparison in if condition in c++

i want to use the word i insert to use it to make comparison in if condition to show some word it the comparison is true.
here is my code
#include <iostream>
using namespace std;
int main()
{
char u[5];
cout<<" p " <<" c "<<" U "<<endl;
cout<<" pepsi=5"<<" coca=3"<<" 7-UP=2"<<endl;
cout<<"CHOOSE your drink"<<endl;
cin>>u;
if (u=="pepsi")
cout<<"your choice is pepsi and ur bill is 5 ";
}
First in the future I would suggest trying to be more specific on what your problem is and what you don't understand. Just saying I want to do X and here is my code is giving us very little to work with and we are basically just guessing on what you are having problems with.
Now on to what I believe you are having problems with (I am assuming since you didn't tell us what is going wrong).
In this case you are using a character array with a length of 5. Now when you use character arrays you need to take into account that all the reasonable inputs that that variable might store will actually fit into that character array.
Let's look at pepsi. You might think it would fit but in fact it doesn't because you are forgetting about the null character that is added on the end. This is what it looks like.
u[0] = 'p'
u[1] = 'e'
u[2] = 'p'
u[3] = 's'
u[4] = 'i'
u[5] = '\0'
So as you can see there is actually 6 characters in this word which will cause a overflow. I am assuming this is your problem.
Now how do we fix this? As others have said in the comments if you are using C++ it is probably better for you to use std::string for this problem since it will hide from you most of the problems you have to do deal with when using C style string (What you are using now). Then once you feel more comfortable with the language you can come back and revisit C style strings.
With std::string it would look something like this. Remember that when testing strings case matters (IE "string" is not the same as "String").
std::string choice;
std::cin >> choice;
if (choice == "pepsi")
{
std::cout << "You selected pepsi!" << std::endl;
}
Hope that helps a little and fixes your problems.

Simple C++ not reading EOF

I'm having a hard time understanding why while (cin.get(Ch)) doesn't see the EOF. I read in a text file with 3 words, and when I debug my WordCount is at 3 (just what I hoped for). Then it goes back to the while loop and gets stuck. Ch then has no value. I thought that after the newline it would read the EOF and break out. I am not allowed to use <fstream>, I have to use redirection in DOS. Thank you so much.
#include <iostream>
using namespace std;
int main()
{
char Ch = ' ';
int WordCount = 0;
int LetterCount = 0;
cout << "(Reading file...)" << endl;
while (cin.get(Ch))
{
if ((Ch == '\n') || (Ch == ' '))
{
++WordCount;
LetterCount = 0;
}
else
++LetterCount;
}
cout << "Number of words => " << WordCount << endl;
return 0;
}
while (cin >> Ch)
{ // we get in here if, and only if, the >> was successful
if ((Ch == '\n') || (Ch == ' '))
{
++WordCount;
LetterCount = 0;
}
else
++LetterCount;
}
That's the safe, and common, way to rewrite your code safely and with minimal changes.
(Your code is unusual, trying to scan all characters and count whitespace and newlines. I'll give a more general answer to a slightly different question - how to read in all the words.)
The safest way to check if a stream is finished if if(stream). Beware of if(stream.good()) - it doesn't always work as expected and will sometimes quit too early. The last >> into a char will not take us to EOF, but the last >> into an int or string will take us to EOF. This inconsistency can be confusing. Therefore, it is not correct to use good(), or any other test that tests EOF.
string word;
while(cin >> word) {
++word_count;
}
There is an important difference between if(cin) and if(cin.good()). The former is the operator bool conversion. Usually, in this context, you want to test:
"did the last extraction operation succeed or fail?"
This is not the same as:
"are we now at EOF?"
After the last word has been read by cin >> word, the string is at EOF. But the word is still valid and contains the last word.
TLDR: The eof bit is not important. The bad bit is. This tells us that the last extraction was a failure.
The Counting
The program counts newline and space characters as words. In your file contents "this if fun!" I see two spaces and no newline. This is consistent with the observed output indicating two words.
Have you tried looking at your file with a hex editor or something similar to be sure of the exact contents?
You could also change your program to count one more word if the last character read in the loop was a letter. This way you don't have to have newline terminated input files.
Loop Termination
I have no explanation for your loop termination issues. The while-condition looks fine to me. istream::get(char&) returns a stream reference. In a while-condition, depending on the C++ level your compiler implements, operator bool or operator void* will be applied to the reference to indicate if further reading is possible.
Idiom
The standard idiom for reading from a stream is
char c = 0;
while( cin >> c )
process(c);
I do not deviate from it without serious reason.
you input file is
this is fun!{EOF}
two spaces make WordCount increase to 2
and then EOF, exit loop! if you add a new line, you input file is
this is fun!\n{EOF}
I took your program loaded it in to visual studio 2013, changed cin to an fstream object that opened a file called stuff.txt which contains the exact characters "This is fun!/n/r" and the program worked. As previous answers have indicated, be careful because if there's not a /n at the end of the text the program will miss the last word. However, I wasn't able to replicate the application hanging in an infinite loop. The code as written looks correct to me.
cin.get(char) returns a reference to an istream object which then has it's operator bool() called which returns false when any of the error bits are set. There are some better ways to write this code to deal with other error conditions... but this code works for me.
In your case, the correct way to bail out of the loop is:
while (cin.good()) {
char Ch = cin.get();
if (cin.good()) {
// do something with Ch
}
}
That said, there are probably better ways to do what you're trying to do.

How to put the string entered into a character array in C++?

Now, I am facing with such a problem: Compare two strings without using "strcmp" in library function.
I have defined the function "mystrcmp" correctly, but I also have to put the string entered into a character array. How can I realize it?
Here is my wrong codes:
char a1[100],a2[100];
int j=0;
do
{
cin>>a1[j];
j=j+1;
}while(getchar()!=10);
int k=0;
do
{
cin>>a2[k];
k=k+1;
}while(getchar()!=10);
cout<<j<<" "<<k<<"\n";
I want to see if the loops are correct through j and k. Unfortunately, the results are wrong.
For example, when I enter "abcdefg" and "gfedcba", I get the result "j=4, k=4".
What's wrong with my codes? How can I correct it?
I'm looking forward to your answers. Thank you.
Why are you using the value 10 in your code? Don't use integer literals in place of character constants, because when you attempt to run this code on a computer that uses the EBCDIC character set you'll notice that '\n' has the value 37, not 10. Use '\n' instead of 10.
Don't mix getchar and cin code. That's a pretty bad idea, because they both consume one character each. In other words, getchar() is consuming one byte, and cin is consuming one byte, so you're consuming two bytes per loop and only storing one of those bytes. If you're going to use getchar, I think you mean something like this:
for (int c = getchar(); c >= 0 && c != '\n'; c = getchar()) {
a1[j++] = c;
}
a1[j] = '\0';
The same sort of thing using C++'s cin:
for (int c = cin.get(); cin.good() && c != '\n'; c = cin.get()) {
a1[j++] = c;
}
a1[j] = '\0';
This is dangerous code. You can write out of a1 & a2 bounds. Use functions made for this, for example cin.getline
http://www.cplusplus.com/reference/istream/istream/getline/

C++ converting character in vector to an integer...tough, need help?

This is what I have:
char userInput;
int position;
vector<string> userVector(7);
vector<int> someVector(7,1);
cin >> userInput;
cin >> position;
if(userInput == 'X')
userVector[position] = '1';
if(userVector[position]-someVector[position] == 0)
cout << "Success"
My problem is that userVector[position] is actually a character, because userVector is a string vector. However, I need this calculation to take place (userVector[position] - someVector[position]) because I need to determine if the outcome is 0 or some other number. Any help?
In case it doesn't make sense here, userVector HAS to be a string vector, because it's part of the requirements for this program. Basically, a user is supposed to be allowed to enter an "X" anywhere in the userVector vector, and you have to tell them if it matches expected outputs.
So, in this case, the "expected output" would be someVector, which has a 1 in all of it's spaces. What I'm trying to do is subtract the two vectors so that if the user enters anything other than X, the vector subtraction will not equal 0, and consequently, result in the program doing something different.
Hope that clears things up!
If I understand correctly your code, you are trying to convert a string representing a decimal number into an integer. You have several ways of doing that; e.g., by using istringstream:
int num;
if (!(istringstream(userInput[position]) >> num))
num = 0;
if (n - someVector[position] == 0) {
...
or you could use good old atoi:
if (atoi(userInput[position].c_str()) - someVector[position] == 0) {
If I am wrong about what you are trying to do, please clarify what you are trying to do...
I can't figure out what you're trying to do from your statement of the
problem. The expression userInput[position] isn't legal, since
userInput isn't a pointer, nor anything that can be converted to a
pointer.
But your code doesn't seem to correspond to the textual description,
since you describe userInput as a string vector
(std::vector<std::string>?), but the code declares it as a char.