How to append a character onto a string? - c

The examples I've seen on Stack Overflow come close to what my problem is but none of them seem to match, so I have to ask myself: How can I properly append a character to a string in C? I am aware that strcat() does not do the job, nor does using array values work properly. Here is my code:
char* buildWord(int posX, int posY, int nextX, int nextY, int gridX, int gridY, char** grid, char* str, int length){
int len2;
char* word = malloc(sizeof(char) * 20);
if(posX+nextX < 0 || posX+nextX > gridX)
return NULL;
if(posY+nextY < 0 || posY+nextY > gridX)
return NULL;
strcpy(word, str);
len2 = strlen(word);
word[len2 + 1] = grid[posX + nextX][posY + nextY]; //grid[x][y] represents a
word[len2 + 2] = '\0'; //single character
printf("%s", word);
length++;
if(length < 4)
word = buildWord(posX+nextX, posY+nextY, nextX, nextY, gridX, gridY, grid, word, length);
return word;
}
As you might guess, the purpose of this code is to build a string from a grid of letters with a particular direction in mind (similar to a wordsearch). For example, if my initial string "str" is "c" and am going in a diagonal direction where the next letter is "a", the string I want to put together is "ca".
When I run this code, the letter is not appended. The string remains the same throughout the code, which of course causes it to break. Is there a proper method to doing this?

You have a bug here:
word[len2 + 1] = grid[posX + nextX][posY + nextY]; //grid[x][y] represents a
word[len2 + 2] = '\0';
It should be:
word[len2] = grid[posX + nextX][posY + nextY]; //grid[x][y] represents a
word[len2 + 1] = '\0';
Remember that the index begin with 0

Related

padding string by adding char to the string

I am trying to create a padding function that adds an underscore to a string. The string length should be 16, and if the string is less than 16 the function should add an underscore until the string length is 16, then return the padding string. If the string is more than 16, the padding function should ignore the characters and returned the first 16 characters of the string.
char* padding(char* plaintext) {
char ch = '_';
size_t len = strlen(plaintext);
size_t lench = 17 - len;
char *p_text = malloc(len + 1 + 1);
strcpy(p_text, plaintext);
if (len < 17) {
int i;
for (i = lench; i < 16; i++) {
p_text[i] = ch;
}
}
// p_text[17] = '\0';
return p_text;
}
int main() {
char *key = "0123456789ABCDEF";
while (1) {
char plaintext[WIDTH + 1];
printf("Enter a string: ");
fgets(plaintext, WIDTH + 1, stdin);
if (plaintext[0] == '\n' || plaintext[0] == '\r')
break;
char* padded_plaintext = padding(plaintext);
printf("padded plaintext = %s\n", padded_plaintext);
printf("\n");
}
return 0;
}
this code returns a weird result.
Consider a clean solution to this problem. Hopefully seeing this (and the accompanying explanation) helps.
char *padded_string(char *src, int width, char ch) {
char *dest = calloc(1, width + 1);
strncpy(dest, src, width);
for (int i = 0; i < width; i++) {
if (!dest[i]) {
dest[i] = ch;
}
}
return dest;
}
We provide ourselves a clean slate to work on by allocating width + 1 bytes using calloc. Using calloc will ensure all bytes are set to 0. When working with strings in C, they need to be null-terminated, so this is very useful.
We copy the contents of src into dest. Using strncpy ensures we don't get a buffer overflow if the source string is longer than the string we want to end up with.
Next we loop from 0, width times. If the character in the destination string at i is a '\0' we'll insert the padding character at that index.
Now, because we used calloc and we allocated an extra byte beyond the character length we needed, the string is already null-terminated, we can simply return its pointer.
The space that you allocate for p_text should not depend on the input. It should always be 17. If len + 1 + 1 < 16, then accessing p_text[i] will lead to undefined behavior for certain values of i that you are using. You should replace:
char *p_text = malloc(len + 1 + 1);
with
char *p_text = malloc(17);
and check that p_text is not NULL before you write to it.
Also, the commented out //p_text[17] = '\0'; is wrong. That should be
p_text[16] = '\0';

Trying to delete a specific character from a string in C?

I'm trying to delete a specific character (?) from the end of a string and return a pointer to a string, but it's not removing it at all at the moment. What am I doing wrong? Is there a better way to go about it?
char * word_copy = malloc(strlen(word)+1);
strcpy(word_copy, word);
int length = strlen(word_copy);
int i = 0;
int j = 0;
for (i = 0; word_copy[i] != '\0'; i++) {
if (word_copy[length - 1] == '?' && i == length - 1){
break;
}
}
for (int j = i; word_copy[j] != '\0'; j++) {
word_copy[j] = word_copy[j+1];
}
word = strdup(word_copy);
I'm immediately seeing a couple of problems.
The first for loop does nothing. It doesn't actually depend on i so it could be replaced with a single if statement.
if (word_copy[length - 1] == '?') {
i = length - 1;
} else {
i = length + 1;
}
The second for loop also acts as an if statement since it starts at the end of the string and can only ever run 0 or 1 times.
You could instead do something like this to remove the ?. This code will return a new malloced string with the last character removed if its ?.
char *remove_question_mark(char *word) {
unsigned int length = strlen(word);
if (length == 0) {
return calloc(1, 1);
}
if (word[length - 1] == '?') {
char *word_copy = malloc(length);
// Copy up to '?' and put null terminator
memcpy(word_copy, word, length - 1);
word_copy[length - 1] = 0;
return word_copy;
}
char *word_copy = malloc(length + 1);
memcpy(word_copy, word, length + 1);
return word_copy;
}
Or if you are feeling lazy, you could also just make the last character the new null terminator instead. Its essentially creates a memory leak of 1 byte, but that may be an acceptable loss. It should also be a fair bit faster since it doesn't need to allocate any new memory or copy the previous string.
unsigned int length = strlen(word);
if (length > 0 && word[length - 1] == '?') {
word[length] = 0;
}

what happens when i use malloc() twice in the same pointer?

I write a code to split string by delimiter.
I want the function get a string and return its strings divided.
It actually works except for one thing.
when I give string "test", it works.
but when I give string "1234 4567", I can access the value '4567', but not '1234'. (garbage value.)
also "1234 2345 3456 ..." results garbage value in only first argument '1234'.
I thought that using malloc() twice causes problem in the same pointer, but it doesn't.
What is the problem for my codes?
char **ft_set_char(char *str)
{
int i;
int j;
int k;
char *str_c;
char **ret;
k = 0;
j = 0;
ret = (char **)malloc(10);
str_c = (char *)malloc(5);
i = 0;
while (*(str + i) != '\0')
{
if (*(str + i) == ' ')
{
*(str_c + k) = '\0';
k = 0;
*(ret + j) = str_c;
j++;
i++;
str_c = (char *)malloc(5);
}
*(str_c + k) = *(str + i);
i++;
k++;
}
*(str_c + k) = '\0';
*(ret + j) = str_c;
*(ret + j + 1) = NULL;
return (ret);
}
ret = (char **)malloc(10);
That is not correct because it allocates 10 bytes and not 10 char * elements. It should be:
ret = malloc(10 * sizeof *ret);
Other unrelated issues but should be noted for best practice:
Don't cast the result of malloc
Don't use magic numbers like 10 and 5. For the former at least use a #define MAX_ARRAY_SIZE 10. For the latter, you can keep work out the exact size of the string to be copied from the original str - that will make your code more robust in case it is ever used with longer sub-strings.

Create a string from a vector of integers in C

I'm trying to create a string from a vector, something like this:
int vector[3] = {1, 2, 3}.
Then, the string I would get should be:
[1, 2, 3] stored in some char[] variable.
I tried to do it dynamically like follows:
void print_vector(int *vector, int lon){
char *str = (char*)calloc(3*lon, sizeof(char));
str[0] = "[";
str[1] = (char) vector[0];
for(int i = 1; i < lon; i += 3){
str[i] = (char)vector[i];
if(i != lon - 1){
str[i + 1] = (char)",";
str[i + 2] = " ";
}else{
str[i + 1] = "]";
}
}
printf("%s\n", str);
}
Where lon is the length of the vector, but I'm getting this warning from the compiler:
warning: the assignment to "char" from "char *" creates an integer from a pointer without a conversion [-Wint-conversion]
What am I doing wrong? Thanks.
There are several issues with your code -
You are using " instead of '. " is used to create a string literal which is of type char*. Hence the error you are getting.
(char) vector[0]; is not the right way to convert an integer to strings. You should use something like sprintf.
You haven't allocated enough memory with the call to calloc (the brackets, commas, space, nul-terminator).
You are only filling in certain characters in the buffer. The rest are initialized to 0. This will cause the string to terminate earlier than expected.
To start, you can fix your code as -
void print_vector(int *vector, int lon){
char *str = calloc(5*lon+3, sizeof(char));
// 5 for each character (3 characters per integer + space + comma.
// Two brackets and nul-terminator
strcpy(str, "[");
if (lon) {
sprintf(str+1, "%d", vector[0]);
for(int i = 1; i < lon; i++){
sprintf(str + strlen(str), ", %d", vector[i]);
}
}
strcat(str, "]");
printf("%s\n", str);
}
You can find the working demo here on ideone.
You're trying to assign strings to char array elements. You need to use single quotes to create char constants.
So
str[0] = "[";
should be
str[0] = '[';
and similarly for all the other assignments.
Another problem is that (char)vector[i] will not return the character representation of the number in vector[i]. It simply uses the integer as the character code. So if vector[i] is 1, this produces '\1', not '1'. The way to get the character representation of a number is with '0' + vector[i].
Finally, you need to add a null terminator to the end of the string so you can print it with %s formatting. And you should free it before returning to prevent a memory leak.
Other problems: You're only putting every 3rd element of vector into the string. You need to use separate indexes for vector and str. And array indexes start at 0, not 1.
void print_vector(int *vector, int lon){
char *str = (char*)calloc(3*lon, sizeof(char));
str[0] = "[";
str[1] = (char) vector[0];
for(int i = 0; i < lon; i++){
str[i*3] = '0' + vector[i];
if(i != lon - 1){
str[i*3 + 1] = ',';
str[i*3 + 2] = ' ';
}else{
str[i*3 + 1] = ']';
str[i*3 + 2] = '\0';
}
}
printf("%s\n", str);
}
Assuming every element in your vector is one digit, and every element is spaced identicially...
... and remembering you need to allicate a null byte at the end to terminate your string...
... perhaps something like this (uncompiled/untested):
void print_vector(int *vector, int lon){
char *str = (char*)calloc((3*lon)+1, sizeof(char));
char *s = str;
*s++ = "[";
int i=1;
while (i < lon) {
*s++ = vector[i] + 0x30; // ASCII "0"= 0x30, "1"= 0x31, ...
*s++ = ',';
*s++ = ' ';
i++;
}
s -= 2;
*s++ = ']';
*s++ = 0;
printf("%s\n", str);

Replacing spaces with %20 in C

I am writing a fastcgi application for my site in C. Don't ask why, leave all that part.
Just help me with this problem- I want to replace spaces in the query string with %20.
Here's the code I'm using, but I don't see 20 in the output, only %. Where's the problem?
Code:
unsigned int i = 0;
/*
* Replace spaces with its hex %20
* It will be converted back to space in the actual processing
* They make the application segfault in strtok_r()
*/
char *qstr = NULL;
for(i = 0; i <= strlen(qry); i++) {
void *_tmp;
if(qry[i] == ' ') {
_tmp = realloc(qstr, (i + 2) * sizeof(char));
if(!_tmp) error("realloc() failed while allocting string memory (space)\n");
qstr = (char *) _tmp;
qstr[i] = '%'; qstr[i + 1] = '2'; qstr[i + 2] = '0';
} else {
_tmp = realloc(qstr, (i + 1) * sizeof(char));
if(!_tmp) error("realloc() failed while allocating string memory (not space)\n");
qstr = (char *) _tmp;
qstr[i] = qry[i];
}
}
In the code, qry is char *, comes as a actual parameter to the function.
I tried with i + 3, 4, 5 in realloc() in the space replacer block, no success.
String-handling in C can be tricky. I'd suggest going through the string first, counting the spaces, and then allocating a new string of the appropriate size (original string size + (number of spaces * 2)). Then, loop through the original string, maintaining a pointer (or index) to the position in both the new string and the original one. (Why two pointers? Because every time you encounter a space, the pointer into the new string will get two characters ahead of the pointer into the old one.)
Here's some code that should do the trick:
int new_string_length = 0;
for (char *c = qry; *c != '\0'; c++) {
if (*c == ' ') new_string_length += 2;
new_string_length++;
}
char *qstr = malloc((new_string_length + 1) * sizeof qstr[0]);
char *c1, *c2;
for (c1 = qry, c2 = qstr; *c1 != '\0'; c1++) {
if (*c1 == ' ') {
c2[0] = '%';
c2[1] = '2';
c2[2] = '0';
c2 += 3;
}else{
*c2 = *c1;
c2++;
}
}
*c2 = '\0';
qstr[i] = '%'; qstr[i + 1] = '2'; qstr[i + 2] = '0';
That line writes three characters to your output buffer, so the next character you write needs to be written at qstr[i+3]. However, you only step i by 1, so the next character is written to qstr[i+1], overwriting the '2'.
You will need to keep separate indexes for stepping through qry & qstr.
I agree with David.
It is advisable to do it in two-steps: in the first loop you just count the spaces:
int spaceCounter=0;
const int sourceLen = strlen(qry);
for(int i = 0; i < sourceLen; ++i)
if ( qry[i] == ' ')
++spaceCounter;
char* newString = (char*)malloc(sourceLen + 3*spaceCounter*sizeof(char) + 1)
//check for null!
for(int i = 0; i < sourceLen; ++i)
if ( qry[i] == ' ')
{
*newString++ = '%';
*newString++ = '2';
*newString++ = '0';
}
else
*newString++ = qry[i];
*newString = '\0';
Warning: code not tested.
You are assigning using the same counter I you will need to have 2 counters since the strings have different lengths
your else case assigns qstr[i] = qry[i]; after you have written the %20 you are at least off by 2 on the result string.
This is known as url encode. You can refer to this page to see some similar implementation: http://www.geekhideout.com/urlcode.shtml
char* toHexSpace(const char *s)
{
char *b=strcpy(malloc(3*strlen(s)+1),s),*p;
while( p=strchr(b,' ') )
{
memmove(p+3,p+1,strlen(p));
strncpy(p,"%20",3);
}
return b;
}
needs "free" in calling context.

Resources