How to add a char/int to an char array in C? - c

How can I add '.' to the char Array := "Hello World" in C, so I get a char Array: "Hello World." The Question seems simple but I'm struggling.
Tried the following:
char str[1024];
char tmp = '.';
strcat(str, tmp);
But it does not work. It shows me the error: "passing argument 2 of ‘strcat’ makes pointer from integer without a cast"
I know that in C a char can be cast as int aswell. Do I have to convert the tmp to an char array aswell or is there a better solution?

strcat has the declaration:
char *strcat(char *dest, const char *src)
It expects 2 strings. While this compiles:
char str[1024] = "Hello World";
char tmp = '.';
strcat(str, tmp);
It will cause bad memory issues because strcat is looking for a null terminated cstring. You can do this:
char str[1024] = "Hello World";
char tmp[2] = ".";
strcat(str, tmp);
Live example.
If you really want to append a char you will need to make your own function. Something like this:
void append(char* s, char c) {
int len = strlen(s);
s[len] = c;
s[len+1] = '\0';
}
append(str, tmp)
Of course you may also want to check your string size etc to make it memory safe.

The error is due the fact that you are passing a wrong to strcat(). Look at strcat()'s prototype:
char *strcat(char *dest, const char *src);
But you pass char as the second argument, which is obviously wrong.
Use snprintf() instead.
char str[1024] = "Hello World";
char tmp = '.';
size_t len = strlen(str);
snprintf(str + len, sizeof str - len, "%c", tmp);
As commented by OP:
That was just a example with Hello World to describe the Problem. It
must be empty as first in my real program. Program will fill it later.
The problem just contains to add a char/int to an char Array
In that case, snprintf() can handle it easily to "append" integer types to a char buffer too. The advantage of snprintf() is that it's more flexible to concatenate various types of data into a char buffer.
For example to concatenate a string, char and an int:
char str[1024];
ch tmp = '.';
int i = 5;
// Fill str here
snprintf(str + len, sizeof str - len, "%c%d", str, tmp, i);

In C/C++ a string is an array of char terminated with a NULL byte ('\0');
Your string str has not been initialized.
You must concatenate strings and you are trying to concatenate a single char (without the null byte so it's not a string) to a string.
The code should look like this:
char str[1024] = "Hello World"; //this will add all characters and a NULL byte to the array
char tmp[2] = "."; //this is a string with the dot
strcat(str, tmp); //here you concatenate the two strings
Note that you can assign a string literal to an array only during its declaration.
For example the following code is not permitted:
char str[1024];
str = "Hello World"; //FORBIDDEN
and should be replaced with
char str[1024];
strcpy(str, "Hello World"); //here you copy "Hello World" inside the src array

I think you've forgotten initialize your string "str": You need initialize the string before using strcat. And also you need that tmp were a string, not a single char. Try change this:
char str[1024]; // Only declares size
char tmp = '.';
for
char str[1024] = "Hello World"; //Now you have "Hello World" in str
char tmp[2] = ".";

Suggest replacing this:
char str[1024];
char tmp = '.';
strcat(str, tmp);
with this:
char str[1024] = {'\0'}; // set array to initial all NUL bytes
char tmp[] = "."; // create a string for the call to strcat()
strcat(str, tmp); //

Related

Function to concatenate two strings in C using strlen but without using strcat

I need to concatenate the strings "abc" and "def" using strlen but without using strcat. Can someone show me what is wrong with my main() function?
#include <stdio.h>
#include <string.h>
void strconcatenate(char *string1, char *string2) {
int i;
int j = strlen(string1);
for (i = 0; string2[i]; i++) {
string1[i+j] = string2[i];
}
string1[i + j]= '\0';
}
int main() {
char string1[3] = "abc";
string1[strlen(string1) - 1] = '\0';
char string2[3] = "def";
string2[strlen(string2) - 1] = '\0';
strconcatenate(string1, string2);
printf("Resultant string = %s\n", string1);
return 0;
}
In main you declared character arrays with three elements
char string1[3] = "abc";
//...
char string2[3] = "def";
These arrays do not contain strings because they do not store the terminating zero character '\0' of the string literals used as initializers. The first array contains three characters { 'a', 'b', 'c' } and the second array contains these three characters { 'd', 'e', 'f' }.
Then you applied the standard string function strlen to these arrays which expects that passed to it arrays contains strings. That is the function calculates the number of characters in a string by counting characters until the terminating zero character is encountered. As the arrays do not contain the terminating zero character '\0' that is as the arrays do not contain strings the calls of strlen invoke undefined behavior.
If you want to append one string to another string then the destination character array shall have enough size to be able to accommodate the second string.
Thus the function main can look the following way
int main( void ) {
char string1[7] = "abc";
char string2[] = "def";
printf( "Resultant string = %s\n", strconcatenate( string1, string2 ) );
return 0;
}
Now the both arrays string1 and string2 contain strings. Moreover the array string1 reserved enough space to accommodate the string stored in the array string2.
The declaration of the function strconcatenate should be similar to the declaration of the standard C function strcat.
char * strconcatenate( char *string1, const char *string2 );
That is the second parameter should have the qualifier const because the passed array is not changed within the function and the function should return the destination array that will contain the concatenated strings.
The function definition will look the following way
char * strconcatenate( char *string1, const char *string2 )
{
for ( char *p = string1 + strlen( string1 ); *p++ = *string2++; );
return string1;
}
There are multiple problems in your code:
[major] char string1[3] = "abc"; defines the destination array with a size of 3 bytes which does not have a enough space for the string "abc" including its null terminator and definitely not long enough to receive the extra characters from string2 at the end. Change this to char string1[7] = "abc";
[major] char string2[3] = "def"; defines the source array with a size of 3 bytes which does not have a enough space for the string "def" including its null terminator, hence will not be null terminated.
[major] string1[strlen(string1) - 1] = '\0'; overwrites the last character of abc, this not necessary.
[major] same remark for string2[strlen(string2) - 1] = '\0';
[minor] string2 should be defined as const char * in void strconcatenate(char *string1, char *string2)
[minor] i and j should be defined with type size_t
[minor] for compatibility with the standard function strcat, strconcatenate should have a return type of char * and return the pointer to the destination array. Yet, As commented by Jonathan Leffler, a more useful design for the return value is to return a pointer to the null at the end of the concatenated string. You already know where the start of the string is; that isn't very interesting information. But knowing where the end of the string is after concatenation — that is useful information which only the concatenate function is privy to. –
Here is a modified version:
#include <stdio.h>
#include <string.h>
char *strconcatenate(char *string1, const char *string2) {
char *p = string1 + strlen(string1);
while ((*p = *string1) != '\0') {
string1++;
p++;
}
return string1; /* strcat semantics */
//return p; /* alternative semantics */
}
int main() {
char string1[7] = "abc";
char string2[] = "def";
strconcatenate(string1, string2);
printf("Resultant string = %s\n", string1);
return 0;
}
Since string1 and string2 has 3 characters so you need to declare it with 4 bytes('\0') and also when you need not to subtract 1 from strlen because it points to '\0' character.
Below is the change to the code.
int main()
{
char string1[4] = "abc";
string1[strlen(string1)] = '\0';
char string2[4] = "def";
string2[strlen(string2)] = '\0';
strconcatenate(string1,string2);
printf("Resultant string = %s\n",string1);
return 0;
}

What happened to my strings in both strcpy() and custom function?

I have been doing well with the string functions I've been making recently. So then, I made my 3rd string function that is basically like strcpy():
#include <stdio.h>
#include <string.h>
const char *copy_str(const char *str);
int main() {
char name[256];
printf("What's your name? "); scanf("%255s", name);
char result[256] = copy_str(name);
printf("Hello, %s.\n", result);
}
const char *copy_str(const char *str) {
return str;
}
I didn't try using the strcpy() function itself in the function I made, because I'm not really familiar with it. Then I got an error:
copy_str.c:9:10: error: array initializer must be an initializer list or string literal
char result[256] = copy_str(name);
^
I fixed it this way:
int main() {
char name[256];
printf("What's your name? "); scanf("%255s", name);
char result[256];
strcpy(name, result);
printf("Hello, %s.\n", result);
}
But then the output went like this:
What's your name? builderman
Hello, .
No string for some reason. Even if you typed in a different string, it would be the same result.
Q: Why did strcpy() ruin my string? What ways can I improve my function?
I will try to answer your questions in parts.
copy_str.c:9:10: error: array initializer must be an initializer list or string literal
char result[256] = copy_str(name);
the meaning of this error is that in C syntax you cannot initialize an array the way that you did.
you can only initialize an array of chars with either a literal like so:
char name[] = "Hello";
or an initialization list like so:
char name[] = {'H', 'e', 'l', 'l', 'o'};
you can't initialize an array with a pointer to a char (which is the return value of your function)
strcpy doesn't magically copy an entire string to another one, it iterates over the string until it finds a NULL terminator '\0'
so a simple implementation of strcpy can be:
char *StrCpy(char *dest, const char *src)
{
char *returned_str = dest;
while (*src != '\0')
{
*dest = *src;
src++;
dest++;
}
*dest = '\0';
return returned_str;
}
so strcpy iterates over the strings and copies each character from src to dest.
a problem may arise when sending an array of characters that doesn't have a null terminator at the end of the array, which is how a string should be terminated in C.
The function strcpy has the following declaration
char *strcpy(char * restrict s1, const char * restrict s2);
That is the first parameter defines the array where the string pointed to by the second parameter is copied.
However in your program
int main() {
char name[256];
printf("What's your name? "); scanf("%255s", name);
char result[256];
strcpy(name, result);
printf("Hello, %s.\n", result);
}
you are copying the non-initialized character array result into the array name.
You have to write
strcpy( result, name );
instead of
strcpy(name, result);
As for the first program then the function copy_str is redundant. You could just write
char result[256] = name;
However the initializer has the type char * due to the implicit conversion of an array to pointer to its first element. So such initialization of an array is incorrect. You may initialize a character array with a string literal like
char s[] = "Hello";
But you may not use a character pointer to initialize a character array like
char t[] = "Hello";
char s[] = t;
Your function copy_str could look the following way
char * copy_str( char *dsn, const char *src )
{
for ( char *p = dsn; ( *p++ = *src++ ); );
return dsn;
}

C - string concatenation with pointers

why does the following string concatenation does not work?
main()
{
char *str1 = "United";
char *str2= "Front";
char *str3;
str3 = strcat(str1, str2 ) ;
printf("\n%s",str3 );
}
I got this problem in exercise questions in one of a book on pointers. The question mentions
[Q] Is the code correct if not why and also correct the code.
See my answer to the question concatenation of character arrays in c
You may not change string literals.
This statement
str3 = strcat(str1, str2 ) ;
tries to change the string literal str1 and moreover tries to write beyond the string literal.
To make a concatenated string you have to allocate a memory large enough to contain the both strings.
What you need is the following
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
const char *str1 = "United";
const char *str2 = "Front";
char *str3 = malloc( strlen( str1 ) + strlen( str2 ) + 1 );
strcpy( str3, str1 );
puts( strcat( str3, str2 ) );
free( str3 );
return 0;
}
The program output is
UnitedFront
When you write char* s = "something" a piece of read-only memory is allocated. More on this here.
The declaration of strcat looks like this:
char *strcat( char *dest, const char *src );
Basically what it will do is append src to dest, but since your destination, str1 does not have enough memory to hold both strings.
So what I would do is, either use snprintf with a pre-allocated buffer or:
char *str1 = "United";
char *str2 = "Front";
char *buf = calloc(strlen(str1) + strlen(str2) + 1, sizeof(char));
strncpy(buf, str1, strlen(str1));
strncat(buf, str2, strlen(str2));
printf("%s", buf);
Or with snprintf:
char *str1 = "United";
char *str2 = "Front";
int buf_len = strlen(str1) + strlen(str2) + 1;
char *buf = calloc(buf_len, sizeof(char));
snprintf(buf, buf_len, "%s%s", str1, str2);
The first parameter of strcat (str1 in your case) needs to have enough allocated memory to hold the concatenated string.
You can either create it with malloc or declare it as an array with a big enough size.

Unknown symbols appear when printing the result

I have two ways to do the same purpose, the first-way prints unknown symbols and the second-way prints exactly what I want.
The first-way:
const char *constStr = "Hello world";
char *str = (char*) malloc(strlen(constStr) + 1), *p = str;
while (*constStr) {
*p = *constStr;
constStr++;
p++;
}
printf("%s\n", str);
free(str);
The result:
The second-way:
const char *constStr = "Hello world";
char *str = (char*) malloc(strlen(constStr) + 1);
for (int i = 0; i <= strlen(constStr); i++) {
str[i] = constStr[i];
}
printf("%s\n", str);
free(str);
The result:
Why the first-way the result seems strange?
No you didn't null terminate the string. This is undefined behavior to pass pointer to non-null terminated char array in printf using %s format specifier.
Outside the loop make *p=0. That will null terminate the char array.
Second way is printing because you copied the \0 which is in strlen(constStr) index of the array. Notice the <= in the loop condition.
From where those weird letters come?
Think in terms of printf. When it sees the %s format specifier it prints starting from the address provided to it as argument. Now when does it stop? when it finds the \0. here it didnt find it and it read out of the memory that you allocated. Those bit patterns on those memory turned out to be those non printable characters. That's what you saw. The correct way to do this would be:
const char *constStr = "Hello world";
char *str = malloc(strlen(constStr) + 1), *p = str;
while (*p++ = *constStr++); // here `\0` will be copied.
printf("%s\n", str);
free(str);
When working with strings make sure you keep the corner cases clean. By that I mean,check whether the \0 is copied or not etc. This is so common a problem when we implement string routines.
To fix the first one, add a null at the end of the string:
const char *constStr = "Hello world";
char *str = (char*) malloc(strlen(constStr) + 1), *p = str;
while (*constStr) {
*p = *constStr;
constStr++;
p++;
}
*p = '\0'; /* <-- HERE */
printf("%s\n", str);
free(str);
Note: you are modifying a pointer to a temporary - not recommended. Use the same approach as you did for str, by using a another pointer which gets shifted.

String concatenation in C

char *str1 = malloc(256*sizeof(char));
char *str2 = "stack"
for (i=0;i<15;i++){
sprintf(str1,"%s%s",str1,str2);
}
printf("%s\n",str1);
I'm trying to concat str2 to str1 at each loop count. But this code segment works but vulnerable.
Whats the best way to concat them?
According to the CERT Secure Coding Guidelines, you need to use pointers to const when referring to string literals.
So, char *str2 = "stack" needs to be const char *str2 = "stack";.
This will make it immutable.
Additionally, you are using deprecated/obsolete functions. The secure function you should be using is strcat_s. For example,
Compliant Example
enum { BUFFERSIZE=256 };
void complain(const char *msg) {
static const char prefix[] = "Error: ";
static const char suffix[] = "\n";
char buf[BUFFERSIZE];
strcpy_s(buf, BUFFERSIZE, prefix);
strcat_s(buf, BUFFERSIZE, msg);
strcat_s(buf, BUFFERSIZE, suffix);
fputs(buf, stderr);
}
Read here about strcpy_s() and strcat_s().
If you want to use sprintf; something like this:
char *str1 = malloc(256*sizeof(char));
char *str2 = "stack";
*str1 = '\0';
for (i=0;i<15;i++){
snprintf(str1 + strlen(str1), 256 - strlen(str1), "%s", str2);
}
printf("%s\n",str1);
The standard C function for string concatenation is char * strncat ( char * destination, char * source, size_t num );.
Use strncat:
char *str1 = malloc(256*sizeof(char));
str1[0] = '\0';
char *str2 = "stack"
for (i=0;i<15;i++){
strncat(str1, str2, 256 - 1 - strlen(str2));
}
printf("%s\n",str1);

Resources