replace by index - c

I want to replace the string by index. The string between x and y. If the string that will be replaced the length is lees than y, the pointer must be incremented by the difference. e.g,
given the string ([10 20]...[10 20]..[30 80]); x = 1(index of [) and y = 7(index of ]), and the string-replace is 50, it must be replaced to (50...[10 20]..[30 80]).
I've tried it:
void replaceindex(char *s, char *replace, unsigned int start, unsigned int end)
{
assert(start < end);
char *p = s, *q = s, *r = replace;
register unsigned int i = 0;
int found = 0;
while(*q) {
if(found == 0 && i == start) {
found = 1;
for(; *r; ++r, ++start, ++q)
*p ++ = *r;
while(++start < end)
q++;
}
*p ++ = *q ++;
i ++;
}
}
using:
char str[] = "([10 20]...[10 20]..[30 80])";
printf("Before: %s\n", str);
replaceindex(str, "50", 1, 7);
printf("After: %s\n", str);
The output is:
Before: ([10 20]...[10 20]..[30 80])
After: (500]...[10 20]..[30 80])0])
But I'm expecting this:
Before: ([10 20]...[10 20]..[30 80])
After: (50...[10 20]..[30 80])
How to fix this?

Building on the ideas from Anon ymous, but avoiding the creation of a new string:
void replaceindex(char *s, char *replace, unsigned int start, unsigned int end)
{
unsigned rl, sl;
rl = strlen(replace);
sl = strlen(s);
++end; /* change inclusive index to exclusive one */
assert(start <= end);
assert(rl <= end - start);
memcpy(s + start, replace, rl);
memmove(s + start + rl, s + end, sl - end + 1);
}

You need two fixes:
for(; *r; ++r, ++start, ++q)
*p ++ = *r;
- while(++start < end)
+ while(start++ <= end)
q++;
}
*p ++ = *q ++;
i ++;
}
+ *p = '\0';
}
The first is because your end index is inclusive (judging from the call), and you want to compare first and increment afterwards. The second is to terminate the new string.
Note that you're in serious trouble if strlen(replace) > end - start + 1.

#include <stdio.h>
#include <string.h>
char* replaceindex(char *s, char *replace, unsigned int start, unsigned int end)
{
char *rep= (char*)malloc(strlen(s)+1);
memset(rep,0,strlen(s)+1);
if(strlen(replace)<=(end-start))
{ memcpy(rep,s,start);
memcpy(rep+start,replace,strlen(replace));
memcpy(rep+start+strlen(replace),s+end,strlen(s+end));
return rep;
}
else{free(rep);}
return s;
}
int main() {
char* z="This answer is crazy";
printf("%s",replaceindex(z,"Code",5,11));
return 0;
}
And the Output is
This Code is crazy
EDIT:
Without Memory:-
#include <stdio.h>
#include <string.h>
void replaceindex(char *s, char *replace, unsigned int start, unsigned int end)
{
if(strlen(replace)<=(end-start))
{
char* iter= s+start+strlen(replace),*cursor=s+end;
memcpy(s+start,replace,strlen(replace));
while(*iter)
*iter++=*cursor++;
}
}
int main()
{
char z[]="This answer is crazy";
replaceindex(z,"Code",5,11);
return printf("%s",z);
}

Related

My invertString function doesn't seem to work properly

So, I have to solve the problem above. I have written some code in C, but the compiler doesn't give me any outputs. Here's the code below.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void invertString(char *s1, char **s2);
void invertString(char *s1, char **s2){
int len = strlen(s1);
*s2 = (char*)malloc((len+1) * sizeof(char));
int start = 0;
int end = 0;
int index = 0;
while (end < len){
while(s1[end]<s1[end+1] && end < len-1)
end++;
for (int i=end;i>=start;i--)
(*s2)[index]=s1[i];
index++;
start = end + 1;
while(s1[end]>=s1[end+1] && end < len-1){
(*s2)[index]=s1[end];
index++;
end++;
start = end;
}
}
(*s2)[index] = '\0';
}
int main() {
char s1[] = "A B C D D D D Z Y X W E F G";
char *s2 = NULL;
invertString(s1, &s2);
printf("Input string: %s\n", s1);
printf("Output string: %s\n", s2);
free(s2);
return 0;
}`
I was expecting the code to output the string such that the substrings in ascending order would be reversed to descending, while the rest of the string would remain the same. Instead, I receive no output. I think the function is stuck in a loop because when I try to re-run, it says the function is already running.
Turns out that because my input string had spaces between all letters, my traverser was completely useless. I had to either iterate +2 every time or delete all spaces in the input. This updated code works fine.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void invertString(char *s1, char **s2);
void invertString(char *s1, char **s2){
int len = strlen(s1);
*s2 = (char*)malloc((len) * sizeof(char));
int start = 0;
int end = 0;
int index = 0;
while (end < len){
printf("%d%d\n", end, len);
while(s1[end]<s1[end+1])
end++;
for (int i=end;i>=start;i--){
(*s2)[index]=s1[i];
index++;
}
end++;
start = end;
while(s1[end]>=s1[end+1]){
(*s2)[index]=s1[end];
index++;
end++;
start = end;
}
}
(*s2)[index] = '\0';
}
int main() {
char s1[] = "ABCDDDDZYXWEFG";
char *s2 = NULL;
invertString(s1, &s2);
printf("Input string: %s\n", s1);
printf("Output string: %s\n", s2);
free(s2);
return 0;
}
Code accesses outside array bounds.
Viewable with some tests using OP's corrected code.
Last error certainly due to insufficient allocation.
// *s2 = (char*)malloc((len) * sizeof(char));
*s2 = malloc((len + 1u) * sizeof(char));
Note: char may be negative.
Perhaps additional errors.
void invertString(char *s1, char **s2){
int len = strlen(s1);
*s2 = (char*)malloc((len) * sizeof(char));
int start = 0;
int end = 0;
int index = 0;
while (end < len){
printf("%d%d\n", end, len);
while(s1[end]<s1[end+1])
end++;
for (int i=end;i>=start;i--){
(*s2)[index]=s1[i];
index++;
}
end++;
start = end;
if (end + 1 > len) {
fprintf(stderr, "%d %d %d\n", __LINE__, end + 1, len);
//exit(-1);
}
while(s1[end]>=s1[end+1]){
(*s2)[index]=s1[end];
index++;
end++;
start = end;
}
}
if (index >= len) {
fprintf(stderr, "%d %d %d\n", __LINE__, index, len);
exit(-1);
}
(*s2)[index] = '\0';
}

C string manipulation for removing xx:xx:xx:xx:xx:xx

I have a problem removing a substring xx:xx:xx:xx:xx:xx from one main string. Here is the background info for the problem:
in a function void funA():
void funA(const char* sth){
if (sth == THINGA){
// do A;
}
else if (sth == THINGB){
// do B;
}
eles{
// do C;
}
log_status("current status: - %s", sth);
}
sth is a string contains a substring in the format of xx:xx:xx:xx:xx:xx where x is either a number or a letter. The substring has a space in front of it but might not have one at the end of the string. I need to obfuscate this substring with a *. Since only the substring has :, I made a helper function to locate the first : and the last : and remove 2 characters before it. Delete the last 2 characters and append a *. I think this way is most the best solution. So I'm wondering if there are any more efficient design of a helper function aka a helper function has shorter runtime and uses less memory. Since the substring xx:xx:xx:xx:xx:xx has a very distinguish format, the only easier way I can think of is to do a string match to find the substring and then replace it with a *. I'm open to other more innovative way though.
#ifndef PARSER_STACK_H_INCLUDED
#define PARSER_STACK_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PATTERN_LEN 18
typedef struct{
unsigned int start;
unsigned int finish;
}index;
void remove_str_pattern(char *original, char *extract, unsigned int start, unsigned int finish);
void splitter(char *x, index *index_SF);
unsigned int count_points(const char *x);
void obscure(char *str, index index_SF);
char* return_obscure_string(char *str);
char* return_pattern(char *str);
char* return_pattern(char *str){
index index_SF = {0,0};
char *str_export = calloc(PATTERN_LEN, sizeof(char));
char *tmp = calloc(sizeof(str)/sizeof(char), sizeof(char));
strcpy(tmp, str);
splitter(str, &index_SF);
obscure(tmp, index_SF);
remove_str_pattern(str, str_export, index_SF.start, index_SF.finish);
return str_export;
}
char* return_obscure_string(char *str){
index index_SF = {0,0};
char *str_export = calloc(PATTERN_LEN, sizeof(char));
char *tmp = calloc(sizeof(str)/sizeof(char), sizeof(char));
strcpy(tmp, str);
splitter(str, &index_SF);
obscure(tmp, index_SF);
remove_str_pattern(str, str_export, index_SF.start, index_SF.finish);
return tmp;
}
void obscure(char *str, index index_SF){
for(unsigned int i = index_SF.start; i < index_SF.finish+1; ++i){
if(str[i] != ':'){
str[i] = '*';
}
}
}
void splitter(char *x, index *index_SF){
for(unsigned int i = 0, tmp = 0; i < strlen(x); ++i){
if(x[i] == ':'){
++tmp;
if(tmp == 1){
index_SF->start = i-2;
}else{
if(tmp == 5){
index_SF->finish = i+2;
}
}
}
}
}
unsigned int count_points(const char *x){
int c = 1;
for(unsigned int i = 0; i < strlen(x); ++i){
if((x[i] == ':' && x[i+2] == ':') || (x[i] == ':' && x[i-2] == ':')){
++c;
}
}
return c;
}
void remove_str_pattern(char *original, char *extract, unsigned int start, unsigned int finish){
for(unsigned int i = start, j = 0; i < finish+1; ++i, ++j){
extract[j] = original[i];
}
}
#endif // PARSER_STACK_H_INCLUDED
That is my personal header file for your request, create header file with this code and try it ! :D
Two "main" functions of this file are.
1. char* return_obscure_string(char *str);
For return original string with obscured sub-string..
2. char* return_pattern(char *str);
For return pattern value from a string..
Good Luck Man !
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PATTERN_LEN 18
typedef struct{
unsigned int start;
unsigned int finish;
}index;
void remove_str_pattern(char *original, char *extract, unsigned int start, unsigned int finish);
void splitter(char *x, index *index_SF);
unsigned int count_points(const char *x);
void obscure(char *str, index index_SF);
void main(){
index index_SF = {0,0};
char *origin = "this is first try for me in stack aa:bb:22:44:55:66 overflow...";
char *str_export = calloc(PATTERN_LEN, sizeof(char));
char *tmp = calloc(sizeof(origin)/sizeof(char), sizeof(char));
strcpy(tmp, origin);
splitter(origin, &index_SF);
obscure(tmp, index_SF);
remove_str_pattern(origin, str_export, index_SF.start, index_SF.finish);
printf("start index: %u finish index: %u\n", index_SF.start, index_SF.finish);
printf("obscured string %s\n", tmp);
printf("original str: %s\n", origin);
printf("pattern: %s\n", str_export);
}
void obscure(char *str, index index_SF){
for(unsigned int i = index_SF.start; i < index_SF.finish+1; ++i){
if(str[i] != ':'){
str[i] = '*';
}
}
}
void splitter(char *x, index *index_SF){
for(unsigned int i = 0, tmp = 0; i < strlen(x); ++i){
if(x[i] == ':'){
++tmp;
if(tmp == 1){
index_SF->start = i-2;
}else{
if(tmp == 5){
index_SF->finish = i+2;
}
}
}
}
}
unsigned int count_points(const char *x){
int count = 1;
for(unsigned int i = 0; i < strlen(x); ++i){
if((x[i] == ':' && x[i+2] == ':') || (x[i] == ':' && x[i-2] == ':')){
++count;
}
}
return count;
}
void remove_str_pattern(char *original, char *extract, unsigned int start, unsigned int finish){
for(unsigned int i = start, j = 0; i < finish+1; ++i, ++j){
extract[j] = original[i];
}
}

Function that return characters from string which occurrences is user definied

I really hitted the wall with this type of function. I need to make a function that returns characters from string.
user can enter any number and I need to find char in string where total number of occurrences is number that user specified.
Does someone knows how can it be done in C language?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int cmp(const void *a, const void *b){
unsigned char ac = *(unsigned char *)a;
unsigned char bc = *(unsigned char *)b;
return ac < bc ? -1 : ac > bc;
}
char *func(const char *str, size_t n){
size_t len = strlen(str);
char *dup = malloc(len + 1);
char temp[len + 1];//[256]
strcpy(dup, str);
qsort(dup, len, sizeof(*dup), cmp);
char *p = dup;
size_t i = 0;
while(*p){
char aChar[] = {*p, 0};
len = strspn(p, aChar);
if(len == n){
temp[i++] = *p;
}
p += len;
}
temp[i] = 0;
strcpy(dup, temp);
return dup;
}
int main(void){
char *occurs = func("111abcddaaa", 1);
for(char *p = occurs; *p; ++p){
printf("%c\n", *p);
}
free(occurs);
return 0;
}

How to rotate the last 4 bytes of an array?

I have created two arrays that need to be concatenated after the second array (y in this case) has been rotated. However I want to rotate only the last 4 bytes of this array. This is my code:
char x[]={"hello"};
char y[]={"goodmorning"};
char combine[20];
strcpy(combine, x);
strcat(combine, y);
printf(combine);
Here before the concatenation into combine I want to do the rotation operation.
before rotation
combine= hellogoodmorning
after rotation
combine= gninhellogoodmor
I have tried to look for a logic to do this online but could not find anything specific. Can anybody please help.
void strRev(char *s)
{
char temp, *end = s + strlen(s) - 1;
while( end > s)
{
temp = *s;
*s = *end;
*end = temp;
--end;
++s;
}
}
char x[]={"hello"};
char y[]={"goodmorning"};
char combine[20];
strcpy(combine, x);
strcat(combine, y);
strRev(combine);
strRev(combine+4);
printf(combine);
I use
#define swap(a, b) { a ^= b; b ^= a; a ^= b; }
void reverse(char * s, int beg, int end) {
while (beg < end) {
swap(s[beg], s[end]);
++beg, --end;
}
}
void rotate(char * s, int k) {
if (!s || !*s) return;
int len = strlen(s);
k %= len;
reverse(s, 0, len - 1);
reverse(s, 0, k - 1);
reverse(s, k, len - 1);
}
and call rotate(combine, 4); to rotate 4 bytes in combine.
Try something like this shown below. I use strncpy instead of strcpy() and strcat(). Try to debug for better understanding. Run Live.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ROTATION_LEN 4
int main() {
char x[] = { "hello" };
char y[] = { "goodmorning" };
char c;
char combine[20] = {0}; // init with null
char * com = combine;
int i;
int leny = strlen(y);
int lenx = strlen(x);
for (i = 0; i < ROTATION_LEN; ++i) {
c = y[leny -1 - i];
combine[i] = c;
}
com += ROTATION_LEN; // forward address of combine by ROTATION_LEN
strncpy(com, x, lenx);
com += lenx; // forward address of combine by x length
strncpy(com, y, leny - ROTATION_LEN);
printf(combine);
return 0;
}
Output:
gninhellogoodmor
If you define a function like this:
void rotate_last_four(char *string)
{
char old_four[4];
char new_four[4];
strncpy(old_four, string + strlen(string) - 4, 4);
new_four[0] = old_four[3];
new_four[1] = old_four[2];
new_four[2] = old_four[1];
new_four[3] = old_four[0];
memmove(string + 4, string, strlen(string) - 4);
strncpy(string, new_four, 4);
}
Then you only need to add this line to your code before printing combine:
rotate_last_four(combine);
And the output is: gninhellogoodmor

Reverse a sentence in C?

I have just written a program which reverses a sentence whatever the user gives. For example: if the user enters "How are you", my program generates "uoy era woH".
The programme which I wrote is shown below. I just have a wild intution that there can be a smarter program than this. So valuable input from your side is most appreciated or any better program than this is also most welcome.
int ReverseString(char *);
main() {
char *Str;
printf("enter any string\n");
gets(Str);
ReverseString(Str);
getch();
}
int ReverseString(char *rev) {
int len = 0;
char p;
while(*rev!='\0') {
len++;
rev++;
}
rev--;
while(len>0) {
p = *rev;
putchar(p);
rev--;
len--;
}
}
Thanks a lot.
You could use recursion.
int ReverseString(char *rev) {
if(*rev!='\0') {
ReverseString(rev + 1);
putchar(*rev);
}
return 1;
}
void ReverseString( char* str, int len ) {
if( len > 1 ) {
swap( &str[0], &str[len - 1] );
ReverseString( ++str, len - 2 );
}
}
Or, unrolling the tail-recursion:
void ReverseString( char* str, int len ) {
while( len > 1 ) {
swap( &str[0], &str[len - 1] );
++str;
len -= 2;
}
}
Where swap is defined as:
void swap( char* a, char* b ) {
*a ^= *b;
*b ^= *a;
*a ^= *b;
}
If you use this though, your TA's will definitely know you didn't figure this out yourself :)
Okay, here is my function. I wrote it a while ago, just for practice.
char* reverse(char *string){
int length = 0;
int half = 0;
length = strlen(string);
half = (length/2) - 1;
--length;
int i = 0;
register char interim;
for(; i<=half; ++i){
interim = string[i];
string[i] = string[length - i];
string[length - i] = interim;
}
return string;
}
now that I look at it, I'm less proud of it than when I got it to work. I'm just posting it because you asked me to post it when I found it--and for completeness' sake.
After looking at some other answers I realize that the calculation of half the string is unnecessary and I could have just decremented length until i and length were equal. Oh well--here it is.
Also, please don't bash me for the use of the register keyword :P
Yet another variation...
void ReverseString( char *str, int len ) {
int i;
for(i=0; i < len/2; i++) {
swap( &str[i], &str[len -1 -i] );
}
}
void swap( char *a, char *b ) {
char tmp = *a;
*a = *b;
*b = tmp;
}
void revstr(TCHAR *str) {
if( *str == '\0' ) {
return;
}
TCHAR *start = str;
TCHAR *end = start + strlen(str) - 1;
while(start < end) {
*start ^= *end;
*end ^= *start;
*start ^= *end;
*start++;
*end-–;
/*
could also use *start ^= *end ^= *start++ ^= *end–-; if you want to get fancy
*/
}
}
Stolen from the 2005 version of myself, but screw that guy, he slept with my wife. Yes, I know I don't need some of the '*'s, but I wrote the one-liner first and just converted it, and the one-liner does require them.
The following program prints its arguments in reverse character order:
#include <string.h>
#include <stdio.h>
char * reverse(char * string) {
char * a = string;
char * b = string + strlen(string) - 1;
for(; a < b; ++a, --b)
*a ^= *b, *b ^= *a, *a ^= *b; // swap *a <-> *b
return string;
}
int main(int argc, char * argv[]) {
for(int i = 1; i < argc; ++i)
puts(reverse(argv[i]));
}
Nothing new here, but IMO more readable than most other answers.
If you don't know the length of the string:
void reverse_string(char* str) {
char* p2 = str;
while (*p2 != '\0') {
/* assumes the string is null-terminated, will fail otherwise */
++p2;
}
--p2;
char* p1 = str;
while (p1 < p2) {
char tmp = *p1;
*p1 = *p2;
*p2 = tmp;
++p1;
--p2;
}
}
If you do:
void reverse_string(char* str, const size_t len) {
if (len <= 1) {
return;
}
char* p2 = str + len - 1;
char* p1 = str;
while (p1 < p2) {
char tmp = *p1;
*p1 = *p2;
*p2 = tmp;
++p1;
--p2;
}
}
This won't work. Should allocate memory for your sentence.
char *Str;
printf("enter any string\n");
gets(Str);
should be:
char str[81]={0};
printf("Enter any string up to 80 characters\n");
scanf("%80s\n",str);
ReverseString(str)
Besides, you should avoid gets function. It leads to buffer overflows
#include<stdio.h>
void reverse(char s[])
{
int i=0,j,x=0,z;
printf("\nThe string is : ");
printf("%s",s);
printf("\nThe reverse string is : ");
while(s[i] != ' ')
{
while(s[i] != ' ')
i++;
z=i+1;
for(j=i-1;j>=x;j--)
printf("%c",s[j]);
printf(" ");
i=z;
x=z;
}
}
main()
{
char s[50];
int a;
for(a=0;a<50;a++)
s[a]=' ';
puts("\nEnter a sentence : ");
fgets(s,50,stdin);
reverse(s);
}

Resources