Really need help!
This code should find a largest palindrome in a string. Which means if there are "abcdcba" and "cdc" in the same string, it should print "abcdcba" out since the length is longer. The function takes a string str and 2 points i and j and determines whether the string from i to j is a palindrome. If it is a palindrome, returns the length of the palindrome and if it is not, returns -1.
int palindromelength(char *str, int i, int j){
int *first = &i, *last = &j;
int len;
while (first < last){
if (toupper(*first) != toupper(*last))
return -1;
first++;
last--;
}
len = last - first;
return (len);
}
int main() {
int length, i, j;
char str;
scanf("%s", &str);
length = strlen(str);
printf("Length = %d\n", palindromelength(str, i, j));
//should print out largest palindrome.
return 0;
}
What you describe and what the function is supposed to do are inconsistent:
"The function takes a string str and 2 points i and j and determines whether the string from i to j is a palindrome. If it is a palindrome, returns the length of the palindrome and if it is not, returns -1"
Therefore the function should returen either j - i or -1
char str;
scanf("%s", &str);
This is not how you should declare then initialize a string. Use instead:
char str[512];
scanf ("%s", str);
Also note that you'll need to ask the user to input the length of that string, and you'll need to pass that length as argument in the "palindromelength" function
You access the (i+1)th entry of your string like this:
str[i]
but before, you need to check that i is strictly lower than the length of your string. And don't forget to initialize i and j in your main() function
Before starting to code, write an algorithm in pseudocode which can solve your problem and evaluate its complexity. In this case, the comlpexity of the most obvious algorithm would be O(n^2), where n is the length of the string. This most obvious solution would be to check every substring, but maybe there are better algorithms: en.wikipedia.org/wiki/Longest_palindromic_substring
You send your function a string and two indexes, then immediately take the address of two indexes and proceeded to increment/decrement the indexes without any relation or regard to your string. That will never get you anywhere.
While it is fine to try and do all comparisons with indexes as integers, it is probably a bit easier to approach finding palindromes operating on strings and characters instead. You use the indexes to set the start and end position within the string. The indexes by themselves are just numbers. Your first and last should not hold the address to the intergers, they should hold the address of the first and last characters of your search string.
Below is a quick example of using the indexes to locate the start and end characters for your search. Note: I use p (pointer) for first and ep (end pointer) for your last. Look over the logic and let me know if you have questions. The program takes 3 arguments, the string, start and end indexes within the string (0 based indexes):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXP 128
int get_palindrome (char *s, size_t i, size_t j);
int main (int argc, char **argv) {
if (argc < 4 ) {
fprintf (stderr, "error: insufficient input, usage: %s str i j\n", argv[0]);
return 1;
}
size_t i = atoi (argv[2]);
size_t j = atoi (argv[3]);
char palindrome[MAXP] = {0};
int len = get_palindrome (argv[1], i, j);
if (len > 0)
{
strncpy (palindrome, argv[1] + i, len);
printf ("\n palindrome: %s (%d chars)\n\n",
palindrome, len);
}
else
printf ("\n no palindrome for for given indexes.\n\n");
return 0;
}
int get_palindrome (char *s, size_t i, size_t j)
{
if (!s || *s == 0) return -1;
int len = 0;
char *p = s + i; /* set start/end pointers */
char *ep = s + j + 1;
char *sp = NULL;
int c = *ep; /* save char from string */
*ep = 0; /* null-terminate at end */
char *s2 = strdup (p); /* copy string to s2 */
*ep = c; /* replace original char */
p = s2; /* set s2 start/end ponters */
ep = s2 + j - i;
while (ep > p) /* check for palindrome */
{
if (toupper(*ep) != toupper(*p))
{
*ep = 0;
sp = NULL;
}
else if (!sp)
sp = p;
p++, ep--;
}
len = sp ? (int) strlen (sp) : -1; /* get length */
if (s2) free (s2); /* free copy of string */
return len; /* return len or -1 */
}
Output
$ ./bin/palindrome 1234abcdcba 4 10
palindrome: abcdcba (7 chars)
Note the use of size_t type instead of int for i & j. i & j are indexes and will not be negative for the purpose of this problem. Try to always choose your data type to best fit your data. It will help identify and prevent problems in your code.
Also note, you should make a copy of the string in the function (if you are concerned about preserving the original). Inserting null-terminating characters locating palindromes will alter the original string otherwise.
There is an easy to understand solution to find out longest palindrome in a string.
Key Concept: at the center of a palindrome, characters are always of the form
"....x y x...." or "......x x......"
step1: scan the string from start to end for the xyx or xx patterns and store the center indices in an auxiliary array.
step2: now around each center try to expand the string in both direction and store the lengths.
step3: return the max length.
This approach takes O(N2) order time.
Related
I am trying to reverse a string. scanf is working well but when I use fixed string then it gives garbage value. So where is the fault ?
#include<stdio.h>
#include<string.h>
int main()
{
char s[50]="Hi I Love Programming";
char rev[strlen(s)];
int i,k;
k=strlen(s);
for(i=0; i<strlen(s); i++)
{
rev[k]=s[i];
k--;
}
printf("The reverse string is: %s\n", rev);
}
Your program has two issues:
1.
char rev[strlen(s)];
You forgot to add an element for the string-terminating null character '\0'.
Use:
char rev[strlen(s) + 1];
Furthermore you also forgot to append this character at the end of the reversed string.
Use:
size_t len = strlen(s);
rev[len] = '\0';
Note, my len is the k in your provided code. I use the identifier len because it is more obvious what the intention of that object is. You can use strlen(s) because the string has the same length, doesn´t matter if it is in proper or reversed direction.
2.
k=strlen(s);
for(i=0; i<strlen(s); i++)
{
rev[k]=s[i];
k--;
}
With rev[k] you accessing memory beyond the array rev, since index counting starts at 0, not 1. Thus, the behavior is undefined.
k needs to be strlen(s) - 1.
Three things to note:
The return value of strlen() is of type size_t, so an object of type size_t is appropriate to store the string length, not int.
It is more efficient to rather calculate the string length once, not at each condition test. Use a second object to store the string length and use this object in the condition of the for loop, like i < len2.
char s[50]="Hi I Love Programming"; can be simplified to char s[]="Hi I Love Programming"; - The compiler automatically detects the amount of elements needed to store the string + the terminating null character. This safes unnecessary memory space, but also ensures that the allocated space is sufficient to hold the string with the null character.
The code can also be simplified (Online example):
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[] = "Hi I Love Programming";
size_t len = strlen(s);
char rev[len + 1];
size_t i,j;
for(i = 0, j = (len - 1); i < len; i++, j--)
{
rev[j] = s[i];
}
rev[len] = '\0';
printf("The reverse string is: %s\n", rev);
}
Output:
The reverse string is: pgnimmargorP evoL I iH
your program is hard to understand. Here you have something much simpler (if you want to reverse the string of course)
#include <stdio.h>
#include <string.h>
char *revstr(char *str)
{
char *start = str;
char *end;
if(str && *str)
{
end = str + strlen(str) - 1;
while(start < end)
{
char tmp = *end;
*end-- = *start;
*start++ = tmp;
}
}
return str;
}
int main()
{
char s[50]="Hi I Love Programming";
printf("%s", revstr(s));
}
https://godbolt.org/z/5KX3kP
I have an array:
char arr[]="This is the string";
For instance, if I want to print only first 5 characters of that string, I have tried the following:
printf("%-5s",arr);
But it is printing whole string. Why?
You can use %.*s, it takes size of intended bytes to be printed and pointer to char as arguments when using with printf. For example,
// It prints This
printf("%.*s", 4, arr);
But it is printing whole string. Why?
You are using %-5s meaning the - left-justifies your text in that field.
En passant, the output cannot be achieved by using the accepted answer as simply as the code snippet, even if it may be seemed derisively.
int i;
char arr[]="This is the string";
for (i = 1; i < sizeof(arr); ++i) {
printf("%.*s\n", i, arr);
}
Output:
T
Th
Thi
This
This
This i
This is
This is
This is t
This is th
This is the
This is the
This is the s
This is the st
This is the str
This is the stri
This is the strin
This is the string
- is a printf formater for justification, not precision.
What you want is the . formater which is used for precision :
printf("%.5s", arr);
This will print the first 5 elements of arr.
If you want to learn more about printf formaters, take a look at this link.
for example substring extraction function (extracts substring to the buff)
char *strpart(char *str, char *buff, int start, int end)
{
int len = str != NULL ? strlen(str) : -1 ;
char *ptr = buff;
if (start > end || end > len - 1 || len == -1 || buff == NULL) return NULL;
for (int index = start; index <= end; index++)
{
*ptr++ = *(str + index);
}
*ptr = '\0';
return buff;
}
You can do it quite simply in a number of ways. With a loop, looping the number of times desired, picking off chars each time, you can walk a pointer down the string an temporary nul-terminate after the 5th character, or you can simply use strncpy to copy 5 chars to a buffer and print that. (that is probably the simplest), e.g.
#include <stdio.h>
#include <string.h>
int main (void)
{
char arr[]="This is the string",
buf[sizeof arr] = ""; /* note: nul-termination via initialization */
strncpy (buf, arr, 5);
printf ("'%s'\n", buf);
return 0;
}
Example Use/Output
$ ./bin/strncpy
'This '
Look things over and let me know if you have any questions.
void split(char array[]) {
int length, length2, half;
char first_half[BUF], sec_half[BUF];
length = strlen(array);
length2 = length / 2;
length -= length2;
strncpy(first_half, array, length - 1);
strncpy(sec_half, (array + length), length2 - 1);
printf("%s\n", first_half);
printf("%s\n", sec_half);
}
If input is "People", it outputs:
Pe0z
plcy etc... Just wondering what's the problem here.
My question is not the same as the question mentioned. I am not trying to insert a word in the middle of another word, I am trying to split a word in half and put the two halves in two strings.
OP's trouble is that first_half[BUF], sec_half[BUF] are not certainly null character terminated - a short coming of strncpy().
strncpy( first_half, array, length);
// printf( "%s\n", first_half );
// alternative limited width print, even if `first_half` lacks a null character.
printf( "%.*s\n", length, first_half );
trying to split a wordstring in half and put the two halves in two strings.
Below is a variable length array (VLA) approach.
I recommend memcpy() as that is often fastest for long strings and lest error prone than strncpy() #Blastfurnace. YMMV.
void split(const char array[]) {
size_t a_length = strlen(array);
size_t l_length = a_length / 2;
size_t r_length = a_length - l_length;
char l_half[l_length + 1], r_half[r_length + 1]; // + 1 for null character
memcpy(l_half, array, l_length);
l_half[l_length] = '\0';
memcpy(r_half, array + l_length, r_length + 1); // +1 for null character
printf("<%s>\n", l_half);
printf("<%s>\n", r_half);
}
size_t, an unsigned type, is the right sized integer type to use for array indexing. int maybe insufficient. Note that strlen() returns type size_t.
If all that is wanted is to print the 2 halves, not much code needed:
void split_print(const char array[]) {
int half = strlen(array) / 2;
printf("%.*s\n", half, array);
printf("%s\n", array + half);
}
One other issue not yet considered is "How do I handle words with an odd number of characters?". It's easy to split 1234 into 12 and 34, but how do you split 123? You must decide how to test for odd/even and decide which half gets the extra character (generally the first half, but it's up to you). You should also consider splitting strings of any size (and validate against processing a NULL pointer or empty-string passed to your function).
To handle checking odd/even length, all you need to do is check the 1st-bit of length on little-endian systems, or for complete portability just use modulo 2. If the 1st-bit (on little-endian) or the result of len % 2 is 0 it's even, otherwise the length is odd. (if odd, just add +1 character to the first half).
If your compiler supports Variable Length Array C99 extensions, the problem becomes simply a matter of declaring the two VLAs and letting the compiler handle the work, e.g.
void split_vla (char *s)
{
if (!s || !*s) { /* validate parameter not NULL or empty-string */
fprintf (stderr, "error: s NULL or empty-string.\n");
return;
}
size_t l = strlen (s),
n = (l % 2 == 0) ? l / 2 : l / 2 + 1;
char s1[n + 1], s2[n + 1]; /* declare VLAs */
memcpy (s1, s, n); /* memcpy chars to each half */
memcpy (s2, s + n, l - n);
s1[n] = 0; /* affirmatively nul-terminate */
s2[l - n] = 0;
printf ("s : %s\ns1 : %s\ns2 : %s\n", s, s1, s2);
}
If it doesn't, you can always dynamically allocate storage for each of the halfs (and if you choose calloc over malloc, then your storage is initialized to all zeros (providing a nul-byte at the end of each half), e.g.
void split_dyn (char *s)
{
if (!s || !*s) { /* validate parameter not NULL or empty-string */
fprintf (stderr, "error: s NULL or empty-string.\n");
return;
}
size_t l = strlen (s),
n = (l % 2 == 0) ? l / 2 : l / 2 + 1;
char *s1, *s2;
/* allocate storage for s1 & s2 and validate allocation */
if (!(s1 = calloc (n + 1, 1)) || !(s2 = calloc (n + 1, 1))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
exit (EXIT_FAILURE);
}
memcpy (s1, s, n); /* memcpy chars to each half */
memcpy (s2, s + n, l - n);
printf ("s : %s\ns1 : %s\ns2 : %s\n", s, s1, s2);
free (s1); /* don't forget to free the memory you allocate */
free (s2);
}
Either way is fine depending on what your compiler supports. You are free to use malloc and affirmatively nul-terminate as was done in the VLA example. Also be aware that alloca gives similar functionality to what you get with VLAs, but provides a bit more flexibility in the scope for your arrays (not relevant here since the VLAs are declared with function scope but be aware of the additional method). Give both examples a try and let me know if you have further questions.
Example Use/Output
$ ./bin/str_split_half 123456789
s : 123456789
s1 : 12345
s2 : 6789
$ ./bin/str_split_half 1234567890
s : 1234567890
s1 : 12345
s2 : 67890
$ ./bin/str_split_half 1
s : 1
s1 : 1
s2 :
Since I see that there is a concern about performance, I'd say get rid of strncpy altogether.
fist_half[l_length] = '\0';
while(l_length--)
first_half[l_length] = array[l_length];
The same method can be applied to the right side with some index modification.
This way you can get rid of overhead and HEADACES of strncpy.
If you use pointers the code can be even further simplified.
It is enough if you initialize the buffers with 0 as shown in split1(...)
char first_half[BUF] = {0}; // whole buffer is full of zeroes
char sec_half[BUF] = {0};
Then termination will be automatic.
The uninitialized buffer contains random characters.
If buffers are not zeroed the termination is needed as shown in split2(...)
The solutions are as close as possible to the original code. They work for even, odd and empty strings.
Please note the symmetry of the solutions with memcpy and strncpy.
#include <stdio.h>
#include <string.h>
#define BUF 255
void split1(char array[], int bUseMemcpy)
{
/* use zeroed buffers to automatically terminated the copied strings */
int length, length2;
char first_half[BUF] = {0};
char sec_half[BUF] = {0};
length = strlen( array );
length2 = length / 2;
length -= length2;
if(bUseMemcpy)
memcpy( first_half, array, length);
else
strncpy( first_half, array, length);
if(bUseMemcpy)
memcpy( sec_half, (array + length), length2);
else
strncpy( sec_half, (array + length), length2);
printf( "<%s>\n", first_half );
printf( "<%s>\n", sec_half );
}
void split2(char array[], int bUseMemcpy)
{
/* Do not initialize the buffers
Use 0 to terminate the buffers after the copy */
int length, length2;
char first_half[BUF];
char sec_half[BUF];
length = strlen(array);
length2 = length / 2;
length -= length2;
if(bUseMemcpy)
memcpy( first_half, array, length);
else
strncpy( first_half, array, length);
first_half[length]=0; /*zero termination needed, since buffers are not initialized to 0*/
if(bUseMemcpy)
memcpy( sec_half, (array + length), length2);
else
strncpy( sec_half, (array + length), length2);
sec_half[length2]=0; // zero termination
printf( "<%s>\n", first_half );
printf( "<%s>\n", sec_half );
}
int main(void) {
split1("123456789",0);
split1("",1);
split2("people",0);
split2("1",1);
return 0;
}
Output:
<12345>
<6789>
<>
<>
<peo>
<ple>
<1>
<>
There is a simple way to output the string split on 2 separate lines: use printf with the %.*s conversion format. It prints a initial portion of the string argument:
void split(const char *array) {
int half = strlen(array) / 2;
printf("%.*s\n%s\n", half, array, array + half);
}
I am doing a check whether 2 strings are permutations. I sort the strings then compare each character to each other. However, I think my sorting process also changes the original strings (I am very bad with pointers and passing by reference).
Is there a way to check without modifying the original strings?
I also tried using strcpy but I don't really know how to use it.
I tried this in my check() function:
char temp[128];
strcpy(temp, word);
Below is my code. I call the areAnagram function from another function like this:
void check(char *word, struct Entry *en) {
if (areAnagram(en->word, word) == 1) {
//printf("EW:%s W:%s\n", en->word, word);
//For example, this should return something like
// EW:silent W:listen
//But I got
// EW:eilnst W:eilnst
}
}
Structure for Entry:
typedef struct Entry {
char *word;
int len;
struct Entry *next;
} Entry;
Here is the anagram check process:
void quickSort(char *arr, int si, int ei);
int areAnagram(char *str1, char *str2)
{
// Get lenghts of both strings
int n1 = strlen(str1);
int n2 = strlen(str2);
// If lenght of both strings is not same, then they cannot be anagram
if (n1 != n2) {
return 0;
}
// Sort both strings
quickSort (str1, 0, n1 - 1);
quickSort (str2, 0, n2 - 1);
int i;
// Compare sorted strings
for (i = 0; i < n1; i++) {
if (str1[i] != str2[i]) {
return 0;
}
}
return 1;
}
void exchange(char *a, char *b)
{
char temp;
temp = *a;
*a = *b;
*b = temp;
}
int partition(char A[], int si, int ei)
{
char x = A[ei];
int i = (si - 1);
int j;
for (j = si; j <= ei - 1; j++) {
if(A[j] <= x) {
i++;
exchange(&A[i], &A[j]);
}
}
exchange (&A[i + 1], &A[ei]);
return (i + 1);
}
void quickSort(char A[], int si, int ei)
{
int pi; /* Partitioning index */
if(si < ei) {
pi = partition(A, si, ei);
quickSort(A, si, pi - 1);
quickSort(A, pi + 1, ei);
}
}
There is a better way of checking whether two strings are anagrams.You can create an array to store the count of each character in first string(increment the ASCII value index in the array). Then traverse second string and decrement the count of each character (ASCII value index in the array). Now check if all elements of array are zero,if yes these are anagrams otherwise not.
int arr[123];
suppose two strings are s1="abba" and s2="baba"
while traversing first string arr[97]=2,arr[98]=2;
while traversing second array arr[97]=0,arr[98]=0;
Now if you traverse the whole array then all elements will be zero.
But if two strings s1="abba" and s2="abac"
while traversing first string arr[97]=2,arr[98]=2;
while traversing second string arr[97]=0,arr[98]=1,arr[99]=-1;
Since all elements of array are not zero so these are not anagrams.
The complexity of above algorithm is O(n).
Hope it helps.
Make a copy using strcpy:
char *copy = malloc(strlen(word) + 1); // can use a temporary buffer, but this allows variable length inputs
strcpy(copy, word);
// use copy as your temporary string
free(copy);
Your title states that you do not want to modify the original string, however your solution uses Quicksort, which modifies the string. Plus, sorting -- even a fast optimized sort -- is an expensive operation and is not needed for the problem you are trying to solve. You could use a lookup table for speed and it would not modify the original string. You simply create a unique number for each letter and sum the values. Equal sums would constitute an anagram.
/* OPTION 1: let the compiler build your table */
static const int A=0x0000001;
static const int B=0x0000002;
static const int C=0x0000004;
/* continue to double for other letters until ... */
static const int Z=0x4000000;
/* OPTION 2: calculate a cheap hash for each letter */
/* Returns 0 for anagram similar to strcmp */
int anagram (const char* word1, const char* word2)
{
/* strings must be equal length */
if (strlen(word1) != strlen(word2))
return -1;
unsigned long sum1 = 0;
unsigned long sum2 = 0;
char c;
for (int i = 0 ; word1[i] != '\0' ; i++)
{
/* use toupper() function here if case insensitive */
c = toupper(word1[i]);
sum1 += 1 << (c - 'A');
}
for (int i = 0 ; word2[i] != '\0' ; i++)
{
/* use toupper() function here if case insensitive */
c = toupper(word2[i]);
sum2 += 1 << (c - 'A');
}
return (int)(sum1 - sum2); /* ignore overflow */
}
The anagram function above is untested and has been written for clarity. You'd need to include the ctype.h to convert the case using toupper().
Finally, you could make a copy of one of the strings, traverse the other string calling strchr() on each character to find the matching character in the copy. If strchr() returns NULL then there is no anagram, otherwise if strchr() returns a valid pointer, use it to modify the copy, e.g. set to char value to 0x01, so that you can sum the chars in the modified copy. In this instance, the strings would be anagrams if the sum of all the chars in the modified copy equal the integer length of the comparison string.
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.