N permutations of string (with repetitions) - c

I have to print first n permutations with repetitions of a string.
String is formed with characters 'a','b','c','d','e','f'.
For example, first 10 permutations would be: aaaaaa,aaaaab,aaaaac,aaaaad,aaaaae,aaaaaf,aaaaba,aaaabb,aaaabc,aaaabd.
This is my failed attempt:
int main()
{
FILE *c;
c = fopen("C:\\Users\\Korisnik\\Desktop\\tekst\\permutacija.txt", "w");
char s[6] = "abcdef";
char t[6] = "aaaaaa";
s[6] = '\0';
t[6] = '\0';
int k = strlen(t);
int m = k;
int n;
scanf("%d", &n);
int br = 0;
int i = 0;
while (br < n) {
i = 0;
while (i < 6) {
t[k-1] = s[i];
fprintf(c, "%s ", t);
fprintf(c, "\n");
i++;
br++;
if (br == n) {
exit(1);
}
}
t[k-1] = 'a';
k--;
if (k < 0) {
k = m;
}
}
return 0;
}
And my output for first 10 permutations is:
aaaaa
aaaaab
aaaaac
aaaaad
aaaaae
aaaaaf
aaaa
aaaaba
aaaaca
aaaada
Any suggestions?

(Showing a different idea)If you look carefully you will see that all the permutations are the numbers in base-7. Consider a as 0, b as 1 and so on. So for every number 1..n you will convert it into base 7 and write it (By write it I mean, in place of 0 you put a,1 - b etc). That will give you the required result. (Ofcourse in conversion you will have to append 0 to the left of the number as per number of digits you want to show). There are problems in your code:
char s[6]="abcdef";
is legal in C.
s[6]=0;
This is not as you are accessing array index out of bound which is Undefined behavior. strlen(t) is undefined behavior as t is not NUL terminated.
Also you have fprintf(c,"%s ",t); in your code - this also leads to undefined behavior, it also expects a char* which points to a nul terminated char array. This will make your realize that how irrelevant it is to have something like this
char s[6]="abcdef";
Long story short, use char s[7]="abcdef"; (same applies to t also).

Related

C allocation memory error. Don't find something like this

Could you help please ?
When I execute this code I receive that:
AAAAABBBBBCCCCCBBBBBCOMP¬ıd┐╔ LENGTH 31
There are some weirds characters after letters, while I've allocate just 21 bytes.
#include <stdio.h>
#include <stdlib.h>
char * lineDown(){
unsigned short state[4] = {0,1,2,1};
char decorationUp[3][5] = {
{"AAAAA"},{"BBBBB"},{"CCCCC"}
};
char * deco = malloc(21);
int k;
int p = 0;
for(int j = 0; j < 4; j++){
k = state[j];
for(int i = 0; i < 5; i++){
*(deco+p) = decorationUp[k][i];
p++;
}
}
return deco;
}
int main(void){
char * lineDOWN = lineDown();
int k = 0;
char c;
do{
c = *(lineDOWN+k);
printf("%c",*(lineDOWN+k));
k++;
}while(c != '\0');
printf("LENGTH %d\n\n",k);
}
The function does not build a string because the result array does not contain the terminating zero though a space for it was reserved when the array was allocated.
char * deco = malloc(21);
So you need to append the array with the terminating zero before exiting the function
//...
*(deco + p ) = '\0';
return deco;
}
Otherwise this do-while loop
do{
c = *(lineDOWN+k);
printf("%c",*(lineDOWN+k));
k++;
}while(c != '\0')
will have undefined behavior.
But even if you will append the array with the terminating zero the loop will count the length of the stored string incorrectly because it will increase the variable k even when the current character is the terminating zero.
Instead you should use a while loop. In this case the declaration of the variable c will be redundant. The loop can look like
while ( *( lineDOWN + k ) )
{
printf("%c",*(lineDOWN+k));
k++;
}
In this case this call
printf("\nLENGTH %d\n\n",k);
^^
will output the correct length of the string equal to 20.
And you should free the allocated memory before exiting the program
free( lineDOWN );
As some other wrote here in their answers that the array decorationUp must be declared like
char decorationUp[3][6] = {
{"AAAAA"},{"BBBBB"},{"CCCCC"}
};
then it is not necessary if you are not going to use elements of the array as strings and you are not using them as strings in your program.
Take into account that your program is full of magic numbers. Such a program is usually error-prone. Instead you should use named constants.
In
char decorationUp[3][5] = {
{"AAAAA"},{"BBBBB"},{"CCCCC"}
};
your string needs 6 characters to also place the null char, even in that case you do not use them as 'standard' string but only array of char. To get into the habit always reverse the place for the ending null character
you can do
char decorationUp[3][6] = {
{"AAAAA"},{"BBBBB"},{"CCCCC"}
};
Note it is useless to give the first size, the compiler counts for you
Because in main you stop when you read the null character you also need to place it in deco at the end, so you need to allocate 21 for it. As before you missed the place for the null character, but here that produces an undefined behavior because you read after the allocated block.
To do *(deco+p) is not readable, do deco[p]
So for instance :
char * lineDown(){
unsigned short state[] = {0,1,2,1};
char decorationUp[][6] = {
{"AAAAA"},{"BBBBB"},{"CCCCC"}
};
char * deco = malloc(4*5 + 1); /* a formula to explain why 21 is better than 21 directly */
int k;
int p = 0;
for(int j = 0; j < 4; j++){
k = state[j];
for(int i = 0; i < 5; i++){
deco[p] = decorationUp[k][i];
p++;
}
}
deco[p] = 0;
return deco;
}

How to get the length of this array without strlen(), sizeof(arr) / sizeof(arr[0]); does not work, C language

This program, tokenizes a user input string, removes extra spaces and saves each word into a 2D array and then print the tokens
EXAMPLE:
input: " Hello world string house and car"
output and EXPECTED output:
token[0]: Hello
token[1]: world
token[2]: string
token[3]: house
token[4]: and
token[5]: car
THE PROBLEM:
the problem is that I achieved this by using strlen() function when printing the tokens(code located at the very bottom), I am not supposed to use any other library than stdio.h and stdlib.h, since strlen() function is defined in string.h i tried to use sizeof(arr) / sizeof(arr[0]); but it does not work as I want, the result using sizeof is :
token[0]: Hello
token[1]: world
token[2]: string
token[3]: house
token[4]: and
token[5]: car
�oken[6]: ��
token[7]: �
token[8]: ����
token[9]: �
token[10]:
I WOULD LIKE TO HAVE THE EXPECTED OUTPUT WITHOUT USING STRLEN()
#include<stdio.h>
#include <stdlib.h>
#define TRUE 1
char tokenize(char *str, char array[10][20])
{
int n = 0, i, j = 0;
for(i = 0; TRUE; i++)//infinite loop until is the end of the string '\0'
{
if(str[i] != ' '){
//position 1, char 1
array[n][j++] = str[i];// if, it is not space, we save the character
}
else{
array[n][j++] = '\0';//end of the first word
n++;// position for next new word
j=0;// start writting char at position 0
}
if(str[i] == '\0')
break;
}
return 0;
}
//removes extra spaces
char* find_word_start(char* str){
/*also removes all extra spaces*/
char *result = (char*) malloc(sizeof(char) *1000);
int c = 0, d = 0;
// no space at beginning
while(str[c] ==' ') {
c++;
}
while(str[c] != '\0'){ // till end of sentence
result[d++] = str[c++]; //take non-space characters
if(str[c]==' ') { // take one space between words
result[d++] = str[c++];
}
while(str[c]==' ') { //
c++;
}
}
result[d-1] = '\0';
//print or return char?
return result;
free(result);
}
int main()
{
char str[]=" Hello world string dudes and dudas ";
//words, and chars in each word
char arr[10][20];
//call the method to tokenize the string
tokenize(find_word_start(str),arr);
int row = sizeof(arr) / sizeof(arr[0]);
/*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*/
for(int i = 0;i <= strlen(arr);i++)
/*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*/
printf("token[%d]: %s\n", i, arr[i]);
return 0;
}
Your code using strlen() may appear the work in this instance but it is not correct.
strlen(arr) makes no semantic sense because arr is not a string. It happens in this case to return 5 because arr has the same address as arr[0], then you kludged it to work for the 6 word output by using the test i <= strlen(arr) in the for loop. The two values strlen(arr) and the number of strings stored in arr are not related.
The expression sizeof(arr) / sizeof(arr[0]) determines the run-time constant number arrays within the array of arrays arr (i.e. 10), not the number of valid strings assigned. It is your code's responsibility to keep track of that either with a sentinel value such as an empty string, or by maintaining a count of strings assigned.
I suggest you change tokenize to return the number of strings (currently it is inexplicably defined to return a char, but in fact only ever rather uselessly returns zero):
int tokenize( char* str, char array[][20] )
{
...
return n ;
}
Then:
int rows = tokenize( find_word_start(str), arr ) ;
for( int i = 0; i < rows; i++ )
{
printf( "token[%d]: %s\n", i, arr[i] ) ;
}

How to avoid segmentation fault in recursive function with strings in C?

Note: I am not trying to get the algorithmic implementation! I already have it figured out in Java. I just can't seem to get my logic to work in C. Below is the Java code (which works) followed by the C99 code that breaks.
The high-level coding challenge that is presenting the segfault in my implementation is:
How to find all combinations of k length and smaller using alphabet of length n with repeating elements in C?
Problem
Code compiles, but I get a segmentation fault at runtime.
Notes / Observations
This is from a self-paced edX course I'm working my way through. I've already done the "less comfortable" challenges, and frankly they were a bit too easy. I'm now trying to go above the requirements and do this "more comfortable" (read more challenging) challenge. It is one of the more advanced beginner challenges.
I'm not a beginner programmer, but pretty much a novice with C.
As far as I understand it, the <cs50.h>is a custom header file that implements some things that simplify (read abstract away) command-line input and handling of strings. Documentation in it can be found at the cs50.net site and on the cs50lib GitHub page
I can't figure out the correct way to pass the values to the recursive function and need to utilize address referencing/dereferencing. Unfortunately my C is a bit fuzzy compared to other langs.
Test Calls with Desired Output Result
~/myTerminal $ ./printall ab 3
aaa
aab
aba
abb
baa
bab
bba
bbb
aa
ab
ba
bb
a
b
~/myTerminal $ ./printall abc 2
aa
ab
ac
ba
bb
bc
ca
cb
cc
a
b
c
myTerminal $ ./printall abcd 1
a
b
c
d
Java Code that Works
public class Main {
public static void main(String[] args) {
System.out.println("First Test");
char[] set1 = {'a', 'b'};
int k = 3;
printCombinations(set1, k);
System.out.println("\nSecond Test");
char[] set2 = {'a', 'b', 'c'};
k = 2;
printCombinations(set2, k);
System.out.println("\nThird Test");
char[] set3 = {'a', 'b', 'c', 'd'};
k = 1;
printCombinations(set3, k);
}
// Print all possible strings of length k or smaller.
static void printCombinations(char[] set, int k) {
int n = set.length;
for(int i = k; i > 0; i--)
{
printCombinationsRec(set, "", n, i);
}
}
// Print all combinations of length k
static void printCombinationsRec(char[] set, String prefix, int n, int k)
{
if (k == 0)
{ // Base case
System.out.println(prefix);
return;
}
// One by one add all characters
// from set and recursively
// call for k equals to k-1
for (int i = 0; i < n; ++i)
{
String newPrefix = prefix + set[i];
printCombinationsRec(set, newPrefix, n, k - 1);
}
}
}
C Code Causing Segmentation Fault
// CS50 custom header file
#include <cs50.h>
// "Regular" headers
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void printCombinations();
void printCombinationsRecur();
int main(int argc, string argv[])
{
if (argc == 3) // Correct number of arguments
{
string strSet = argv[1];
int maxLength = atoi(argv[2]);
printCombinations(strSet, maxLength);
return 0;
}
// Incorrect usage
printf("Usage: %s <charset>:string\n <maxLength>:int\n", argv[0]);
return 1;
}
// Functions below were adapted and modified from code at :
// https://www.geeksforgeeks.org/print-all-combinations-of-given-length/
// Accessed : 2018-07-13
void printCombinations(string sSet, int strLength)
{
int aLength = strlen(sSet);
for (int i = strLength; i > 0; i--)
{
printCombinationsRecur(sSet, "", aLength, strLength);
}
}
void printCombinationsRecur(string *sSet, string prefix, int aLength, int strLength )
{
// printf("sSet: %s\nprefix: %s\naLength: %i\nstrLength: %i\n", *sSet, prefix, aLength, strLength);
// In terms of the traditional equation k=> strLength, n=>aLength, S=>sSet
if (strLength == 0)
{
printf("%s\n", prefix);
}
for (int i = 0; i < aLength; i++)
{
string temp1 = "";
strcat(temp1, prefix); // <== SEGFAULT HAPPENING HERE!
string newPrefix = strcat(temp1, sSet[i]);
printCombinationsRecur(sSet, newPrefix, aLength, strLength - 1);
}
}
I made the following change (suggested by #Stargateur) to the recursive function, but still get a segfault!
void printCombinationsRecur(string *sSet, string prefix, int aLength, int strLength )
{
// printf("sSet: %s\nprefix: %s\naLength: %i\nstrLength: %i\n", *sSet, prefix, aLength, strLength);
// In terms of the traditional equation k=> strLength, n=>aLength, S=>sSet
if (strLength == 0)
{
printf("%s\n", prefix);
}
for (int i = 0; i < aLength; i++)
{
printf("This prints");
char *temp1 = malloc((strLength +2) * sizeof(char));
for (int j = 0; j < strLength + 2; j++){
if(j < strLength)
{
temp1[j] = prefix[j];
}
if(j == strLength)
{
temp1[j] = *sSet[i];
}
if(j == strLength + 1){
temp1[j] = '\0';
}
}
printCombinationsRecur(sSet, temp1, aLength, strLength - 1);
free(temp1);
}
}
One of the key differences between your Java code that works and the C code that doesn't is in the printCombinations() function.
Working Java:
for(int i = k; i > 0; i--)
{
printCombinationsRec(set, "", n, i);
}
Broken C:
int aLength = strlen(sSet);
for (int i = strLength; i > 0; i--)
{
printCombinationsRecur(sSet, "", aLength, strLength);
}
You're calling the recursive function with the same length, over and over and over again. To match the Java, the strLength argument should be i instead.
You also do not handle the base case properly. The Java code returns after printing if k == 0; the C code doesn't.
Working Java:
if (k == 0)
{ // Base case
System.out.println(prefix);
return;
}
Broken C:
if (strLength == 0)
{
printf("%s\n", prefix);
}
And then you handle the string concatenation incorrectly. C is not very forgiving. There are at least two ways to handle it. The method that will work with any version of C uses malloc(). The method that will work with C99, or with C11 as long as the compiler does not define __STDC_NO_VLA__, uses a VLA. The version using malloc() also calls free() and so it does a bit more work than the other.
Since the length allocated is always the same, you could offset the cost by calling malloc() once before the loop and free() once after the loop, and you'd only need to copy the prefix once and then simply set the extra characters (even the null could be set once). You could also enhance the VLA code to define the new prefix array once outside the loop, copy the prefix once, set the null byte once, and just set the extra character inside the loop.
You should also use formal prototype declarations for the functions, not mere function declarations that care not one whit about the arguments presented.
The code shown below is lazy and does not check that the malloc() calls work. It also does not validate that the alphabet is a sensible length, nor that the maximum length is reasonable, nor that the elements in the alphabet are unique.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void printCombinations(const char *set, int strLength);
static void printCombinationsRec(const char *set, const char *prefix, int aLength, int strLength);
int main(int argc, char *argv[])
{
if (argc != 3)
{
fprintf(stderr, "Usage: %s alphabet maxlen\n", argv[0]);
return 1;
}
/* GIGO: garbage in, garbage out */
char *strSet = argv[1];
int maxLength = atoi(argv[2]);
printCombinations(strSet, maxLength);
return 0;
}
static void printCombinations(const char *set, int k)
{
int n = strlen(set);
for (int i = k; i > 0; i--)
{
printCombinationsRec(set, "", n, i);
}
}
#if defined(USE_VLA) && __STDC_NO_VLA__ != 1
static void printCombinationsRec(const char *set, const char *prefix, int n, int k)
{
if (k == 0)
{
printf("%s\n", prefix);
return;
}
for (int i = 0; i < n; ++i)
{
size_t len = strlen(prefix);
char newPrefix[len + 2];
strcpy(newPrefix, prefix);
newPrefix[len + 0] = set[i];
newPrefix[len + 1] = '\0';
printCombinationsRec(set, newPrefix, n, k - 1);
}
}
#else
static void printCombinationsRec(const char *set, const char *prefix, int n, int k)
{
if (k == 0)
{
printf("%s\n", prefix);
return;
}
for (int i = 0; i < n; ++i)
{
size_t len = strlen(prefix);
char *newPrefix = malloc(len + 2);
strcpy(newPrefix, prefix);
newPrefix[len + 0] = set[i];
newPrefix[len + 1] = '\0';
printCombinationsRec(set, newPrefix, n, k - 1);
free(newPrefix);
}
}
#endif /* USE_VLA */
Compiled with -DUSE_VLA with a compiler that supports VLAs, it will not use malloc(). Compiled without the option, or with a compiler that supports C11 but does not support VLAs, then it uses malloc() and free().
At one point, I also added argument validation code in main(), but the 20 lines or so seemed to be more getting in the way than useful, so I left the GIGO comment there instead.
If this was 'production code', I'd be using error reporting functions and would not skip the checks (in part because the error reporting functions make it easier, using a single line per reported error instead of 5 or so without. I'd be using the error reporting code available in my SOQ (Stack Overflow Questions) repository on GitHub as files stderr.c and stderr.h in the src/libsoq sub-directory.
Note that you can't use strcat() easily because you want to append a single character, not a string. Hence the use of the two assignments. The + 0 emphasizes the similarity between the two assignments; the compiler does not generate any code for + 0.
When run (I called it comb47.c, compiled to comb47), it produces the output desired:
$ comb47 ab 3
aaa
aab
aba
abb
baa
bab
bba
bbb
aa
ab
ba
bb
a
b
$ comb47 abc 2
aa
ab
ac
ba
bb
bc
ca
cb
cc
a
b
c
$ comb47 abcd 1
a
b
c
d
$

realloc() seems to affect already allocated memory

I am experiencing an issue where the invocation of realloc seems to modify the contents of another string, keyfile.
It's supposed to run through a null-terminated char* (keyfile), which contains just above 500 characters. The problem, however, is that the reallocation I perform in the while-loop seems to modify the contents of the keyfile.
I tried removing the dynamic reallocation with realloc and instead initialize the pointers in the for-loop with a size of 200*sizeof(int) instead. The problem remains, the keyfile string is modified during the (re)allocation of memory, and I have no idea why. I have confirmed this by printing the keyfile-string before and after both the malloc and realloc statements.
Note: The keyfile only contains the characters a-z, no digits, spaces, linebreaks or uppercase. Only a text of 26, lowercase letters.
int **getCharMap(const char *keyfile) {
char *alphabet = "abcdefghijklmnopqrstuvwxyz";
int **charmap = malloc(26*sizeof(int));
for (int i = 0; i < 26; i++) {
charmap[(int) alphabet[i]] = malloc(sizeof(int));
charmap[(int) alphabet[i]][0] = 0; // place a counter at index 0
}
int letter;
int count = 0;
unsigned char c = keyfile[count];
while (c != '\0') {
int arr_count = charmap[c][0];
arr_count++;
charmap[c] = realloc(charmap[c], (arr_count+1)*sizeof(int));
charmap[c][0] = arr_count;
charmap[c][arr_count] = count;
c = keyfile[++count];
}
// Just inspecting the results for debugging
printf("\nCHARMAP\n");
for (int i = 0; i < 26; i++) {
letter = (int) alphabet[i];
printf("%c: ", (char) letter);
int count = charmap[letter][0];
printf("%d", charmap[letter][0]);
if (count > 0) {
for (int j = 1; j < count+1; j++) {
printf(",%d", charmap[letter][j]);
}
}
printf("\n");
}
exit(0);
return charmap;
}
charmap[(int) alphabet[i]] = malloc(sizeof(int));
charmap[(int) alphabet[i]][0] = 0; // place a counter at index 0
You are writing beyond the end of your charmap array. So, you are invoking undefined behaviour and it's not surprising that you are seeing weird effects.
You are using the character codes as an index into the array, but they do not start at 0! They start at whatever the ASCII code for a is.
You should use alphabet[i] - 'a' as your array index.
The following piece of code is a source of troubles:
int **charmap = malloc(26*sizeof(int));
for (int i = 0; i < 26; i++)
charmap[...] = ...;
If sizeof(int) < sizeof(int*), then it will be performing illegal memory access operations.
For example, on 64-bit platforms, the case is usually sizeof(int) == 4 < 8 == sizeof(int*).
Under that scenario, by writing into charmap[13...25], you will be accessing unallocated memory.
Change this:
int **charmap = malloc(26*sizeof(int));
To this:
int **charmap = malloc(26*sizeof(int*));

remove a specified number of characters from a string in C

I can't write a workable code for a function that deletes N characters from the string S, starting from position P. How you guys would you write such a function?
void remove_substring(char *s, int p, int n) {
int i;
if(n == 0) {
printf("%s", s);
}
for (i = 0; i < p - 1; i++) {
printf("%c", s[i]);
}
for (i = strlen(s) - n; i < strlen(s); i++) {
printf("%c", s[i]);
}
}
Example:
s: "abcdefghi"
p: 4
n: 3
output:
abcghi
But for a case like n = 0 and p = 1 it's not working!
Thanks a lot!
A few people have shown you how to do this, but most of their solutions are highly condensed, use standard library functions or simply don't explain what's going on. Here's a version that includes not only some very basic error checking but some explanation of what's happening:
void remove_substr(char *s, size_t p, size_t n)
{
// p is 1-indexed for some reason... adjust it.
p--;
// ensure that we're not being asked to access
// memory past the current end of the string.
// Note that if p is already past the end of
// string then p + n will, necessarily, also be
// past the end of the string so this one check
// is sufficient.
if(p + n >= strlen(s))
return;
// Offset n to account for the data we will be
// skipping.
n += p;
// We copy one character at a time until we
// find the end-of-string character
while(s[n] != 0)
s[p++] = s[n++];
// And make sure our string is properly terminated.
s[p] = 0;
}
One caveat to watch out for: please don't call this function like this:
remove_substr("abcdefghi", 4, 3);
Or like this:
char *s = "abcdefghi";
remove_substr(s, 4, 3);
Doing so will result in undefined behavior, as string literals are read-only and modifying them is not allowed by the standard.
Strictly speaking, you didn't implement a removal of a substring: your code prints the original string with a range of characters removed.
Another thing to note is that according to your example, the index p is one-based, not zero-based like it is in C. Otherwise the output for "abcdefghi", 4, 3 would have been "abcdhi", not "abcghi".
With this in mind, let's make some changes. First, your math is a little off: the last loop should look like this:
for (i = p+n-1; i < strlen(s); i++) {
printf("%c", s[i]);
}
Demo on ideone.
If you would like to use C's zero-based indexing scheme, change your loops as follows:
for (i = 0; i < p; i++) {
printf("%c", s[i]);
}
for (i = p+n; i < strlen(s); i++) {
printf("%c", s[i]);
}
In addition, you should return from the if at the top, or add an else:
if(n == 0) {
printf("%s", s);
return;
}
or
if(n == 0) {
printf("%s", s);
} else {
// The rest of your code here
...
}
or remove the if altogether: it's only an optimization, your code is going to work fine without it, too.
Currently, you code would print the original string twice when n is 0.
If you would like to make your code remove the substring and return a result, you need to allocate the result, and replace printing with copying, like this:
char *remove_substring(char *s, int p, int n) {
// You need to do some checking before calling malloc
if (n == 0) return s;
size_t len = strlen(s);
if (n < 0 || p < 0 || p+n > len) return NULL;
size_t rlen = len-n+1;
char *res = malloc(rlen);
if (res == NULL) return NULL;
char *pt = res;
// Now let's use the two familiar loops,
// except printf("%c"...) will be replaced with *p++ = ...
for (int i = 0; i < p; i++) {
*pt++ = s[i];
}
for (int i = p+n; i < strlen(s); i++) {
*pt++ = s[i];
}
*pt='\0';
return res;
}
Note that this new version of your code returns dynamically allocated memory, which needs to be freed after use.
Here is a demo of this modified version on ideone.
Try copying the first part of the string, then the second
char result[10];
const char input[] = "abcdefg";
int n = 3;
int p = 4;
strncpy(result, input, p);
strncpy(result+p, input+p+n, length(input)-p-n);
printf("%s", result);
If you are looking to do this without the use of functions like strcpy or strncpy (which I see you said in a comment) then use a similar approach to how strcpy (or at least one possible variant) works under the hood:
void strnewcpy(char *dest, char *origin, int n, int p) {
while(p-- && *dest++ = *origin++)
;
origin += n;
while(*dest++ = *origin++)
;
}
metacode:
allocate a buffer for the destination
decalre a pointer s to your source string
advance the pointer "p-1" positions in your source string and copy them on the fly to destination
advance "n" positions
copy rest to destination
What did you try? Doesn't strcpy(s+p, s+p+n) work?
Edit: Fixed to not rely on undefined behaviour in strcpy:
void remove_substring(char *s, int p, int n)
{
p--; // 1 indexed - why?
memmove(s+p, s+p+n, strlen(s) - n);
}
If your heart's really set on it, you can also replace the memmove call with a loop:
char *dst = s + p;
char *src = s + p + n;
for (int i = 0; i < strlen(s) - n; i++)
*dst++ = *src++;
And if you do that, you can strip out the strlen call, too:
while ((*dst++ = *src++) != '\0);
But I'm not sure I recommend compressing it that much.

Resources