C - copy the last characters from an unknown length string - c

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.

Related

How to copy string char by char in c?

I have a chunk of memory I'm declaring on the heap.
char *str;
str = (char *)malloc(sizeof(char) * 10);
I have a const string.
const char *name = "chase";
Because *name is shorter than 10 I need to fill str with chase plus 5 spaces.
I've tried to loop and set str[i] = name[i] but there's something I'm not matching up because I cannot assign spaces to the additional chars. This was where I was going, just trying to fill str with all spaces to get started
int i;
for (i = 0; i < 10; i++)
{
strcpy(str[i], ' ');
printf("char: %c\n", str[i]);
}
As the others pointed out, you need
//malloc casting is (arguably) bad
str = malloc(sizeof(char) * 11);
and then, just do
snprintf(str, 11, "%10s", name);
Using snprintf() instead of sprintf() will prevent overflow, and %10swill pad your resulting string as you want.
http://www.cplusplus.com/reference/cstdio/snprintf/
If you want str to have 10 characters and still be a C-string, you need to '\0' terminate it. You can do this by mallocing str to a length of 11:
str = malloc(11);
Note there's no need to cast the return pointer of malloc. Also, sizeof(char) is always 1 so there's no need to multiply that by the number of chars that you want.
After you've malloc as much memory as you need you can use memset to set all the chars to ' ' (the space character) except the last element. The last element needs to be '\0':
memset(str, ' ', 10);
str[10] = '\0';
Now, use memcpy to copy your const C-string to str:
memcpy(str, name, strlen(name));
easy to use snprintf like this
#include <stdio.h>
#include <stdlib.h>
int main(){
char *str;
str = (char *)malloc(sizeof(char)*10+1);//+1 for '\0'
const char *name = "chase";
snprintf(str, 11, "%-*s", 10, name);//11 is out buffer size
printf(" 1234567890\n");
printf("<%s>\n", str);
return 0;
}

Getting the first 10 characters of a string?

I have not been able to find any information with a web-search. Where should I be looking?
char myString[256]; // Input string
char dest[256]; // Destination string
strncpy(dest, myString, 10);
dest[10] = 0; // null terminate destination
char source[] = "abcdefthijklmn";
char target[100];
strncpy(target, source, 10);
target[10] = '\0'; // IMPORTANT!
Adding to the above answers:
char* someString = "your string goes here";
int main()
{
int n = 10;
printf("(%.*s)\n", n, someString);
return 0;
}
There are many different ways to achieve your goal:
You can use snprintf (safest):
char source[] = "abcdefthijklmn";
char target[100];
snprintf(target, sizeof target, "%.10s", source);
You can use strncat if you know the destination has at least 11 elements:
char source[] = "abcdefthijklmn";
char target[100];
*target = '\0';
strncat(target, source, 10);
You can use strlen and memcpy (same assumption about the size of destination):
char source[] = "abcdefthijklmn";
char target[100];
size_t len = strlen(source);
if (len > 10)
len = 10;
memcpy(target, source, len);
target[len] = '\0';
You can use a loop (same assumption about the size of destination):
char source[] = "abcdefthijklmn";
char target[100];
size_t i;
for (i = 0; i < 10; i++) {
target[i] = source[i];
}
target[i] = '\0';
You could but should not use strncpy()
If you're looking for a good source, here's an example of an online man page you can use:
http://linux.die.net/man/3/strncpy
Important to note: you could also use memcpy instead of strncpy, but it requires you to add your own null-terminating byte.
Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated.
Hence, memcpy and strncpy work almost the same here, and memcpy is more efficient and less prone to error.
I got it to work like this.
# include <stdio.h>
# include <string.h>
//Strings. String lenght terminator.
//KHO2016.no1. mingw (TDM-GCC-32) . c-ansi .
int main ()
{
//declare
char src_str[20],dst_str[10];
//valuate
printf ("Enter a sentance of 20 letters\n");
gets (src_str);
strcpy (dst_str,src_str);
//calculate
dst_str [10] ='\0'; // from the "www.stack overflow"
printf ("%s",dst_str);
printf ("\n");
//terminate
return 0;
}
You can also use sprintf with .10 precision format:
#include <stdio.h>
#include <string.h>
int main(void)
{
char source[] = "abcdefghijklmnopqrstuvwxyz";
char dest[11];
memset(dest, '\0', sizeof(dest));
sprintf(dest, "%.10s", source);
printf("%s", dest); // abcdefghij
return 0;
}

How to set element in array to null in C program

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.

How to concatenate two strings where the source string should be appended before the destination string?

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".

Strip first and last character from C string

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.

Resources