I have a C string that looks like "Nmy stringP", where N and P can be any character. How can I edit it into "my string" in C?
To "remove" the 1st character point to the second character:
char mystr[] = "Nmy stringP";
char *p = mystr;
p++; /* 'N' is not in `p` */
To remove the last character replace it with a '\0'.
p[strlen(p)-1] = 0; /* 'P' is not in `p` (and it isn't in `mystr` either) */
Another option, again assuming that "edit" means you want to modify in place:
void topntail(char *str) {
size_t len = strlen(str);
assert(len >= 2); // or whatever you want to do with short strings
memmove(str, str+1, len-2);
str[len-2] = 0;
}
This modifies the string in place, without generating a new address as pmg's solution does. Not that there's anything wrong with pmg's answer, but in some cases it's not what you want.
Further to #pmg's answer, note that you can do both operations in one statement:
char mystr[] = "Nmy stringP";
char *p = mystr;
p++[strlen(p)-1] = 0;
This will likely work as expected but behavior is undefined in C standard.
The most efficient way:
//Note destroys the original string by removing it's last char
// Do not pass in a string literal.
char * getAllButFirstAndLast(char *input)
{
int len = strlen(input);
if(len > 0)
input++;//Go past the first char
if(len > 1)
input[len - 2] = '\0';//Replace the last char with a null termination
return input;
}
//...
//Call it like so
char str[512];
strcpy(str, "hello world");
char *pMod = getAllButFirstAndLast(str);
The safest way:
void getAllButFirstAndLast(const char *input, char *output)
{
int len = strlen(input);
if(len > 0)
strcpy(output, ++input);
if(len > 1)
output[len - 2] = '\0';
}
//...
//Call it like so
char mod[512];
getAllButFirstAndLast("hello world", mod);
The second way is less efficient but it is safer because you can pass in string literals into input. You could also use strdup for the second way if you didn't want to implement it yourself.
Related
Hello and Happy New Year!
I have a problem on recursion I am trying to solve which looks like the below. I've managed to get it to work, however an alternative method I wanted to use isn't working (the working line commented out).
I am not able to append a single char to char* array - compiler gives the error 'Unable to convert const char to char'
I've tried declaring x1 as array of like char[1] instead. I cannot declare x1,x2 as char* because they feed into the bigram function which takes char by reference specifically.
Any help would be greatly appreciated. Thank you very much.
void encode(char square[6][6], char* prepared, char* encoded){
// EXIT CONDITION:
if (strlen(prepared) == 0) {encoded[0] ='\0'; return;}
encode(square,++++prepared,++++encoded);
char x1
char x2;
bigram(square, prepared[0],prepared[1],x1,x2);
// bigram(square, prepared[0],prepared[1],encoded[0],encoded[1]); << WORKS
strcat(prepared,x1); // << DOES NOT WORK with 'cannot convert const char* to char*' error
strcat(prepared,x2); // << does not work
}
// I have to pass the chars by reference here per problem statement
bool bigram(char square[6][6], char inchar1,char inchar2,char& outchar1,char& outchar2){
/* some calcs which compute outchar1, outchar2 */
}
To append a single character to a string, various approaches exist. String memory management also needs consideration and usually hints to the best approached.
char* append(size_t sz, char *s, char ch) {
size_t len = strlen(s);
if (len + 1 >= sz) {
fprintf(stderr, "Insufficient room\n");
return NULL;
}
// Append via `len`
s[len++] = ch;
s[len] = '\0';
// OR
// strcat with compound literal
strcat(s, (char[2]) {ch});
return s;
}
As OP's wants to append 2 characters:
char* append2(size_t sz, char *s, char ch1, char ch2) {
size_t len = strlen(s);
if (len + 2 >= sz) {
fprintf(stderr, "Insufficient room\n");
return NULL;
}
// Append via `len`
s[len++] = ch1;
s[len++] = ch2;
s[len] = '\0';
// OR
// strcat with compound literal
strcat(s, (char[3]) {ch1, ch2});
return s;
}
Pedantic: Appending a null character is a special case not detailed above.
SOLVED (Thank you #pmg !!)
It was as simple as this instead of the two strcats. Strcats DO NOT work on a single character - they have to take a char* on the RHS:
*encoded++ = x1;
*encoded++ = x2;
In C programming, suppose that I have some input strings with unknown length like:
abcde.xxx
abc.xxx
abcdefgh.xxx
....
How can I take the last 4 characters from them? I tried this way but it doesn't work:
char dest[] = "abcdef.ghi";
char s[5];
memset(s, '\n', sizeof s);
strncpy(s, dest - 5, 4);
But I can't use strstr() since the dest may be wrong with the format xxxx.xxx like abcd.xxxy
char s[5] = {0};
size_t len = 0;
char dest[] = "abcdef.ghi";
char *p = strchr(dest, '.');
if(!p)
{
// error no '.'
return;
}
len = strlen(p);
if(len != sizeof(s)-1)
{
// More or less than 3 characters plus '.'
return;
}
strcpy(s, p);
When the string is null-terminated you can use strlen to get the lenght of the string:
char s[5];
size_t len, offset;
char dest[] = "abcdef.ghi";
len = strlen(dest);
memset( s, '\0', sizeof(char)*5);
offset = len-4;
strncpy( s, &dest[offset], 4 );
If this is not the case you can loop over the string as an array and look for your dot.
Afterwards you can use this index to calculate your correct offset. But be careful for that solution. If one string does not hate a dt and last free character you can cause an access violation.
I need to extract substrings that are between Strings I know.
I have something like char string = "abcdefg";
I know what I need is between "c" and "f", then my return should be "de".
I know the strncpy() function but do not know how to apply it in the middle of a string.
Thank you.
Here's a full, working example:
#include <stdio.h>
#include <string.h>
int main(void) {
char string[] = "abcdefg";
char from[] = "c";
char to[] = "f";
char *first = strstr(string, from);
if (first == NULL) {
first = &string[0];
} else {
first += strlen(from);
}
char *last = strstr(first, to);
if (last == NULL) {
last = &string[strlen(string)];
}
char *sub = calloc(strlen(string) + 1, sizeof(char));
strncpy(sub, first, last - first);
printf("%s\n", sub);
free(sub);
return 0;
}
You can check it at this ideone.
Now, the explanation:
1.
char string[] = "abcdefg";
char from[] = "c";
char to[] = "f";
Declarations of strings: main string to be checked, beginning delimiter, ending delimiter. Note these are arrays as well, so from and to could be, for example, cd and fg, respectively.
2.
char *first = strstr(string, from);
Find occurence of the beginning delimiter in the main string. Note that it finds the first occurence - if you need to find the last one (for example, if you had the string abcabc, and you wanted a substring from the second a), it might need to be different.
3.
if (first == NULL) {
first = &string[0];
} else {
first += strlen(from);
}
Handle situation, in which the first delimiter doesn't appear in the string. In such a case, we will make a substring from the beginning of the entire string. If it does appear, however, we move the pointer by length of from string, as we need to extract the substring beginning after the first delimiter (correction thanks to #dau_sama).
Depending on your specifications, this may or may not be needed, or another result might be expected.
4.
char *last = strstr(first, to);
Find occurence of the ending delimiter in the main string. Note that it finds the first occurence.
As noted by #dau_sama, it's better to search for ending delimiter from the first, not from beginning of the entire string. This prevents situations, in which to would appear earlier than from.
5.
if (last == NULL) {
last = &string[strlen(string)];
}
Handle situation, in which the second delimiter doesn't appear in the string. In such a case, we will make a substring until end of the string, so we get a pointer to the last character.
Again, depending on your specifications, this may or may not be needed, or another result might be expected.
6.
char *sub = calloc(last - first + 1, sizeof(char));
strncpy(sub, first, last - first);
Allocate sufficient memory and extract substring based on pointers found earlier. We copy last - first (length of the substring) characters beginning from first character.
7.
printf("%s\n", sub);
Here's the result.
I hope it does present the problem with enough details. Depending on your exact specifications, you may need to alter this somehow. For example, if you needed to find all substrings, and not just the first one, you may want to make a loop for finding first and last.
TY guys, worked using the form below:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *between_substring(char *str, char from, char to){
while(*str && *str != from)
++str;//skip
if(*str == '\0')
return NULL;
else
++str;
char *ret = malloc(strlen(str)+1);
char *p = ret;
while(*str && *str != to){
*p++ = *str++;//To the end if `to` do not exist
}
*p = 0;
return ret;
}
int main (void){
char source[] = "abcdefg";
char *target;
target = between(source, 'c', 'f');
printf("%s", source);
printf("%s", target);
return 0;
}
Since people seemed to not understand my approach in the comments, here's a quick hacked together stub.
const char* string = "abcdefg";
const char* b = "c";
const char* e = "f";
//look for the first pattern
const char* begin = strstr(string, b);
if(!begin)
return NULL;
//look for the end pattern
const char* end = strstr(begin, e);
if(!end)
return NULL;
end -= strlen(e);
char result[MAXLENGTH];
strncpy(result, begin, end-begin);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *between(const char *str, char from, char to){
while(*str && *str != from)
++str;//skip
if(*str == '\0')
return NULL;
else
++str;
char *ret = malloc(strlen(str)+1);
char *p = ret;
while(*str && *str != to){
*p++ = *str++;//To the end if `to` do not exist
}
*p = 0;
return ret;
}
int main(void){
const char* string = "abcdefg";
char *substr = between(string, 'c', 'f');
if(substr!=NULL){
puts(substr);
free(substr);
}
return 0;
}
I am writing a C program in Unix and cannot figure out how to set an array element to NULL. I need to be able to do this to remove multiple characters from a string.
You can't assign null to specific char array index as value represented by that index is char instead of pointer. But if you need to remove specific character from given string, you can implement this as follows
void removeChar(char *str, char garbage) {
char *src, *dst;
for (src = dst = str; *src != '\0'; src++) {
*dst = *src;
if (*dst != garbage) dst++;
}
*dst = '\0';
}
Test Program
#include<stdio.h>
int main(void) {
char* str = malloc(strlen("abcdef")+1);
strcpy(str, "abcdbbbef");
removeChar(str, 'b');
printf("%s", str);
free(str);
return 0;
}
output
acdef
If you have a char[], you can zero-out individual elements using this:
char arr[10] = "foo";
arr[1] = '\0';
Note that this isn't the same as assigning NULL, since arr[1] is a char and not a pointer, you can't assign NULL to it.
That said, that probably won't do what you think it will. The above example will produce the string f, not fo as you seem to expect.
If you want to remove characters from a string, you have to shift the contents of the string to the left (including the null terminator) using memmove and some pointer arithmetic:
Example:
#include <stdio.h>
#include <string.h>
int removechars(char *str, size_t pos, size_t cnt) {
size_t len = strlen(str);
if (pos + cnt > len)
return -1;
memmove(str + pos, str + pos + cnt, len - pos - cnt + 1);
return 0;
}
Then use it like so:
char str[12] = "hello world";
if (removechars(str, 5, 4) == 0) /* remove 4 chars starting at str[5] */
printf("%s\n", str); /* hellold */
If you're talking about an array of pointers (say char **), you'd just say array[element] = NULL;. But it sounds as though you really want to just truncate a string (char *), in which case you'd actually want to write string[index] = '\0', where \0 is the null byte. But, as far as I know, 0, '\0', and NULL are all equivalent and equal to 0 (please correct me if I'm wrong). Of course, for clarity, you should use 0 for numbers, '\0' for chars and strings, and NULL for pointers.
I'm stuck at yet another C problem. How can I concatenate two strings with the second string being inserted before the first string?
This is what I came up with. Unfortunately I'm stuck at all these pointer to chars, char arrays et cetera.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[] )
{
char* output;
int i;
for(i = 9; i > 0; i--)
{
unsigned int value = (unsigned int)i;
char buffer[20];
sprintf(buffer, "%u", value);
// strcat(ouput, buffer); // append before the string.
// first loop: 9
// second loop: 89
// third loop: 789
}
printf("%s", output);
}
How must I correct my code to make it work? I guess I have to somehow set the output variable to empty. When do I need fixed widths for the char array or the pointer? 20 was just a random guess from me.
I'm very confused, as your posted code has absolutely nothing to do with the problem you state. (Well, they both use strings, but that's about it)
char* src = "Hello, ";
char* dest = "World!";
char* temp;
temp = malloc(strlen(src) +strlen(dest) + 1);
strcpy(temp, src);
strcat(temp, dest);
dest = temp;
Unless dest is a fixed buffer of adequate size for the combined string. If so, then replace the last line with:
strcpy(dest, temp);
free(temp);
Now, if you want to specifically build the list of digits backwards, let's try a different tack:
char buffer[10];
buffer[9] = '\0'; // null terminate our string.
char* output;
int i;
for(i = 9; i > 0; i--)
{
// this is a fast way of saying, sprintf("%u", i);
// works only for single digits
char d = (char)('0' + i);
buffer[i-1] = d;
output = &buffer[i-1];
printf("%s", output);
}
Usually, you should just avoid the situation to start with. The most obvious solution for your example would be to simply count upward to start with. When that's not suitable, a recursive solution to reverse the order in which the string is built can still allow you to generate the string from beginning to end:
int build_string(int value, char *string) {
char temp[10];
if (value > -1)
build_string(value-1, string);
sprintf(temp, "%d", value); // use snprintf if available.
strcat(string, temp);
return string;
}
int main() {
char result[20] = {0};
build_string(9, result);
printf("%s", result);
return 0;
}
You can append the integer at the end of the string as:
int i;
char buffer[20];
for(i = 0; i < 10; i++) {
sprintf(buffer+i, "%u", i);
}
printf("%s", buffer); // prints 0123456789
For your stated problem (insert one string in front of another), this code will do the job - but has no error checking. It assumes there is enough space in the target buffer for the existing string and the new prefix:
/* Insert string t in front of string s in string s */
char *strinsert(char *s, const char *t)
{
char *p = s + strlen(s);
char *q = p + strlen(t);
char *r = s;
while (p >= s)
*q-- = *p--;
while (*t)
*s++ = *t++;
return(r);
}
What it does is copy the existing string up by the correct number of places so that there is space for the new string at the beginning.
Assuming that the destination buffer is big enough and that the source and destination do not overlap:
// not sure what order to put the params - the usual C way is destination
// followed by source, but it's also potentially confusing that the result of
// prepend(foo,bar) is "<bar><foo>".
char* prepend(char *restrict dest, const char *restrict src) {
size_t len = strlen(src);
memmove(dest + len, dest, strlen(dest));
return memcpy(dest, src, len);
}
If the buffers may overlap (for example, if src is the second half of dest), this approach doesn't work.
If the destination buffer is not big enough, then someone has to allocate new memory for the result, in which case the question of which is the "source" and which the "destination" disappears - they're both "source" and neither is "destination".