Strange characters appear when using strcat function in C++ - c++

I am a newbie to C++ and learning from the MSDN C++ Beginner's Guide.
While trying the strcat function it works but I get three strange characters at the
beginning.
Here is my code
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main() {
char first_name[40],last_name[40],full_name[80],space[1];
space[0] = ' ';
cout << "Enter your first name: ";
gets(first_name);
cout << "Enter your last name: ";
gets(last_name);
strcat(full_name,first_name);
strcat(full_name,space);
strcat(full_name,last_name);
cout << "Your name is: " << full_name;
return 0;
}
And here is the output
Enter your first name: Taher
Enter your last name: Abouzeid
Your name is: Y}#Taher Abouzeid
I wonder why Y}# appear before my name ?

You aren't initializing full_name by setting the first character to '\0' so there are garbage characters in it and when you strcat you are adding your new data after the garbage characters.

The array that you are creating is full of random data. C++ will allocate the space for the data but does not initialize the array with known data. The strcat will attach the data to the end of the string (the first '\0') as the array of characters has not been initialized (and is full of random data) this will not be the first character.
This could be corrected by replacing
char first_name[40],last_name[40],full_name[80],space[1];
with
char first_name[40] = {0};
char last_name[40] = {0};
char full_name[80] = {0};
char space[2] = {0};
the = {0} will set the first element to '\0' which is the string terminator symbol, and c++ will automatically fill all non specified elements with '\0' (provided that at least one element is specified).

The variable full_name isn't being initialized before being appended to.
Change this:
strcat(full_name,first_name);
to this:
strcpy(full_name,first_name);

You can not see any problem in your test, but your space string is also not null-terminated after initializing its only character with ' '.

As others have said, you must initialize the data, but have you ever thought about learning the standard c++ library? It is more intuitive sometimes, and probably more efficient.
With it would be:
string full_name=first_name+" "+last_name;
and you won't have to bother with terminating null characters. For a reference go to cplusplus
Oh and a full working example so you could understand better (from operator+=):
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string name ("John");
string family ("Smith");
name += " K. "; // c-string
name += family; // string
name += '\n'; // character
cout << name;
return 0;
}

The problem is with your space text.
The strcat function requires a C-style string, which is zero or more characters followed by a null, terminating, character. So when allocating arrays for C-style strings, you need to allocate one extra character for the terminating null character.
So, your space array needs to be of length 2, one for the space character and one for the null character.
Since space is constant, you can use a string literal instead of an array:
const char space[] = " ";
Also, since you are a newbie, here are some tips:
1. Declare one variable per line.
This will be easier to modify and change variable types.
2. Either flush std::cout, use std::endl, or include a '\n'.
This will flush the buffers and display any remaining text.
3. Read the C++ language FAQ.
Click here for the C++ language Frequently Asked Questions (FAQ)
4. You can avoid C-style string problems by using std::string
5. Invest in Scott Myers Effective C++ and More Effective C++ books.

Strings are null-terminated in C and C++ (the strcat function is a legacy of C). This means that when you point to a random memory address (new char[] variables point to a stack address with random content that does not get initialized), the compiler will interpret everything up to the first \0 (null) character as a string (and will go beyond the allocated size if you use pointer arithmetic).
This can lead to very obscure bugs, security issues (buffer overflow exploits) and very unreadable and unmaintainable code. Modern compilers have features that can help with the detection of such issues.
Here is a good summary of your options.

Related

Declaration of a String of Dynamic Length Using Pointer

I wanted to declare an array with a pointer in character type, and the length of the array can be determined by my input string.
I wrote it in this way:
char *s;
cout << "Enter a string: " << endl;
cin >> s;
I expected that I can initialize the string by the cin operation, but an error showed up when compiling. The error is about "invalid operands to binary expression".
I'm not sure why the lines I wrote was wrong.
I though not only the built in string class is used for declaring an array.
Isn't the string data type in C++ the same as "a character array"?
Isn't the line char *s means the pointer s points to an character array (or string)?
Thank you!
You should use std::string.
It is a class that represents a string of characters. It is different than an old c style array of characters (although internally might contain one).
In your case:
#include <string>
#include <iostream>
std::string s;
std::cout << "Enter a string: " << endl;
std::cin >> s;
Using std::string means memory is managed automatically for you. Specifically with cin it will also be resized to fit the input.
A side note: better to avoid using namespace std - see here Why is "using namespace std;" considered bad practice?.
"the cin operation".
cin is really the source. The real work is done by the overloaded operator>>. And the operator>> which reads to a char* expects that the char* is already allocated to the right size. That's of course a problem with cin, where the size is unknown.
The operator>> overload that reads to std::string will resize the std::string to the right size.
The answer to your question is no, as when you create a type pointer you always have to specify in advance how much memory to allocate. We can imagine that this is what happens with strings, that is to go to fetch the data and arrange the occupied cells in memory at a later time.
Now the real problem is, it is true that you have declared a pointer to a character, but you have not specified how much to allocate for it. It is as if you are saying you want to create a box but you are not specifying the size. I show you the correct method:
char *s = new char[10];
Obviously when using pointers, always remember to deallocate them at the end of use so as not to have any memory leaks.
Taking a summary of the situation, you tried to save a data in a box that you intend to create but does not exist. That is, you have named the box called s which will contain a pointer to a character but you have not yet built/created it in its final size.

C++ strlen() initialized char array

Quick question.
I couldn't find why an initialized char array returns this value. I understand that the strlen() function will only return the amount of characters inside of an array, and not the size, but why will it return 61 if there are no characters in it?
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
const int MAX = 50;
char test[MAX];
int length = strlen(test);
cout << "The current \'character\' length of the test array is: " << length << endl;
// returns "61"
// why?
cin >> test; //input == 'nice'
length = strlen(test);
cout << "The new \'character\' length of the test array is: " << length << endl;
// returns 4 when 'nice' is entered.
// this I understand.
return 0;
}
This was driving me nuts during a project because I would be trying to use a loop to feed information into a character array but strlen() would always return an outrageous value until I initialized the array as:
char testArray[50] = '';
instead of
char testArray[50];
I got these results using Visual Studio 2015
Thanks!
I think the basic misunderstanding is that - unlike in other languages - in C, locally defined variables are not initialised with any value, neither with empty strings, nor with 0, nor with any <undefined> or whatever unless you explicitly initialise them.
Note that accessing uninitialised variables actually is "undefined behaviour"; it may lead to "funny" and non-deterministic results, may crash, or might even be ignored at all.
A very common behaviour of such programs (though clearly not guaranteed!) is that if you write
char test[50];
int length = strlen(test);
then test will point to some memory, which is reserved in the size of 50 bytes yet filled with arbitrary characters, not necessarily \0-characters at all. Hence, test will probably not be "empty" in the sense that the first character is a \0 as it would be with a really empty string "". If you now access test by calling strlen(test) (which is actually UB, as said), then strlen may just go through this arbitrarily filled memory, and it might detect a \0 within the first 50 characters, or it might detect the first \0 much after having exceeded the 50 bytes.
It's good that you have found your answer, but you have to understand how does this thing works, I think.
char test[MAX];
In this line of code you have just declared an array of MAX chars. You will get random values in this array until you initialize it. The strlen function just walks through the memory until it find 0 value. So, since values in your array are random, the result of this function is random. Moreover, you can easily walk outside of your array and get UB.
char test[MAX] = '';
This code initilizes the first element in 'test' array with 0 value so strlen will be able to find it.

C++ String.h Char Tables cutting-off word without strstr

I need help with C++ <string.h> char tables.... How to cut word from sentence, using "*" operator, with no strstr? For example: "StackOverFlow is online website". I have to cut off "StackOverFlow" and leave in table "is online website" using operator, with no strstr. I couldn't find it anywhere.
Mostly like:
char t[]
int main
{
strcpy(t,"Stackoverflow is online website");
???
(Setting first char to NULL, then strcat/strcpy rest of sentence into table)
}
Sorry for English problems/Bad naming... I'm starting to learning C++
You can do something like this. Explain better what you need, please.
char szFirstStr[] = "StackOverflow, flowers and vine.";
strcpy(szFirstStr, szFirstStr + 15);
std::cout << szFirstStr << std::endl;
Will output "flowers and vine".
Using c strings is not good style for C++ programmer, use std::string class.
Your code is obviously syntactically incorrect, but I guess you are aware of that.
Your variable t is really a char array and you have a pointer that points to the first character of that char array, like you have a pointer that points to the first character of your null terminated string. What you can do is to change the pointer value to point to the new starting point of your string.
You can either do that, or if you indeed use an array, you can copy from the pointer of the new starting point you wish to use. So if the data you wish to copy resides in memory pointed to by:
const char* str = "Stackoverflow is an online website";
This looks like the following in memory:
Stackoverflow is an online website\0
str points to: --^
If you want to point to a different starting point you can alter the pointer to point at a different starting location:
Stackoverflow is an online website\0
str + 14 points to: --------------^
You can pass the address of the "i" to your strcpy, like so:
strcpy(t, str + 14);
Obviously it is not certain that you know the size to cut off without an analysis (the 14), what you might do is search through the string for the first character following a white space.
// Notice that this is just a sample of a search that could be made
// much more elegant, but I will leave that to you.
const char* FindSecondWord(const char* strToSearch) {
// Loop until the end of the string is reached or the first
// white space character
while (*strToSearch && !isspace(*strToSearch)) strToSearch++;
// Loop until the end of the string is reached or the first
// non white space character is found (our new starting point)
while (*strToSearch && isspace(*strToSearch)) strToSearch++;
return strToSearch;
}
strcpy(t, FindSecondWord("Stackoverflow is an online website"));
cout << t << endl;
This will output: is an online website
Since this is most likely a school assignment, I will skip the lecture on more modern C++ string handling, as I expect this has something to do with learning pointers. But obviously this is very low level modification of a string.
As a beginner why make it harder then it really have to be?
Use std::string
and
substr()
Link

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.

Appending character arrays using strcat does not work

Can some one tell me what's wrong with this code???
char sms[] = "gr8";
strcat (sms, " & :)");
sms is an array of size 4 1. And you're appending more char literals, which is going outside of the array, as the array can accommodate at max 4 chars which is already occupied by g, r, 8, \0.
1. By the way, why exactly 4? Answer : Because that there is a null character at the end!
If you mention the size of array as shown below, then your code is valid and well-defined.
char sms[10] = "gr8"; //ensure that size of the array is 10
//so it can be appended few chars later.
strcat (sms, " & :)");
But then C++ provides you better solution: use std::string as:
#include <string> //must
std::string sms = "gr8";
sms += " & :)"; //string concatenation - easy and cute!
Yes, there is no room for the extra characters. sms[] only allocates enough space to store the string that it is initialized with.
Using C++, a much better solution is:
std::string sms = "gr8";
sms += " & :)";
You're copying data into unallocated memory.
When you do this: char sms[] = "gr8"; you create a char array with 4 characters, "gr8" plus the 0 character at the end of the string.
Then you try to copy extra characters to the array with the strcat call, beyond the end of the array. This leads to undefined behaviour, which means something unpredictable will happen (the program might crash, or you might see weird output).
To fix this, make sure that the array that you are copying the characters to is large enough to contain all the characters, and don't forget the 0 character at the end.
In C, arrays don't automatically grow.
sms has a specific length (4, in this case - three letters and the terminating NULL). When you call strcat, you are trying to append characters to that array past its length.
This is undefined behavior, and will break your program.
If instead you had allocated an array with a large enough size to contain both strings, you would be okay:
char sms[9] = "gr8";
strcat (sms, " & :)");
C++ has the (basically) the same restrictions on arrays that C does. However, it provides higher level facilities that make it so you don't have to deal with arrays a lot of the time, such as std::string:
#include <string>
// ...
std::string sms = "gr8";
sms += " & :)";
The reason this is nicer is that you don't have to know ahead of time exactly how long your string will be. C++ will grow the underlying storage in memory for you.
Buffer overflow for character array followed by crash somewhere!
Your sms buffer is only 4 characters long. strcat will copy 5 more characters over the end of it and corrupt the stack.