i've done a function that inverse a String(array of character) given in parameter , but it's not working , any idea why ?
I'm getting something like this : æIGt(Kt$0#
thanks you
#include <stdio.h>
#include <string.h>
char *
inverse(char *s)
{
int i, taille = strlen(s);
char r[taille];
for (i = 0 ; i < taille ; i++)
{
r[i] = s[taille - i - 1];
}
r[i] = '\0';
return r;
}
int
main()
{
char s[] = "kira";
char *r = inverse(s);
printf("%s",r);
return 1;
}
You are returning a pointer to a local variable. That variable gets destroied when the function inverse returns, so accessing the pointer after the function exits will return invalid data.
It's slightly hard to tell from you question, because you haven't given any outputs, but my best guess is that it's because your returning a pointer to an item on the stack, which will get over-written by the next call, in your case printf. You need to pass inverse a place to put its answer. Try this instead:
#include <stdio.h>
#include <string.h>
void inverse(char *s, char *r)
{
int i,taille=strlen(s);
for(i=0;i<taille;i++)
{
r[i]=s[taille-i-1];
}
r[i]='\0';
}
int main()
{
char s[] = "kira";
char r[sizeof(s)];
inverse(s, r);
printf("%s",r);
return 1;
}
Another standard approach to reversing a string uses pointers to work from both the beginning and end of the string swapping two characters with each iteration. It swaps the original string in place (make a copy if you need to preserve the original, or pass a second string and place the reversed string in there)
/** strrevstr - reverse string, swaps 2 chars per-iteration.
* Takes valid string and reverses, original is not preserved.
* If 's' is valid and non-empty, returns pointer to 's',
* returns NULL otherwise.
*/
char *strrevstr (char *s)
{
if (!s || !*s) { /* validate string is not NULL and non-empty */
printf ("strrevstr() error: invalid string\n");
return NULL;
}
char *begin = s; /* pointers to beginning and end, and tmp char */
char *end = begin + strlen (s) - 1;
char tmp;
while (end > begin) /* swap both beginning and end each iteration */
{
tmp = *end;
*end-- = *begin;
*begin++ = tmp;
}
return s;
}
As you can tell, there are a number of ways to approach the problem, with this and the other answers provided, you should be able to tailor a solution to meet your needs.
There are advantages and disadvantages to every approach. There is nothing wrong with dynamically allocating a new block of memory to hold the reversed string, it just adds an additional responsibility to (1) preserve a pointer to the starting address for the new block so (2) it can be freed when no longer needed. If you need to preserve the original string, passing a pointer to an character array of sufficient size to hold the reversed string is another option preserve the original.
Look over all the answers and let me know if you have any questions.
Related
I understand that issues with string-reversal in C are numerous on this site, but I seem to be having a uniquely odd problem: the reversal logic simply does not run despite seeming to be set up correctly.
I wanted to write a program to reverse a given string in-place, by moving two pointers from the front and back of the string together:
void reverse_inplace_pointer(char *string_in, int length) {
char *back_ptr = string_in + (length - 1);
for (int i = 0; i < length / 2; i++) {
char swap_char = *back_ptr;
/* Dereference pointers to double-check values */
printf("\nCurrent front char: %c\nCurrent back char: %c", *string_in, *back_ptr);
/* Swap */
*back_ptr = *string_in;
*string_in = swap_char;
printf("\nSwap %u successful.", i + 1);
string_in++;
back_ptr--;
}
}
Calling this with a test string:
char *test_string = "TestMeTestMe";
nets the result:
Current front char: T
Current back char: e
And then execution just stops, at the assignment of the character pointed to by *string_in to the location pointed to by *back_ptr. If I remove the assignment, the program will quite happily move the pointers along the test string and print out each character without issue.
I looked for other examples of reassigning elements in arrays and found the logic in tutorials to be almost identical to mine. I copied this example wholesale as a test:
void steal_this_function(char *string) {
printf("\nEntering function:");
int length, c;
char *begin, *end, temp;
length = strlen(string);
begin = string;
end = string;
for (c = 0; c < (length - 1); c++) {
end++;
}
for (c = 0; c < length / 2; c++) {
temp = *end;
*end = *begin;
*begin = temp;
begin++;
end--;
}
}
The result is the same - it stops on the first iteration and the program exits. The only difference here is the reuse of the original pointer string, which is then walked to the end of the string with a for-loop.
Clearly I have some confusion here with pointers, but my understanding was that *back_ptr = *string_in; effectively says dereference the pointer string_in, then go to the location pointed to by back_ptr and store whatever it contains there.
I'm also compiling with the -Wall flag on GCC and it isn't finding any issues. This is frustrating because it should be very simple.
the function requires modifiable char array. It cannot be called when parameter is a pointer to thestring literal.
Some additional remarks.
This kind of function should return the reversed string. It is possible to use it as a parameter of another functions.
strlen returns size_t not int. Use the correct type in the loops as well
#include <string.h>
#include <stdio.h>
char *reverse(char *str)
{
char *end = str + strlen(str) - !!*str;
char *wrk = str;
while(end > wrk)
{
char tmp = *wrk;
*wrk++ = *end;
*end-- = tmp;
}
return str;
}
int main(void)
{
char str[] = "0123456789";
printf("%s\n", reverse(str));
}
Calling this with a test string: char *test_string = "TestMeTestMe";
That's the culprit, as noted in the comments, it declares a pointer to the memory where the string literal "TestMeTestMe" is stored, which you are not allowed to modify.
You should declare an array instead.
char test_string[] = "TestMeTestMe"; // Now test_string is a modifiable
// NULL-terminated char[13]
I'm also compiling with the -Wall flag on GCC and it isn't finding any issues.
-Wall it's not enough, but you can use -Wwrite-strings to catch this particular issue (see e.g. here).
I have a string declared as such:
char *mode_s = (char *)calloc(MODE_S_LEN, sizeof(char));
How can I add a char to the end of the array?
Lets assume " first available position " means at index 0.
char *mode_s = (char *)calloc(MODE_S_LEN, sizeof(char));
*mode_s='a';
To store a character at an arbitrary index n
*(mode_s+n)='b';
Use pointer algebra, as demonstrated above, which is equivalent to
mode_s[n]='b';
One sees that the first case simply means that n=0.
If you wish to eliminate incrementing the counter, as specified in the comment bellow, you can write a data structure and a supporting function that fits your needs. A simple one would be
typedef struct modeA{
int size;
int index;
char *mode_s;
}modeA;
The supporting function could be
int add(modeA* a, char toAdd){
if(a->size==a->index) return -1;
a->mode_s[index]=toAdd;
a->index++;
return 0;
}
It returns 0 when the add was successful, and -1 when one runs out of space.
Other functions you might need can be coded in a similar manner. Note that as C is not object oriented, the data structure has to be passed to the function as a parameter.
Finally you code code a function creating an instance
modeA genModeA(int size){
modeA tmp;
tmp.mode_s=(char *)calloc(size, sizeof(char));
tmp.size=size;
tmp.index=0;
return tmp;
}
Thus using it with no need to manually increment the counter
modeA tmp=genModeA(MODE_S_LEN);
add(&tmp,'c');
There is no standard function to concatenate a character to a string in C. You can easily define such a function:
#include <string.h>
char *strcatc(char *str, char c) {
size_t len = strlen(str);
str[len++] = c;
str[len] = '\0';
return str;
}
This function only works if str is allocated or defined with a larger size than its length + 1, ie if there is available space at its end. In your example, mode_s is allocated with a size of MODE_S_LEN, so you can put MODE_S_LEN-1 chars into it:
char *mode_s = calloc(MODE_S_LEN, sizeof(*mode_s));
for (int i = 0; i < MODE_S_LEN - 1; i++) {
strcatc(mode_s, 'X');
}
char newchar = 'a'; //or getch() from keyboard
//realloc memory:
char *mode_sNew = (char *)calloc(MODE_S_LEN + 1, sizeof(char));
//copy the str:
srncpy(mode_sNew, mode_s, MODE_S_LEN);
//put your char:
mode_sNew[MODE_S_LEN] = newchar;
//free old memory:
free(mode_s);
//reassign to the old string:
mode_s = mode_sNew;
//in a loop you can add as many characters as you want. You also can add more than one character at once, but assign only one in a new position
So I've looked around on SO and can't find code that answers my question. I have written a function that is supposed to reverse a string as input in cmd-line. Here is the function:
void reverse (char string[]) {
int x;
int i = 0;
char line[strlen(string)];
for (x = strlen(string) - 1; x > 0; x--) {
char tmp = string[x];
line[i] = tmp;
i++;
}
string = line;
}
When I call my reverse() function, the string stays the same. i.e., 'abc' remains 'abc'
If more info is needed or question is inappropriate, let me know.
Thanks!!
You're declaring your line array one char shorter remember the null at the end.
Another point, it should be for (x = strlen(string) - 1; x >= 0; x--) since you need to copy the character at 0.
void reverse (char string[]) {
int x;
int i = 0;
char line[strlen(string) + 1];
for (x = strlen(string) - 1; x >= 0; x--) {
char tmp = string[x];
line[i] = tmp;
i++;
}
for(x = 0; x < strlen(string); x++)
{
string[x] = line[x];
}
}
Note that this function will cause an apocalypse when passed an empty string or a string literal (as Bobby Sacamano said).
Suggestion you can probably do: void reverse(char source[], char[] dest) and do checks if the source string is empty.
I think that your answer is almost correct. You don't actually need an extra slot for the null character in line. You just need two minor changes:
Change the assignment statement at the bottom of the procedure to a memcpy.
Change the loop condition to <-
So, your correct code is this:
void reverse (char string[]) {
int x;
int i = 0;
char line[strlen(string)];
for (x = strlen(string) - 1; x >= 0; x--) {
char tmp = string[x];
line[i] = tmp;
i++;
}
memcpy(string, line, sizeof(char) * strlen(line));
}
Since you want to reverse a string, you first must decide whether you want to reverse a copy of the string, or reverse the string in-situ (in place). Since you asked about this in 'C' context, assume you mean to change the existing string (reverse the existing string) and make a copy of the string in the calling function if you want to preserve the original.
You will need the string library
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Array indexing works, and this version takes that approach,
/* this first version uses array indexing */
char*
streverse_a(char string[])
{
int len; /*how big is your string*/
int ndx; /*because 'i' is hard to search for*/
char tmp; /*hold character to swap*/
if(!string) return(string); /*avoid NULL*/
if( (len=strlen(string)) < 2 ) return(string); /*one and done*/
for( ndx=0; ndx<len/2; ndx++ ) {
tmp=string[ndx];
string[ndx]=string[len-1-ndx];
string[len-1-ndx]=tmp;
}
return(string);
}
But you can do the same with pointers,
/* this is how K&R would write the function with pointers */
char*
streverse(char* sp)
{
int len, ndx; /*how big is your string */
char tmp, *bp, *ep; /*pointers to begin/end, swap temporary*/
if(!sp) return(sp); /*avoid NULL*/
if( (len=strlen(bp=sp)) < 2 ) return(sp); /*one and done*/
for( ep=bp+len-1; bp<ep; bp++, ep-- ) {
tmp=*bp; *bp=*ep; *ep=tmp; /*swap*/
}
return(sp);
}
(No, really, the compiler does not charge less for returning void.)
And because you always test your code,
char s[][100] = {
"", "A", "AB", "ABC", "ABCD", "ABCDE",
"hello, world", "goodbye, cruel world", "pwnz0r3d", "enough"
};
int
main()
{
/* suppose your string is declared as 'a' */
char a[100];
strcpy(a,"reverse string");
/*make a copy of 'a', declared the same as a[]*/
char b[100];
strcpy(b,a);
streverse_a(b);
printf("a:%s, r:%s\n",a,b);
/*duplicate 'a'*/
char *rp = strdup(a);
streverse(rp);
printf("a:%s, r:%s\n",a,rp);
free(rp);
int ndx;
for( ndx=0; ndx<10; ++ndx ) {
/*make a copy of 's', declared the same as s[]*/
char b[100];
strcpy(b,s[ndx]);
streverse_a(b);
printf("s:%s, r:%s\n",s[ndx],b);
/*duplicate 's'*/
char *rp = strdup(s[ndx]);
streverse(rp);
printf("s:%s, r:%s\n",s[ndx],rp);
free(rp);
}
}
The last line in your code does nothing
string = line;
Parameters are passed by value, so if you change their value, that is only local to the function. Pointers are the value of the address of memory they are pointing to. If you want to modify the pointer that the function was passed, you need to take a pointer to that pointer.
Here is a short example of how you could do that.
void reverse (char **string) {
char line = malloc(strlen(*string) + 1);
//automatic arrays are deallocated once the function ends
//so line needs to be dynamically or statically allocated
// do something to line
*string = line;
}
The obvious issue with this is that you can initialize the string with static memory, then this method will replace the static memory with dynamic memory, and then you'll have to free the dynamic memory. There's nothing functionally wrong with that, it's just a bit dangerous, since accidentally freeing the string literal is illegal.
char *test = "hello";
reverse(test);
free(test); //this is pretty scary
Also, if test was allocated as dynamic memory, the pointer to it would be lost and then it would become a memory leak.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int reverse(char *, int);
main()
{
char *word = "Thanks for your help";
reverse(word, strlen(word));
printf("%s", word);
getchar();
}
int reverse(char *line, int len)
{
int i, j;
char *newline = malloc(strlen(line));
for (i = len - 1, j = 0 ; i >= 0; i--, j++)
{
newline[j] = line[i];
}
newline[j] = '\0';
line = &newline;
}
Hey folks. I've got a simple C question that I can't seem to solve.
The program above is meant to take in a string and print it out backwards. Reverse is the function by which this is done.
The issue, specifically, is that when I print word in main(), the string appears unchanged. I've attempted to make the address of line the address of newline, but it doesn't have any effect.
int reverse(char *line, int len)
{
int i, j;
char *newline = malloc(strlen(line));
for (i = len - 1, j = 0 ; i >= 0; i--, j++)
{
newline[j] = line[i];
}
newline[j] = '\0';
line = &newline; // Your problem is here
}
You're merely assigning to the local line pointer. This has no effect on the calling function whatsoever.
Consider instead:
char *reverse(char *line, int len)
{
// ...
return newline;
}
Additional advice:
Turn on compiler warnings, and heed them. You've got lots of little things wrong (e.g. reverse isn't currently returning anything, but is declared as returning int).
Given that the first argument of reverse is a pointer to a C string (NUL-terminated), there's no need to take a length argument as well.
A reverse function doesn't necessarily need to be defined as returning a copy of the string, reversed. It could instead reverse a string in-place. Note that you cannot pass a string literal to a function like this, as they are read-only.
Here's how I would write this:
#include <stdio.h>
#include <string.h>
void reverse(char *str)
{
size_t i, j;
for (i = strlen(str) - 1, j = 0 ; i > j; i--, j++)
{
// Swap characters
char c = str[i];
str[i] = str[j];
str[j] = c;
}
}
int main(void)
{
// Mutable string allocated on the stack;
// we cannot just pass a string literal to reverse().
char str[] = "Here is a test string";
reverse(str);
printf("Result: \"%s\"\n", str);
return 0;
}
Note that the for loop condition is i > j, because we want each to only traverse half the array, and not swap each character twice.
Result:
$ ./a.exe
Result: "gnirts tset a si ereH"
Take a look at the code below:
void addOne(int a) {
int newA = a + 1;
a = newA;
}
int main() {
int num = 5;
addOne(num);
printf("%d\n", num);
}
Do you see why that will print 5, and not 6? It's because when you pass num to addOne, you actually make a copy of num. When addOne changes a to newA, it is changing the copy (called a), not the original variable, num. C has pass-by-value semantics.
Your code suffers from the same problem (and a couple other things). When you call reverse, a copy of word is made (not a copy of the string, but a copy of the character pointer, which points to the string). When you change line to point to your new string, newLine, you are not actually changing the passed-in pointer; you are changing the copy of the pointer.
So, how should you implement reverse? It depends: there are a couple options.
reverse could return a newly allocated string containing the original string, reversed. In this case, your function signature would be char *reverse, instead of int reverse.
reverse could modify the original string in place. That is, you never allocate a new string, and simply move the characters of the original string around. This works, in general, but not in your case because char pointers initialized with string literals do not necessarily point to writable memory.
reverse could actually change the passed-in pointer to point at a new string (what you are trying to do in your current code). To do this, you'd have to write a function void reverse(char **pointerToString). Then you could assign *pointerToString = newLine;. But this is not great practice. The original passed-in argument is now inaccessible, and if it was malloc'd, it can't be freed.
I have a character pointer that points the begining of a string and an index less than the length of the string. Now I want to create a pointer to point a substring of original string from the begining to the index or a substring with above constraints. Please help me to find a way to get it done. Here is a bit of the code:
char* ch="323+465";//this is the original string
int index=2; //this is the index upto which I wish to create a substring,
// in java, it would have been ch.substring(0,3), if ch were a String
Thanks in advance.
You can't do that without creating 3 strings. The char point only marks the beginning of the string, so you would need to combine a pointer and an index into a new type. Remember you don't have strings in C. In languages like Java (and others) will create copies of the sub string anyway.
struct pseudo_string { char *s, int index; } vstring[3];
char* ch="323+465";
vstring[0].s = ch;
vstring[0].index = 2;
vstring[1].s = ch + index + 1; // weird
vstring[1].index = 1;
vstring[2].s = vstring[1].s + 1;
vstring[2].index = 2;
So it is overly complex and useless. In this case index is being used as counter...
If you want to keep the same base pointer, you gonna need 2 indices or 1 index and a len:
struct pseudo_string2 { char *s; int start; int end; };
But that's an overkill for small strings.
If don't want to use malloc, you can try to use a matrix:
char vstring[3][10]={0};
strncpy(vstring[0], ch, 3);
strncpy(vstring[1], ch+3, 1);
strncpy(vstring[2], ch+4, 3);
The advantage of the matrix, even if you waste few bytes, is that you don't need to deallocate it. But if you need to use these values outside this function, than you don't have another scape than to use malloc and free (don't consider globals for that ;-).
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * substr(char *s, int start, int end)
{
int size = end - start + 2; // 1 for the inclusive limits and another 1 for the \0
char * r = (char*)malloc(size);
strncpy(r,s+start, size-1);
r[size-1]=0;
return r;
}
int main()
{
char* ch="323+465";
char *parts[3];
parts[0] = substr(ch, 0,2);
parts[1] = substr(ch, 3,3);
parts[2] = substr(ch, 4,6);
printf("%s %s %s\n", parts[0], parts[1], parts[2]);
free(parts[0]);
free(parts[1]);
free(parts[2]);
}
Make a copy of a suitable number of characters:
char * substr = malloc(index + 2);
strncpy(substr, ch, index + 1);
substr[index + 1] = 0;
// ...
free(substr);
If you're happy to mutilate the original string, just insert a null byte:
ch[index + 1] = 0;
The odd + 1 comes from the fact that your index seems to be inclusive, which is generally a bad idea.
You can't, because that would imply modifying the string literal, which is illegal.
Alternative:
char ch[]="323+465";
int index=2;
ch[index] = '\0';
First, make the string writable by using a char array instead of a pointer to a string literal. Then
char ch[] = "323+456";
int idx = 2;
ch[idx] = 0; /* Now ch holds the string "32" */
You should avoid an identifier clash with the classic BSD index function, that's why I used idx instead.
This solution assumes it is okay to modify the original string. If not, you need to allocate a new string first.
the same behavior of java substring (allocates new string)
char* res = (char*)malloc(index+2);
strncpy(res,ch,index+1);
res[index+1]='\0';
I see that you try to delimit by +, so easier is to use strtok :
char ch[] ="323+465";
char * res;
res = strtok (ch,"+");
// res= 323