C++ char array value assignment - c++

I'm trying to keep the alphabet in a char array. But 4 letters show absurd charachters.
I run the program step by step using F11 button. Wrote the alphabet and after 'Q', until 'V' whatever I write, it shows ...PQÿÿÿÿVWXYZ this character: 'ÿ'
int main()
{
cout << "ALPHABET:";
char alf[] = "";
cin >> alf;
system("PAUSE");
}
I expect: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Actual result: ABCDEFGHIJKLMNOPQÿÿÿÿVWXYZ

Problem is with this line:
char alf[] = "";
you declare char array with size 1 which can only hold empty strings (null terminator). Note that std::istream::operator>> with char * does not validate size of array (it cannot) so you are getting Undefined Behavior writing into array with out of bounds. Solution is to use std::string instead which will grow as needed.
int main()
{
std::cout << "ALPHABET:";
std::string alf;
std::cin >> alf;
std::cout << alf << std::endl;
}

Related

Console couts a memory address instead of string

As I understand that strings can be treated like arrays, so I tried to insert each character of a string by iterating with a while loop. However the final cout pointed to a memory address, not the string I hoped it would print.
int main()
{
int i = 0;
int n = 2;
char input;
string str1[n];
while(i<=n){
cout<<"enter letter: ";
cin>>input;
str1[i] = input;
i++;
}
cout<<"Your word is: "<<str1;
return 0;
}
The output was:
enter letter: a
enter letter: b
enter letter: c
Your word is: 0x7ffd505af1f0
How can I print my string at the end, instead of a pointer to a mem address?
More interestingly, when I adjusted the final line to cout str1[n] instead of str1, the console prints the next character in the alphabet from the last input!
cout<<"Your word is: "<<str1[n];
and the output is
enter letter: a
enter letter: b
enter letter: c
Your word is: d
How is this happening?
When people say that strings are like arrays, they mean specifically "c-strings", which are just char arrays (char*, or char []). std::string is a separate C++ class, and is not like an array. See this question for a definition of C-strings.
In your example, str1 is actually an array of std::strings, and when you print it, you're printing the pointer address.
Below is an example using both C++ std::string, and a C-string, to illustrate the difference. In general, when writing C++, you should prefer std::string.
const int n = 2;
std::string str1; //A c++ std::string, which is not like an array
char cstr1[n+1]; // a c-string, which is array-like
for(int i = 0; i < n; ++i) {
char input = '\0';
cout<<"enter letter: ";
cin>>input;
str1.push_back(input); //Append to c++ string
cstr1[i] = input; //Add to array-like c-string
}
cstr1[n] = '\0'; //Ensure C-string is null-terminated
cout << "As C++: " << str1 << std::endl;
cout << "AS C: " << cstr1 << std::endl;
cout << "C++ can convert to C-string: " << str1.c_str() << std::endl;
Added const to n, to make it valid C++, since you shouldn't create arrays from non-const variables
Most likely you meant either string str1; or char str1[n]; (I suggest the first one, as the latter is a variable-length array supported only by compiler extensions, not a part of C++). string str1[n]; is an array of strings, which in generally decays to a pointer when passed around, so it happened in your case.
Should you decide to go with the std::string I suggest getting rid of i and n and rewriting it to sth like that:
while(str1.size() < 2){
cout<<"enter letter: ";
cin>>input;
str1.push_back(input);
}
Should you decide to stick to C-style char array (char str1[n];) I suggest making n a compile time constant, i.e. by defining it the following way: constexpr int n = 5; (provided you're on C++11 or newer).

Char outputting random characters at the end of the sentence

#include <iostream>
#include <string.h>
using namespace std;
void crypt(char* sMsg)
{
cout << "Original Message: '" << sMsg << "'" << endl;
int length = strlen(sMsg);
char sMsg_Crypt[3][length];
/* sMsg_Cryp[3]
[0] CRYPT LETTERS, ASCII + 3
[1] INVERT CHAR
[2] HALF+ OF SENTENCE, ASCII - 1
*/
for (int i=0; i<length; i++)
{
if (isalpha((int)sMsg[i]))
sMsg_Crypt[0][i] = sMsg[i] + 3; // DO ASCII + 3
else
sMsg_Crypt[0][i] = sMsg[i];
}
cout << "Crypt[0]: '" << sMsg_Crypt[0] << "'" << endl;
}
int main()
{
char sMsg[256];
cin.getline(sMsg,256);
crypt(sMsg);
return 0;
}
Input:
Hello World! Testing the Cryptography...
Output:
Original Message: 'Hello World! Testing the Cryptography...'
Crypt[0]: 'Khoor Zruog! Whvwlqj wkh Fu|swrjudsk|...Çi­o'
Why this Çi­o is comming out??
For starters variable length arrays like this
int length = strlen(sMsg);
char sMsg_Crypt[3][length];
is not a standard C++ feature.
You could use at least an array of objects of the type std::string like for example
std::string sMsg_Crypt[3];
Nevertheless the problem is that the array sMsg_Crypt[0] dies not contain a string. That is you forgot to append inserted characters in the array with the terminating zero character '\0'.
You could write after the for loop
sMsg_Crypt[0][length] = '\0';
provided that the array (if the compiler supports VLA) is declared like
char sMsg_Crypt[3][length+1];
Firstly, you can't define a static char array like this: char sMsg_Crypt[3][length];. That is because the length is not a const type, meaning the size of the array will be sMsg_Crypt[3][0] (this is because the size is not known at compile time). In MSVC, it'll flag an error (by IntelliSense). Since you know the size beforehand (256), you can replace the length with 256.
The second fact is that you're using C++ and you have access to std::string. So without using a char buffer, use std::string instead. It would look something like this: std::string sMsg_Crypt[3];
The last fact is that, for a string to be read correctly, it needs to be null-terminated ('\0' at the end). This means that the ending character must be '\0'. In the case of std::string, it does it for you.

Why allocating memory to a char pointer does not truncate the char sequence

I can't understand why char *ptr = new char[7] would not truncate an input of data bigger than 7 characters. Also why eighter char c[7] would let me input more than 6 characters (but giving error when attributing it a literal value of more than 6 characters).
Doing it with malloc function seems a little bit to hard for me for a moment, this is why i prefer not to use it. I would prefer for the moment not to use it.
char qs[7] = "1234567"; //error too many
char qs2[7];
cin >> qs2; //input 123456789
cout << qs2; //out same as input, expecting 123456
char *qs3 = new char[7];
cin >> qs3; //input 123456789
cout << qs3; //out same as input, expecting 123456
The input stream, currently, only takes a pointer as an argument. Therefore it cannot know the size of the buffer that it fills. Therefore it cannot know whether it should truncate or not. Reading a string longer than the buffer will cause the buffer to overflow, and behaviour of the program will be undefined. Don't do it.
Since C++20, the array operand is passed by reference, and the operation does know the size and will truncate the input. This won't help in the case of qs3 however, since it is only a pointer rather than an array.
Instead, you can use:
std::cin.get(qs3, 6);
qs3[6] = '\0';
To ensure that no more characters are read than fit the buffer.
Or if you prefer to not truncate input, then you can read into std::string.
Doing it with malloc function seems a little bit to hard for me for a moment, this is why i prefer not to use it.
Good. It wouldn't solve your problem, and there is no need to use it, nor is there any advantage to using it either.
The both code snippets
char qs2[7];
cin >> qs2; //input 123456789
cout << qs2; //out same as input, expecting 123456
char *qs3 = new char[7];
cin >> qs3; //input 123456789
cout << qs3; //out same as input, expecting 123456
have undefined behavior. The memory beyond the allocated arrays is overwritten. The consequence can be of any kind.
Consider the following demonstrative program.
#include <iostream>
int main()
{
char gs1[7] = "123456";
char gs2[7];
char gs3[7] = "ABCDEF";
std::cin >> gs2;
std::cout << '\n';
std::cout << gs1 << '\n';
std::cout << gs2 << '\n';
std::cout << gs3 << '\n';
return 0;
}
If to enter
1234567
then the program output might look like
123456
1234567
As you can see the string "ABCDEF" was not outputted. It is the result of that the terminating zero '\0' that was appended to the array gs2 after this statement
std::cin >> gs2;
overwrites the first character of the array gs3. Now it content looks like
{ '\0', 'B', 'C', 'D', 'F', '\0' }
So as the first element of the array is the terminating zero then the empty string was being outputted in this statement
std::cout << gs3 << '\n';
The C-strings are zero-terminated, that mean you should always allocate buffer with size string length + 1.
char qs[7] = "1234567"; //error too many
In statically allocated buffers it is obvious for the compiler that your buffer does not have space for terminating zero. This should be char qs[8].
In both other examples, the operator takes pointer to buffer as argument and there is no way for it to know how large it is. It just fill it until the end of input. You get classic buffer overrun situation, and you are lucky that there is nothing important out there (after the buffer boundaries).

Using pointers to find positions of characters between unbalances parentheses

I am given a C++ programming problem: In a string I need to find wether or not there are balanced parentheses. If not, using pointers I should find position of the characters between unclosed parentheses (between second opening and nearest closing).
The problem statement is a bit confusing, I know. I think it should work somehow like that:
Input #1:
((aba)aaab)
Output:
OK.
Input #2:
(aa(a)ab
Output:
Parentheses not balanced: between characters 1 and 6.
Code below solves part of problem with the closed parentheses check and also there is a structure to keep the address of the opening parenteses. I am not sure how exactly to use pointers for that purposes, some attempts did not give any result, so I need some help here.
#include<iostream>
#include<string>
#include<stack>
using namespace std;
struct br_data{
char br_t;
char *cptr; //store the address of the opening parenthesis
};
int main (){
string input;
int addr;
br_data br;
getline(cin, input);
stack<br_data> braces;
char *a = input[0];
auto init_char = static_cast<void*>(&a); //store the address of the first character in the input string
cout << static_cast<void*>(&a) << endl; //gives the address in memory
for(auto c: input) {
if (c == '(') {
br.br_t = c;
br.cptr = &c; //storing the address of the first parenhesis
braces.push(br);
} else if (c == ')' ) {
if (braces.empty())
cout << "This line does not contain unclosed parentheses\n";
if (!braces.empty())
braces.pop();
}
}
if (!braces.empty()){
//int addr = br.cptr;
cout << "This line does not contain unclosed parentheses\n";
//int pos = (&br.cptr) - (&a); //how to calculate the position??
cout << "Position of the second opening parenthis is " << () << endl;
//cout << "Position of the nearest closing parenthis is " << -how?? (static_cast<void*>(&br.cptr)) << endl;
}
if (braces.empty()){
cout << "Parentheses are balanced in this line\n";
}
return 0;
}
When you write
br.cptr = &c; //storing the address of the first parenhesis
you're actually storing the address of a local object of char type declared earlier:
auto c: input
By the moment you exit the loop it is officially dangling.
One simplest solution would be to actually consider string's characters, not their local copies:
for(auto &c: input) {
(and, even better, change auto into char for better clarity keeping source length the same). Then you can go on and see how your solution needs to be fixed further.
(A few extra free advice: input[0] is a rvalue reference of type char so it makes no sense to assign it to a variable of type char *, and what you try to do in that line is actually written as char *a = input.c_str(); or input.data() or even &input[0], pick the best option; and br.cptr is of type pointer-to-char already, so the character's position in a string would be calculated as br.cptr - a, you need to subtract the pointers themselves, not their addresses.)
#include <iostream>
using namespace std;
int main(){
char str[]="Hello Programming";
char *ptr;
char ch;
char s;
s='n';
ptr=str;
cout<<"To be found Character"<<endl;
cin>>ch;
while(*ptr++ != '\0')
if(*ptr==ch)
s='y';
if (s=='y')
cout<<"FOUND";
else
cout<<"not found";``
return 0;
}

how to print char array in c++

how can i print a char array such i initialize and then concatenate to another char array? Please see code below
int main () {
char dest[1020];
char source[7]="baby";
cout <<"source: " <<source <<endl;
cout <<"return value: "<<strcat(dest, source) <<endl;
cout << "pointer pass: "<<dest <<endl;
return 0;
}
this is the output
source: baby
return value: v����baby
pointer pass: v����baby
basically i would like to see the output print
source: baby
return value: baby
pointer pass: baby
You haven't initialized dest
char dest[1020] = ""; //should fix it
You were just lucky that it so happened that the 6th (random) value in dest was 0. If it was the 1000th character, your return value would be much longer. If it were greater than 1024 then you'd get undefined behavior.
Strings as char arrays must be delimited with 0. Otherwise there's no telling where they end. You could alternatively say that the string ends at its zeroth character by explicitly setting it to 0;
char dest[1020];
dest[0] = 0;
Or you could initialize your whole array with 0's
char dest[1024] = {};
And since your question is tagged C++ I cannot but note that in C++ we use std::strings which save you from a lot of headache. Operator + can be used to concatenate two std::strings
Don't use char[]. If you write:
std::string dest;
std::string source( "baby" )
// ...
dest += source;
, you'll have no problems. (In fact, your problem is due to the fact
that strcat requires a '\0' terminated string as its first argument,
and you're giving it random data. Which is undefined behavior.)
your dest array isn't initialized. so strcat tries to append source to the end of dest wich is determined by a trailing '\0' character, but it's undefined where an uninitialized array might end... (if it does at all...)
so you end up printing more or less random characters until accidentially a '\0' character occurs...
Try this
#include <iostream>
using namespace std;
int main()
{
char dest[1020];
memset (dest, 0, sizeof(dest));
char source[7] = "baby";
cout << "Source: " << source << endl;
cout << "return value: " << strcat_s(dest, source) << endl;
cout << "pointer pass: " << dest << endl;
getchar();
return 0;
}
Did using VS 2010 Express.
clear memory using memset as soon as you declare dest, it's more secure. Also if you are using VC++, use strcat_s() instead of strcat().