c-make String in Reverse with helper swap function use only pointers - c

I need write the following function: char * Rev(char * str, int size);
The function get *pointer to string. It should replace the order of words within str, and return the result in the pointer. Only need reverse order for the words. Must use the helper swap function. In this function, there is no use of [] anywhere, ONLY USE pointers. Printing via main only.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *str1,*str2,*pRev;
char *pstr="YPEFMI ICMKMS JGLYZJ";
swap(&str1, &str2);
getchar();
*pRev =*RevWords (pstr,SIZE)
return 0;
}
methods.c
void swap(char* str1, char* str2);
char * Rev(char * string, int size);
//The function replaces the contents of both strings 1s and 2s.
void swap(char* str1, char* str2)
{
// if both of them are zero characters then stop
if (*str1 == '\0' && *str2 == '\0')
return;
// else swap the contents of the pointers
else
{
char tmp = *str1;
*str1 = *str2;
*str2 = tmp;
// advance both pointer and swap them too if thye are not '\0'
swap(++str1, ++str2);
}
}
char * Rev(char * string, int size)
{ //no idea-->NOT work in reverse.
char string[SIZE * (SIZE + 1)]
char *str = (char *)(malloc (SIZE * SIZE + SIZE-1));
for (int i = 0; i < SIZE; i++) {
memcpy(string + i * SIZE, matrix + i, SIZE);
if (i < SIZE - 1) {
swap(*(string + i * SIZE + SIZE));
} else {
swap(*(string + i * SIZE + SIZE)) = 0;
}
}
return string;
}
The swap method work but REV method NOT work.
For example:
pStr = YPEFMI ICMKMS JGLYZJ
pRev = -->JGLYZJ ICMKMS YPEFMI <--

Related

Is there an easy way to remove specific chars from a char*?

char * deleteChars = "\"\'.“”‘’?:;-,—*($%)! \t\n\x0A\r"
I have this and i'm trying to remove any of these from a given char*. I'm not sure how I would go about comparing a char* to it.
For example if the char* is equal to "hello," how would I go about removing that comma with my deleteChars?
So far I have
void removeChar(char*p, char*delim){
char*holder = p;
while(*p){
if(!(*p==*delim++)){
*holder++=*p;
p++;
}
}
*holder = '\0';
A simple one-by-one approach:
You can use strchr to decide if the character is present in the deletion set. You then assign back into the buffer at the next unassigned position, only if not a filtered character.
It might be easier to understand this using two indices, instead of using pointer arithmetic.
#include <stdio.h>
#include <string.h>
void remove_characters(char *from, const char *set)
{
size_t i = 0, j = 0;
while (from[i]) {
if (!strchr(set, from[i]))
from[j++] = from[i];
i++;
}
from[j] = 0;
}
int main(void) {
const char *del = "\"\'.“”‘’?:;-,—*($%)! \t\n\x0A\r";
char buf[] = "hello, world!";
remove_characters(buf, del);
puts(buf);
}
stdout:
hello world
If you've several delimiters/characters to ignore, it's better to use a look-up table.
void remove_chars (char* str, const char* delims)
{
if (!str || !delims) return;
char* ans = str;
int dlt[256] = {0};
while (*delims)
dlt[(unsigned char)*delims++] = 1;
while (*str) {
if (dlt[(unsigned char)*str])
++str; // skip it
else //if (str != ans)
*ans++ = *str++;
}
*ans = '\0';
}
You could do a double loop, but depending on what you want to treat, it might not be ideal. And since you are FOR SURE shrinking the string you don't need to malloc (provided it was already malloced). I'd initialize a table like this.
#include <string.h>
...
char del[256];
memset(del, 0, 256 * sizeof(char));
for (int i = 0; deleteChars[i]; i++) del[deleteChars[i]] = 1;
Then in a function:
void delChars(char *del, char *string) {
int i, offset;
for (i = 0, offset = 0; string[i]; i++) {
string[i - offset] = string[i];
if (del[string[i]]) offset++;
}
string[i - offset] = 0;
}
This will not work on string literals (that you initialize with char* x = "") though because you'd end up writing in program memory, and probably segfault. I'm sure you can tweak it if that's your need. (Just do something like char *newString = malloc(strlen(string) + 1); newString[i - offset] = string[i])
Apply strchr(delim, p[i]) to each element in p[].
Let us take advantage that strchr(delim, 0) always returns a non-NULL pointer to eliminate the the null character test for every interrelation.
void removeChar(char *p, char *delim) {
size_t out = 0;
for (size_t in; /* empty */; in++) {
// p[in] in the delim set?
if (strchr(delim, p[in])) {
if (p[in] == '\0') {
break;
}
} else {
p[out++] = p[in];
}
}
p[out] = '\0';
}
Variation on #Oka good answer.
it is better way - return the string without needless characters
#include <string.h>
char * remove_chars(char * str, const char * delim) {
for ( char * p = strpbrk(str, delim); p; p = strpbrk(p, delim) )
memmove(p, p + 1, strlen(p));
return str;
}

Converting a comma separated string to array

I have been trying to convert a string in array of integers, floats and characters. While I could get it work for integers and floats, there is some problem for characters.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *s1;
int k, no=5;
char* variable = "R1,R2,R3,R4,R5";
void* value;
s1 = calloc(no,sizeof(char)*81);
for (k=0; k<no; k++) s1[k] = strdup(mchar);
ListChar(variable, s1, no, ",");
memcpy(value, s1, no*sizeof(char)*81);
free(s1);
int i;
for (i = 0; i < no; i++)
printf("%s", value[i]);
printf("\n");
return 0;
}
In the header file I have
#define mchar "A...(81times)"
Implementation:
int ListChar(char *buf, char *list, int maxloop, char* delim)
{
int n = 0;
char *s,*t;
s= strdup(buf);
t= strtok(s,delim);
while ( t && (n<maxloop))
{
if (list!=NULL) list[n] =strdup(t);
n++;
t=strtok(NULL,delim);
}
free(s);
return(n);
}
During the calloc memory assignment when I watch s1 its 0xsomeadress ""
After the for loop s1 becomes 0xsomeadress "Garbage value 81 times"
When s1 is assigned to list its still reads the same garbage value.
And when list [n] = strdup(t) list[0] reads the first block of garbage value like -21 '\221 ṗ'.
t is getting delimited correctly. I even tried initializing char *s1[81] = {"something"} and looping it on j but it wont work, same problem, and I need to free s1 at the end because this function runs for number of times. I did it for integers and floats by list[n]=atoi(t) it works fine. Can anyone suggest me something?
There seems to be a fundamental misunderstanding about how strings work. Your s1 clearly needs to be a char ** and the usage of strdup is incorrect. If s1 is of type char *, then s1[k] is of type char. But strdup returns a char *, so s1[k] = strdup ... is clearly an error which your compiler ought to warn you about. Perhaps you want something like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void * xmalloc(size_t s);
void
ListChar(const char *buf, char **list, int maxloop, int delim)
{
char set[] = {delim, 0};
for( int n = 0; n < maxloop; n += 1 ){
size_t len = strcspn(buf, set);
list[n] = xmalloc(len + 1);
memcpy(list[n], buf, len);
buf += len + 1;
}
}
int
main(int argc, char **argv)
{
int delim = ',';
(void)argc; /* Suppress compiler warning */
while( *++argv ){
char **s1;
int k, num = 1;
char *input = *argv;
for( const char *p = input; *p; p += 1 ){
if( *p == delim ){
num += 1;
}
}
s1 = xmalloc(num * sizeof *s1);
ListChar(input, s1, num, delim);
for( int i = 0; i < num; i += 1 ){
printf("%s\n", s1[i]);
}
free(s1);
}
return 0;
}
void *
xmalloc(size_t s)
{
void *rv = malloc(s);
if( rv == NULL ){
perror("malloc");
exit(EXIT_FAILURE);
}
return rv;
}
Note that the above code scans each string twice, which is not ideal. Rather than scanning the string to find the number of delimiters and then parsing the string, it would be better to do both in one pass. But for the purposes of demonstrating how to break up the string, that seems like unnecessary complexity. (Though it's actually simpler, IMO)

How to copy char array in C without inner function

This is my code
char function(char *dst)
{
int i;
char *arr;
i = 0;
while(dst[i] != '\0')
{
arr[i] = dst[i];
i++;
}
dst[i] != '\0'
return(arr);
}
int main(void)
{
char a[] ="asdf"
printf("%s", function(a);
}
I want to copy *dst to empty *arr but my code didn't work.
I can't understand.
How can I copy array without inner function in C(ex_strcpy, memspy....)
Thank you
Apart from missing ; and making sure that the string being passed to the function is always a '\0' terminated one ( else the program will run into side effects strcpy causes ). and returning char* instead of char, you missed allocating memory for arr
// return char * instead of char
char* function(char *dst)
{
// Note - sizeof(dst) wont work
// Neither does sizeof(dst)/sizeof(char)
// allocate one extra for '\0'
size_t size_to_alloc = (strlen(dst) + 1) * (sizeof *arr);
char *arr = malloc( size_to_alloc );
char *p = arr;
for ( ; *dst ; p++, dst++)
*p = *dst;
*p = '\0';
return(arr);
}
If you want to dynamically copy an array, you'll need to allocate memory for the char array using malloc or other equivalent. Make sure you free the memory once you're done with it. I would suggest reading some posts on malloc and allocating memory in c.
This is probably a good place to start.
https://www.geeksforgeeks.org/dynamic-memory-allocation-in-c-using-malloc-calloc-free-and-realloc/
#include <stdio.h>
#include <stdlib.h>
char* function(char *dst, size_t length) {
int i;
// Allocating the memory needed for the char array.
char *arr = (char*) malloc (sizeof(char) * length);
i = 0;
while(dst[i] != '\0') {
arr[i] = dst[i];
i++;
}
arr[length - 1] = '\0';
return(arr);
}
int main(void) {
char a[] ="asdf";
// Getting length of the array
size_t length = sizeof(a) / sizeof(a[0]);
char* val = function(a, length);
printf("%s", val);
free(val);
}
You are missing the memory allocation and basically attempting to recode strdup. See below:
char *ft_strdup(const char *src)
{
char *dst;
int len;
len = 0;
while (src[len]) // no inner function
++len;
if (!(dst = malloc(sizeof(char) * (len + 1)))) // need 1 extra char to NULL terminate.
return NULL;
dst[len] = '\0';
while (--len > -1)
dst[len] = src[len];
return dst;
}
Note that it makes sense to code your own version of strdup and include it in your program library as this function is not part of the C Standard.
If there is a possibility of copying strings without using c functions, perhaps it can be done by doing what c functions do.
it may be interesting to see what strcpy does:
https://code.woboq.org/userspace/glibc/string/strcpy.c.html
char *
STRCPY (char *dest, const char *src)
{
return memcpy (dest, src, strlen (src) + 1);
}
infact it uses memcpy: https://code.woboq.org/gcc/libgcc/memcpy.c.html
and here the magic...
void *
memcpy (void *dest, const void *src, size_t len)
{
char *d = dest;
const char *s = src;
while (len--)
*d++ = *s++;
return dest;
}
and strlen: https://code.woboq.org/userspace/glibc/string/strlen.c.html
You can use memcpy() to copy memory directly, like in Memcpy, string and terminator and https://www.gnu.org/software/libc/manual/html_node/Copying-Strings-and-Arrays.html In C any string has to be terminated by \0 (sentinel value)
#include<stdio.h>
#include<string.h>
int main()
{
char source[] = "World";
char destination[] = "Hello ";
/* Printing destination string before memcpy */
printf("Original String: %s\n", destination);
/* Copies contents of source to destination */
memcpy (destination, source, sizeof(source));
/* Printing destination string after memcpy */
printf("Modified String: %s\n", destination);
return 0;
}
source : https://www.educative.io/edpresso/c-copying-data-using-the-memcpy-function-in-c

Reversing a C string function crashes?

I'm trying to write a C function to reverse a passed in C style string (ie char *) and return the char pointer of the reversed string. But when I run this in VS2012, nothing is printed in terminal and "main.exe has stopped working" msg shows up.
#include <stdio.h>
#include <string.h>
char * rrev_str(char * str )
{
char *revd_str=""; //I tried char revd_str []="" error: stack around "revd_str" is corrupted
int i,r;
int str_len=strlen(str);
for (i = str_len-1, r=0; i >=0; i--,r++)
{
revd_str[r]= str[i];
}
return revd_str;
}
int main(int argc, char* argv[])
{
char str1 [] ="STEETS";
char str2 [] ="smile everyday!";
//reverse "chars" in a C string and return it
char * rev_string=rrev_str(str1);
}
The problem here is three fold. First you aren't allocating enough space for the reversed string, and secondly you are returning a pointer to a local variable in rrev_str(), and thirdly you're modifying a string literal. You need to allocate space for revd_str on the heap:
char * rrev_str(char * str )
{
int i,r;
int str_len=strlen(str);
char *revd_str=malloc(str_len + 1);
memset(revd_str, 0, str_len + 1);
for (i = str_len-1, r=0; i >=0; i--,r++)
{
revd_str[r]= str[i];
}
return revd_str;
}
Problem: You are accessing invalid memory address.
revd_str is pointing to literal constant string of length 1 and you are accessing it beyond the length which is invalid.
Solution:
Create char array of require length (statically or dynamically).
Reverse the given string.
Pass 2nd param as destination string
syntax: char * rrev_str(char * src, char *dest);
Reverse the given string
char * rrev_str(char * str )
{
int start = 0;
int end = strlen(str) - 1;
char temp;
for (; start < end; start++ ,end--)
{
temp = str[start];
str[start] = str[end];
str[end] = temp;
}
return str;
}
int main(int argc, char* argv[])
{
char string [] ="smile";
//reverse "chars" in a C string and return it
char * rev_string = rrev_str(string);
printf("%s",rev_string);
}
Pass 2nd param as destination string
char * rrev_str(char * src, char *dest)
{
int srcLength = strlen(src);
int destLength = strlen(dest);
int i;
// Invalid destination string
if (srcLength > destLength)
{
return NULL;
}
dest[srcLength] = '\0';
srcLength--;
for (i=0; srcLength >= 0;i++, srcLength--)
{
dest[i] = src[srcLength];
}
return dest;
}
int main(int argc, char* argv[])
{
char string [] ="smile";
char revString[20];
//reverse "chars" in a C string and return it
char * rev_string = rrev_str(string, revString);
printf("%s",rev_string);
}
What! you are doing..
char *revd_str=""; // Creating String Literal which can't be modified because they are read only
char *revd_str[]=""; // Creating Char Array of Size Zero.
So Solution are
Either take reference of your string
char *revd_str = strdup(str);
Or create dynamic char array
char *revd_str = (char*) malloc (strlen(str)+1);
your program will run fine. logic is incorrect for reversing so modify it. A sample solution is given below
char * rrev_str(char * str )
{
char *revd_str=strdup(str);
int i; // no need for extra 'int r'
int str_len=strlen(str);
for (i = 0; i < str_len/2; i++)
{
char temp = revd_str[i];
revd_str[i]= revd_str[str_len - 1 -i];
revd_str[str_len - 1 -i] = temp;
}
return revd_str;
}

Trouble filling a dynamic c array

I am having issues with filling an array of strings that was created dynamically. The array basically contains two strings and I would like to print them both with their lengths. I am getting a very weird result whereby the memory locations are getting mixed up. Please see the code below.
Any suggestions would greatly be appreciated. Thanks.
void printWords(char **words, int numberOfWords)
{
int index;
for (index = 0; index < numberOfWords; index++)
{
printf("%s, %d\n", &(*words)[index], (int)strlen(&(*words)[index]));
}
}
void fillWords(char **words)
{
*words = malloc(2 * sizeof(char *));
char hello[] = {"Hello"};
(*words)[0] = (char)malloc(strlen(hello) * sizeof(char));
strcpy(&(*words)[0], hello); //Copy word into array
char world[] = {"Worldz"};
(*words)[1] = (char)malloc(strlen(world) * sizeof(char));
strcpy(&(*words)[1], world); //Copy word into array
}
int main (int argc, const char * argv[])
{
char *words;
fillWords(&words);
printWords(&words, 2);
return 0;
}
The expected output should be
Hello, 5
Worldz, 6
however I am getting
HWorldz, 7
Worldz, 6
I think you are getting confused between char * and char **.
Also, be sure to allocate enough memory for the null-termination character at the end of the string.
Here is my solution:
#include <stdio.h>
#include <string.h>
#include <malloc.h>
void printWords(char **words, int numberOfWords)
{
int index;
for (index = 0; index < numberOfWords; index++)
{
printf("%s, %d\n", words[index], (int)strlen(words[index]));
}
}
char ** createWords()
{
char ** words;
// Allocate memory for an array of pointers, length 2.
words = malloc(2 * sizeof(char *));
char hello[] = {"Hello"};
words[0] = malloc((strlen(hello)+1) * sizeof(char));
strcpy(words[0], hello); //Copy word into array
char world[] = {"Worldz"};
words[1] = malloc((strlen(world)+1) * sizeof(char));
strcpy(words[1], world); //Copy word into array
return words;
}
int main (int argc, const char * argv[])
{
char **words;
words = createWords();
printWords(words, 2);
return 0;
}
I renamed fillWords to createWords and made it return a pointer instead of taking a pointer as an argument. If you really want fillWords to take a pointer as an argument, you can do it, but the argument will have to be of type char ***.
First problem: you can't put 2 words in a char * (well ... you can, but not the way you're doing; and the way to do it is nothing like your code).
You need an "array of strings", or, more C-like, an array of char *:
char *words[2]; /* words[0] and words[1] are pointers to char */
char *wrong; /* wrong[0] is a char; wrong[1] is a char */
So, change the definition of words in your main and check/edit all the other functions for correctness.
int main (int argc, const char * argv[])
{
char *words[2];
fillWords(words);
printWords(words, 2);
return 0;
}
Here is the solution. I was getting confused between char* and char. What I want was an array of chars.
void printWords(char **words, int numberOfWords)
{
int index;
for (index = 0; index < numberOfWords; index++)
{
printf("%s, %d\n", words[index], (int)strlen(words[index]));
}
}
void fillWords(char **words)
{
*words = malloc(2 * sizeof(char *));
char hello[] = {"Hello"};
words[0] = malloc(strlen(hello) * sizeof(char));
strcpy(words[0], hello); //Copy word into array
char world[] = {"Worldz"};
words[1] = malloc(strlen(world) * sizeof(char));
strcpy(words[1], world); //Copy word into array
}
int main (int argc, const char * argv[])
{
char *words;
fillWords(&words);
printWords(&words, 2);
return 0;
}

Resources