How would I remove the first three letters of a string with C?
Add 3 to the pointer:
char *foo = "abcdef";
foo += 3;
printf("%s", foo);
will print "def"
void chopN(char *str, size_t n)
{
assert(n != 0 && str != 0);
size_t len = strlen(str);
if (n > len)
return; // Or: n = len;
memmove(str, str+n, len - n + 1);
}
An alternative design:
size_t chopN(char *str, size_t n)
{
assert(n != 0 && str != 0);
size_t len = strlen(str);
if (n > len)
n = len;
memmove(str, str+n, len - n + 1);
return(len - n);
}
For example, if you have
char a[] = "123456";
the simplest way to remove the first 3 characters will be:
char *b = a + 3; // the same as to write `char *b = &a[3]`
b will contain "456"
But in general case you should also make sure that string length not exceeded
Well, learn about string copy (http://en.wikipedia.org/wiki/Strcpy), indexing into a string (http://pw1.netcom.com/~tjensen/ptr/pointers.htm) and try again. In pseudocode:
find the pointer into the string where you want to start copying from
copy from that point to end of string into a new string.
In C, string is an array of characters in continuous locations. We can't either increase or decrease the size of the array. But make a new char array of size of original size minus 3 and copy characters into new array.
Related
i have try this code made by me but no output and there's no errors?
#include <stdio.h>
void reverse(char *p,char *v,int size){
for(int i=size-1,j=0;i<0;i--){
*(v+j) = *(p+i);
j++;
}
}
int main(){
char word[6] = {"hello"};
char re_word[6];
re_word[5]='\0';
reverse(word,re_word,6);
printf("%s",re_word);
}
Using pointers it can look like this:
void reverse(char *w, char *revw, int slen) {
revw += slen - 1; // forward to pos. of last letter
revw[1] = '\0'; // one further *(revw+1)
while (*w)
*revw-- = *w++;
}
This is clear and symmetric, once it works, while your i-- and j++ are far apart.
slen is meant to be the number of letters w/o termination. Here the call:
char word[] = {"hello"};
char re_word[sizeof word];
reverse(word, re_word, sizeof word - 1);
strlen() should be used, probably, but these lines show how you can and have to control not just the total size but especially the last byte of the char array.
Without the correct length, reverse() would have to do a strlen() first, because it has to know how far away to put the first letter.
This *(v+j) = *(p+i) is more or less v[j] = p[i] and does not really take advantage of pointers, on the contrary.
(revw
caller) in reverse()
| |
v v
-4 -3 -2 -1 revw +1
o l l e h \0
... revw-- revw[1]
So revw is maybe not the best name inside the function; revw_first_backwards is meant...or fill_start. But before I fill backwards I do the one additional write to the right side to terminate the string: array notation using a pointer: revw[1] = '\0'.
First of all, i < 0 will always be false, given i = size - 1 > 0.
What you want is i >= 0.
Also, given size = 6, size - 1 will be equal to 5, and that is the NULL terminator position since array indexing in C start from 0. Perhaps use a C function such as strlen() to calculate the length rather than hard coding it.
void reverse(char *p, char *v, size_t size)
{
for (int i = size - 1, j = 0; i >= 0; i--)
{
*(v + j) = *(p + i);
j++;
}
}
int main()
{
char word[6] = {"hello"};
char re_word[6];
re_word[5] = '\0';
reverse(word, re_word, 5); /* or reverse(word, re_word, strlen(word)) */
printf("%s", re_word);
}
I am trying to center align strings in a total of 16 spaces to eventually print them on a 16x2 LCD Display. The values are grabbed from a database, and put in a global variable that is constantly being updated.
The values in the database are already in string format.
What I'd like to do is after getting the value from the DB, update the global variable to contain a string centered in 16 spaces.
I understand using global variables may not be best practice but ignoring that is there a way to do this?
char * systemInfoValues[5] = {" "," "," "," "," "}
for(int i=0; i< 5; i++){
systemInfoValues[i] = PQgetvalue(res,i,0); //get the value from db;
int len = strlen(systemInfoValues[i]);
char tmp[20];
sprintf(tmp,"%*s", (17-len)/2 + len, systemInfoValues[i]);
strcpy(systemInfoValues[i],tmp);
}
0 = a blank space
xxxxx = string from db
If the length of the string is odd
I expect the output to be [00xxxxxxxxxxxxx0]
if the length of the string is even
I expect the output to be [00xxxxxxxxxxxx00]
It is simple 6 line function. symetry is giving you the option
char *centerinstring(char *buff, size_t len, const char *str, int symetry)
{
size_t strl = strlen(str);
size_t pos = (len - strl) / 2 + (strl & 1) * !!symetry;
memset(buff,' ', len);
buff[len] = 0;
memmove(buff + pos, str, strl);
return buff;
}
int main()
{
char buff[11];
printf("|%s|\n", centerinstring(buff, 10, "1234567", 1));
printf("|%s|\n", centerinstring(buff, 10, "1234567", 0));
return 0;
}
or with the option to allocate memory for the buff (if you pass NULL
char *centerinstring(char *buff, size_t len, const char *str, int symetry)
{
size_t strl = strlen(str);
size_t pos = strl / 2 + (strl & 1) * !!symetry;
buff = buff ? malloc(len + 1) : buff;
if(buff)
{
memset(buff,' ', len);
buff[len] = 0;
memmove(buff + pos, str, strl);
}
return buff;
}
sprintf()-comfort:
#include <assert.h>
#include <string.h>
#include <stdio.h>
void center(char *dst, char *src, size_t width)
{
assert(dst && src && width);
size_t src_len = strlen(src);
if (src_len >= width) {
*dst = '\0';
return;
}
int right = (int)(width - src_len) / 2;
int left = right + (int)src_len;
right -= (src_len & 1);
sprintf(dst, "%*s%*s", left, src, right, "");
}
int main(void)
{
char destination[17];
center(destination, "12345678901234", sizeof(destination));
printf("\"%s\"\n", destination);
}
You can do it in another way (without using the sprintf function).
I don't know about any interface of the sprintf function that would allow you to do it, but you can solve the problem using simple strcpy of variables.
This is a main program that would solve your problem, it is documented in itself, so you should be able to understand how to apply this to your code:
#include <stdio.h>
#include <string.h>
/* This simple program would transfer the original string that is in the
* out_value to be centralized in this variable. */
int main(void) {
char out_value[17] = "1234567891";
char temp[20] = {0};
int first_index = 0;
int string_length = 0;
/* Copy the string to the temp variable, to modify the chars in
* out_value. */
strcpy(temp, out_value);
/* Find out the index for the first char to be placed in the centralized
* string. */
string_length = strlen(temp);
first_index = (16 - string_length) / 2;
/* Set all the values of the out_value to be the wanted value of space (here
* it is 0 for visualizing, it can be space to not be present). */
memset(out_value, '0', 16);
/* Copy the original string back, moving the start of it, so it would be
* centralized. */
strncpy(&(out_value[first_index]), temp, string_length);
/* Print the string. */
printf("%s", out_value);
}
When modifying your code to work with this, the code would look something like this:
char * systemInfoValues[5] = {NULL}
for(int i=0; i< 5; i++){
systemInfoValues[i] = PQgetvalue(res,i,0); //get the value from db;
int len = strlen(systemInfoValues[i]);
char tmp[20];
int first_index = 0;
strcpy(tmp, systemInfoValues[i]);
first_index = (16 - len) / 2;
memset(systemInfoValues[i], ' ', 16);
strncpy(&(systemInfoValues[i][first_index]), tmp, len);
}
Note that I changed the initializing of the value of systemInfoValues. When you initialized it, you put empty strings there. Note that this is a bad habit. Putting empty strings there (or strings with a single space) would allocate the memory for this string (which you will never use).
You didn't include the definition to the function of PQgetvalue, but assuming that it would return a char pointer, this should work.
But, this code would change the global value as well. If you don't want to change it, you shoudn't put the result there, but copy the result to the string before doing any changes to it.
After modifying the code, it should look like this:
char systemInfoValues[5][17] = {{0}}
for(int i=0; i< 5; i++){
char *global_reference = PQgetvalue(res,i,0); //get the value from db;
int len = strlen(systemInfoValues[i]);
char tmp[20];
int first_index = 0;
strcpy(tmp, global_reference);
first_index = (16 - len) / 2;
memset(systemInfoValues[i], ' ', 16);
strncpy(&(systemInfoValues[i][first_index]), tmp, len);
}
edit: apperently there is an interface for the sprintf function to work (as you originally wanted). To see it, refer to the answer of Swordfish
Hy everybody!
I am trying to write a program that checks if a given string of text is a palindrome (for this I made a function called is_palindrome that works) and if any of it's substrings is a palindrome, and I can't figure out what is the optimal way to do this:
For example, for the string s = "abcdefg" it should first check "a", then "ab", "abc", "abcd" and so on, for each character
In Python this is the equivalent of
s[:1], s[:2], ... (a, ab, ...)
s[1:2], s[1:3] ... (b, bc, ...)
What function/method is there that I can use in a similar way in C ?
This is the one liner I use to get a slice of a string in C.
void slice(const char *str, char *result, size_t start, size_t end)
{
strncpy(result, str + start, end - start);
}
Pretty straightforward.
Given you've checked boundaries and made sure end > start.
This slice_str() function will do the trick, with end actually being the end character, rather than one-past-the-end as in Python slicing:
#include <stdio.h>
#include <string.h>
void slice_str(const char * str, char * buffer, size_t start, size_t end)
{
size_t j = 0;
for ( size_t i = start; i <= end; ++i ) {
buffer[j++] = str[i];
}
buffer[j] = 0;
}
int main(void) {
const char * str = "Polly";
const size_t len = strlen(str);
char buffer[len + 1];
for ( size_t start = 0; start < len; ++start ) {
for ( int end = len - 1; end >= (int) start; --end ) {
slice_str(str, buffer, start, end);
printf("%s\n", buffer);
}
}
return 0;
}
which, when used from the above main() function, outputs:
paul#horus:~/src/sandbox$ ./allsubstr
Polly
Poll
Pol
Po
P
olly
oll
ol
o
lly
ll
l
ly
l
y
paul#horus:~/src/sandbox$
There isn't; you'll have to write your own.
In order to check a string, you would need to supply to the number of characters to check in order to check for a palindrome:
int palindrome(char* str, int len)
{
if (len < 2 )
{
return 0;
}
// position p and q on the first and last character
char* p = str;
char* q = str + len - 1;
// compare start char with end char
for ( ; p < str + len / 2; ++p, --q )
{
if (*p != *q)
{
return 0;
}
}
return 1;
}
now you would need to call the function above for each substring (as you described it, i.e. always starting from the beginning) e.g.
char candidate[] = "wasitaratisaw";
for (int len = 0; len < strlen(candidate); ++len)
{
if (palindrome(candidate, len))
{
...
}
}
disclaimer: not compiled.
Honestly, you don't need a string slicing function just to check for palindromes within substrings:
/* start: Pointer to first character in the string to check.
* end: Pointer to one byte beyond the last character to check.
*
* Return:
* -1 if start >= end; this is considered an error
* 0 if the substring is not a palindrome
* 1 if the substring is a palindrome
*/
int
ispalin (const char *start, const char *end)
{
if (start >= end)
return -1;
for (; start < end; ++start)
if (*start != *--end)
return 0;
return 1;
}
With that, you can create the following:
int
main ()
{
const char *s = "madam";
/* i: index of first character in substring
* n: number of characters in substring
*/
size_t i, n;
size_t len = strlen (s);
for (i = 0; i < len; ++i)
{
for (n = 1; n <= len - i; ++n)
{
/* Start of substring. */
const char *start = s + i;
/* ispalin(s[i:i+n]) in Python */
switch (ispalin (start, start + n))
{
case -1:
fprintf (stderr, "error: %p >= %p\n", (void *) start, (void *) (start + n));
break;
case 0:
printf ("Not a palindrome: %.*s\n", (int) n, start);
break;
case 1:
printf ("Palindrome: %.*s\n", (int) n, start);
break;
} /* switch (ispalin) */
} /* for (n) */
} /* for (i) */
}
Of course, if you really wanted a string slicing function merely for output (since you technically shouldn't cast a size_t to int), and you still want to be able to format the output easily, the answer by Paul Griffiths should suffice quite well, or you can use mine or even one of strncpy or the nonstandard strlcpy, though they all have their strengths and weaknesses:
/* dest must have
* 1 + min(strlen(src), n)
* bytes available and must not overlap with src.
*/
char *
strslice (char *dest, const char *src, size_t n)
{
char *destp = dest;
/* memcpy here would be ideal, but that would mean walking the string twice:
* once by calling strlen to determine the minimum number of bytes to copy
* and once for actually copying the substring.
*/
for (; n != 0 && *src != 0; --n)
*destp++ = *src++;
*destp = 0;
return dest;
}
strslice actually works like a combination of strncpy and the nonstandard strlcpy, though there are differences between these three functions:
strlcpy will cut the copied string short to add a null terminator at dest[n - 1], so copying exactly n bytes before adding a null terminator requires you to pass n + 1 as the buffer size.
strncpy may not terminate the string at all, leaving dest[n - 1] equal to src[n - 1], so you would need to add a null terminator yourself just in case. If n is greater than the src string length, dest will be padded with null terminators until n bytes have been written.
strslice will copy up to n bytes if necessary, like strncpy, and will require an extra byte for the null terminator, meaning a maximum of n+1 bytes are necessary. It doesn't waste time writing unnecessary null terminators as strncpy does. This can be thought of as a "lightweight strlcpy" with a small difference in what n means and can be used where the resulting string length won't matter.
You could also create a memslice function if you wanted, which would allow for embedded null bytes, but it already exists as memcpy.
There is not any built-in function/method in any standard C library which can handle this. However, you can come up with your own method to do the same.
Given a char[] in c, I want to specify the length of output from that array starting with some position in printf, how can I conveniently do that?
For example, I want to print the portion from position 3 (indexed from 0) to position 8:
printf("%s", char_array+3..char_array+8)
I could make a temporary char[] with the desired length, but that is not very convenient. Or I could write a substring function
char* substring(const char* str, size_t begin, size_t len) {
if (str == 0 || strlen(str) == 0 || strlen(str) < begin || strlen(str) < (begin + len))
return 0;
return strndup(str + begin, len);
}
But if I call
printf("%s", substring(s, 3, 5));
I am afraid there will be memory leak.
What do you think about the best way to do this?
#include <stdio.h>
int printmid(const char *data, size_t start, int len) {
return printf("%.*s", len, data + start);
}
int main(void) {
char data[] = "Hello, World!";
printmid(data, 3, 6);
puts("");
return 0;
}
output
lo, Wo
int end = 8;
int bgn = 3;
int len = end - bgn + 1;
printf("%*.*s", len, len, char_array + bgn);
Note that len should be an int (and not, for example, the difference between two pointers - that's a ptrdiff_t or size_t). You can also omit the first length if you want - both can be specified, and they have specific meanings if the source string is shorter than the designated length (meaning there's a null byte in the string before char_array + end). Clearly, if the string in char_array is shorter than 4 bytes, then what follows the terminating null is probably garbage, and GIGO applies. If you're not certain the string is at least 8 bytes long, you might prefer to have the output left justified, in which case, insert a minus - before the first *; as written, the shorter string would be right justified.
What would be the fastest/shortest way to create a string of repeating characters.
For instance, n = 10, char = '*', resulting allocated string: **********
Use memset.
int n = 10;
char c = '*';
char* buf = malloc(n+1);
memset(buf, c, n);
buf[n] = '\0';
free(buf);
memset(buf, '*', 10); buf[10]=0;
Replace '*' and 10 with the values you want, and if the length is not known in advance and could be large, use buf=malloc(n+1); to get your buffer.
char *allocate(int c, size_t n)
{
if(!c) return calloc(n + 1);
char *s = malloc(n + 1);
memset(s, c, n);
s[n] = '\0';
return s;
}
Honestly, why are you trying to do it fastest? Why not just do it, and then speed it up later if you need to?
Particularly, if you're only creating this to output it, you could just
void printtimes(int c, size_t n, FILE *f)
{
while(n--) fputc(c, f);
}