I see a very interesting code to reverse a string,
but I don't understand here:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void Reverse(char *s);
int main()
{
char *s=NULL;
s=(char *)malloc(sizeof(char *));
gets(s);
Reverse(s);
puts(s);
return 0;
}
void Reverse(char *s)
{
char *end=s;
char tmp;
if (s)
{
while (*end)
{
++end;
}
--end;
while (s<end) ??
{
tmp=*s;
*s++=*end;
*end--=tmp;
}
}
}
I see the this program tries to work on the same string by using end=s to change both string at the same time, but what does '*' line : while(s<end) here mean?
I use gdb and find that when we input asdfgh, when *s is fdsa and *end is fds, this is no longer true, how this line controls the program?
I just want to know what '??' line mean..
Thanks a lot !
Strings in C are terminated by the \0 character, which has the integer value 0. As such it is a false value.
By using while(*end) you check whether end is pointing on the termination character of the given string. If it isn't pointing on the end, you move it further (++end). To ensure that the pointer is valid you move the "cursor" backward after this.
while(s < end) will now move check whether s is further forwarded than end. If not, then you'll swap the value of both "cursor". end will move toward s and vice versa. This way you're going to reverse the string.
You're debugging output is a result of gdbs interpretation. It interpreds end as a string, not a single character. Have a look at *end while debugging.
Note that your malloc is completely wrong. You have to allocate enough memory for the string, for example s = malloc(500*sizeof(char));. Use fgets instead, where you can specify the maximum number of characters to be read. Don't forget to free all memory you allocate:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define BUFFER_SIZE 500
void Reverse(char *s);
int main()
{
char* s = malloc(BUFFER_SIZE * sizeof(char));
fgets(s,BUFFER_SIZE,stdin);
Reverse(s);
puts(s);
free(s);
return 0;
}
void Reverse(char *s)
{
char* end=s;
char tmp;
if(s)
{
while (*end)
{
++end;
}
--end;
while (s<end)
{
tmp=*s;
*s++=*end;
*end--=tmp;
}
}
}
s and end are char pointer so the test (s < end) is true until the s pointer doesn't become greater than then end pointer.
Example
Assume that you want to reverse the string "hello" stored at the address 0x0000, ad the start of the function you have:
s = 0x0000
end = 0x003
now the while loop:
s=0x0000 e=0x0003 *s=o *e=h
s=0x0001 e=0x0002 *s=l *e=e
s=0x0002 e=0x0003 << while exit >>
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
My program need to print all the ABC but I see I have problems with the code. How I can fix it? (no pointer for this time).
What is the runtime error in the code and how to fix it?
Here is the code:
// Elvis’s hip and happening ABC-printing code
#include <stdio.h>
#include <string.h>
#define NUM_ABC_LET 26
void makeABC(char abc[NUM_ABC_LET]);
int main() {
char abcString[NUM_ABC_LET] = "";
makeABC(abcString);
puts(abcString);
return (0);
}
void makeABC(char abc[NUM_ABC_LET]) {
char letter;
for (letter = 'a'; letter <= 'z'; letter++) {
strcat(abc, letter);
}
}
The problem is that the strcat function expects both arguments to be (zero-terminated) strings. You only pass one string, and then one single character as arguments (which should give you compiler warnings).
You need to convert this single characters into a string (or an array) of a single character.
And don't forget that strings in C are zero-terminated.
What happens you use the single character as argument to the strcat function is that the compiler converts it to an int which is then in turn converted to a pointer. The problem with this is that the address 'a' (for example) is not a valid address to a string. That will lead to undefined behavior and a crash.
Your program logic is correct, the problem is the calling of the strcat() function. The strcat() function is implemented as:
char *strcat(char *dest, const char *src)
{
char *ret = dest;
while (*dest)
dest++;
while (*dest++ = *src++);
return ret;
}
The second argument must be a string instead which you pass a character.
This is the reason for your run time error.
Can you try something like following? I haven't tested the following but it should work on most part.
// Elvis’s hip and happening ABC-printing code
#include <stdio.h>
#include <string.h>
#define NUM_ABC_LET 26
void makeABC(char abc[NUM_ABC_LET]);
int main()
{
char abcString[NUM_ABC_LET + 1];
makeABC(abcString);
puts(abcString);
return 0;
}
void makeABC(char abc[NUM_ABC_LET + 1])
{
char letter;
int i=0;
for(letter = 'a'; letter <= 'z'; letter++)
{
abc[i] = letter;
i++;
}
abc[i]='\0';
}
Your program has several issues:
You cannot call strcat with a char, you must pass char * arguments, pointing to null terminated C strings.
The array into which you compose the alphabet is too short: you need to define it with a size one larger than the number of characters for the final '\0' terminator.
Here is a corrected version:
#include <stdio.h>
#include <string.h>
#define NUM_ABC_LET ('z' - 'a' + 1) // 26 ASCII letters
void makeABC(char *abc); // makeABC receives a pointer to an array of char
// this declaration is equivalent to
// void makeABC(char abc[NUM_ABC_LET+1]);
// but less error prone
int main(void) {
char abcString[NUM_ABC_LET + 1] = "";
makeABC(abcString);
puts(abcString);
return 0;
}
void makeABC(char *abc) {
char letter;
char buf[2]; // a buffer for a 1 letter C string
for (letter = 'a'; letter <= 'z'; letter++) {
buf[0] = letter; // make a 1 letter string
buf[1] = '\0'; // set the null terminator
strcat(abc, buf);
}
}
Prototype of strcat is
char *strcat(char *destination, const char *source);
means our source as well as destinations should and must be string so this is the issue that why if you compile in turbo c it will through error of
"type mismatch".
and if you wanna write program for printing ABC up to Z than simply write
void main()
{
int i;
for(i = 65; i<=90; i++)
{
printf("%c", i);
}
}
I hope you will like it......
As a slight variation, I would suggest passing the length of the character array to the function, so that the function does not overflow the array.
As the character array is passed to the function as a pointer, the function does not know it's size.
In your case you know the size, but for the future it might be better to explicitly pass the size.
Also I just copied the characters rather than use strcat, and added the null termination at the end.
#include <stdio.h>
#define NUM_ABC_LET 26
/* function takes pointer to array and size of array */
void makeABC(char *abc, int len);
int main()
{
/* array needs to include space for null termination */
char abcString[NUM_ABC_LET + 1];
/* call function with pointer + size */
makeABC(abcString, NUM_ABC_LET);
printf("%s\n", abcString);
return (0);
}
void makeABC(char *abc, int len)
{
int n;
for(n = 0; n < len; n++ ) {
/* add letters to the array */
abc[n] = n + 'a';
}
/* put a null termination on the end */
abc[n] = '\0';
}
I need to write a probram in C, which adds a string to a string etc. (for example '5' strings - It needs to read "vbvbvbvbvb" 5 times.) But it doesn't work? Help please!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char s[80];
int len;
int counter = 0;
char* repeat(char* s, int n) {
if (n > 0) {
if (s[len] == n) {
counter++;
}
len--;
repeat(s, (n++));
}
return s;
}
int main(void) {
printf("%s", repeat("vb", 5));
fflush(stdout);
return EXIT_SUCCESS;
}
You're trying to write into the end of "vb" which is a string in the constant pool. Don't do that. Allocate a string that is strlen(s) * n + 1 long and write into that.
Your base case is probably wrong. The base case should probably be when n == 0 which is when the empty string (nothing appended except terminating NUL as below) is appropriate.
Your recursive step (n++) should probably be (n - 1) to count down to that base case. As written, the post-increment does a useless assign and recurses with the same value of n.
I don't know what counter and len are supposed to do, but they looks redundant to me. len is uninitialized, so s[len] has undefined behavior.
After writing the n copies, you need to add a terminating NUL ('\0') at the end so that printf and similar functions can identify the end.
You are using s both as a global and a local variable, the function is working on the local.
Try not to use global variables where not necessary. Also, recursion is not necessary for this.
#include <stdio.h>
void concatenate_string(char *dest, const char *src, int n) {
char *s;
while(n--) {
s = (char*)src;
while(*(s))
*(dest++)=*(s++);
}
*(dest++) = 0;
}
int main(void) {
char out[80];
concatenate_string(out, "ab", 5);
printf("%s", out);
return 0;
}
so I was practicing writing c code with pointers using the K&R. For one problem with strcat function, I couldn't find out what was wrong with my code, which according to Visual Studio, returned the destination string unchanged after the strcat function. Any suggestion is appreciated!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int strcat(char* s, char* t);
int main(void)
{
char *s="hello ", *t="world";
strcat(s,t);
printf("%s",s);
return 0;
}
int strcat(char* s,char* t)
{
int i;
i=strlen(s)+strlen(t);
s=(char*) malloc(i);
while(*s!='\0')
s++;
while('\0'!=(*s++=*t++))
;
return 0;
}
I'm pretty sure that strcat returns a char* in the real implementation (holding the original value of the first string).
strcat is not supposed to alter the first parameter's address, so you shouldn't call malloc.
Point #2 means that you need to declare char *s as char s[20] in main (where 20 is some arbitrary number big enough to hold the whole string).
If you really want to alter the value of the an input parameter you will need to pass the address of the value - so it would need to be strcat(char **s, ...) in the function declaration/definition, and called with strcat(&s, ...) in main.
1) defining string in this way
char *s="hello "
means that you are defined a literal string. a literal string is saved into read only memory so you can not edit it
you have to define your string as a char array in order to be able to edit it
char s[100] = "hello ";
2) when you define your function in this way
int strcat(char* s,char* t)
you can not change the address of s into the function strcat(). So assigning memory with malloc() into the function will not change the s address when leaving the function
3) change your function strcat to
int strcat(char** s,char* t)
{
int i;
char *u, *v;
i=strlen(*s)+strlen(t);
v = *s;
u=(char*) malloc(i+1);
while(*v!='\0')
*u++ = *v++;
while('\0'!=(*u++=*t++));
*s = u;
return 0;
}
and you call it in the main with:
char *s="hello ", *t="world";
strcat(&s,t);
In
strcat(char* s, char* t)
the 's' is send by value. The value of 's' at call time is copied into the stack then strcat() is call. At the return of strcat the modified version is discard from the stack. So the calling value of 's' is never changed (and you create a memory leak).
Beward, in C every memory cell can be change, even parameters or instructions sections; some changes can be very hard to understand.
Since you are trying to do like the real strcat it's said that the first parameter
The string s1 must have sufficient space to hold the result.
so you don't need to use malloc
char *strcat(char* s, const char* t);
int main(void)
{
char s[15] = {0}; //
char *t = "world"; //const char * so you can't change it
strcpy(s, "Hello ");
strcat(s,t);
printf("%s\n",s);
return (0);
}
char *strcat(char* s, const char* t)
{
int i = 0;
while (s[i] != '\0')
i++;
while (*t != '\0')
s[i++] = *t++;
s[i] = '\0'; //useless because already initialized with 0
return (s);
}
#include<stdio.h>
#include<string.h>
#define LIMIT 100
void strcatt(char*,char*);
main()
{
int i=0;
char s[LIMIT];
char t[LIMIT];
strcpy(s,"hello");
strcpy(t,"world");
strcatt(s,t);
printf("%s",s);
getch();
}
void strcatt(char *s,char *t)
{
while(*s!='\0')
{
s++;
}
*s=' ';
++s;
while(*t!='\0')
{
*s=*t;
s++;
t++;
}
*s=*t;
}
Dear user,
you don't have to complicate things that much. The simpliest code for strcat, using pointers:
void strcat(char *s, char *t) {
while(*s++); /*This will point after the '\0' */
--s; /*So we decrement the pointer to point to '\0' */
while(*s++ = *t++); /*This will copy the '\0' from *t also */
}
Although, this won't give you report about the concatenation's success.
Look at this main() part for the rest of the answer:
int main() {
char s[60] = "Hello ";
char *t = "world!";
strcat(s, t);
printf("%s\n", s);
return 0;
}
The s[60] part is very important, because you can't concatenate an another string to it's end if it doesn't have enough space for that.
I have the following code:
#include <stdio.h>
void insertion_sort(char[], int);
void swap(char*, char*);
int main() {
char s[] = "hello world";
puts(s);
insertion_sort(s, sizeof(s)/sizeof(char));
puts("done\n");
puts(s);
return 0;
}
void swap(char* a, char* b) {
char tmp = *a;
*a = *b;
*b = tmp;
}
void insertion_sort(char s[], int n)
{
int i,j;
/* counters */
for (i=1; i<n; i++) {
j=i;
while ((j>0) && (s[j] < s[j-1])) {
swap(&s[j],&s[j-1]);
j = j-1;
}
printf("%s\n", s);
}
}
The problem is, after the insertion_sort() function call, s becomes empty - puts(s) prints nothing.
Please advise.
Change:
insertion_sort(s, sizeof(s)/sizeof(char));
to:
insertion_sort(s, strlen(s));
otherwise you will be including the '\0' terminator of s[] in your sort.
Note that you will need an additional header for strlen so change:
#include <stdio.h>
to:
#include <stdio.h> // printf etc
#include <string.h> // strlen etc
The problem is that the length that you pass to insertion_sort includes terminating \0 character, which happens to have value 0, so in sort it is placed as the first element of your array. This is why your last puts() prints nothing - because the first character is now "the end of a string".
I suggest you to calculate the size of a string using strlen() which will return the length of a string excluding terminating character. Or if you want to do it your way, take terminating character into consideration and substract it from the total length.
my problem is in convert a char to string
i have to pass to strcat() a char to append to a string, how can i do?
thanks!
#include <stdio.h>
#include <string.h>
char *asd(char* in, char *out){
while(*in){
strcat(out, *in); // <-- err arg 2 makes pointer from integer without a cast
*in++;
}
return out;
}
int main(){
char st[] = "text";
char ok[200];
asd(st, ok);
printf("%s", ok);
return 0;
}
Since ok is pointing to an uninitialized array of characters, it'll all be garbage values, so where the concatenation (by strcat) will start is unknown. Also strcat takes a C-string (i.e. an array of characters which is terminated by a '\0' character). Giving char a[200] = "" will give you a[0] = '\0', then a[1] to a[199] set to 0.
Edit: (added the corrected version of the code)
#include <stdio.h>
#include <string.h>
char *asd(char* in, char *out)
{
/*
It is incorrect to pass `*in` since it'll give only the character pointed to
by `in`; passing `in` will give the starting address of the array to strcat
*/
strcat(out, in);
return out;
}
int main(){
char st[] = "text";
char ok[200] = "somevalue"; /* 's', 'o', 'm', 'e', 'v', 'a', 'l', 'u', 'e', '\0' */
asd(st, ok);
printf("%s", ok);
return 0;
}
strcat will not append single characters. Instead it takes a const char* (a full C-style string) which is appended to the string in the first parameter. So your function should read something like:
char *asd(char* in, char *out)
{
char *end = out + strlen(out);
do
{
*end++ = *in;
} while(*in++);
return out;
}
The do-while loop will include the zero-terminator which is necessary at the end of C-style strings. Make sure that your out string is initialized with a zero-terminator at the end or this example will fail.
And as an aside: Think about what *in++; does. It will increment in and dereference it, which is the very same as in++, so the * is useless.
To look at your code, I can make a couple of pointers in relation to it, this is not a criticism, take this with a pinch of salt that will enable you to be a better C programmer:
No function prototype.
Incorrect usage of pointers
Dealing with the strcat function is used incorrectly.
Overdoing it - no need for the asd function itself!
Usage of dealing with variables notably char array that is not properly initialized.
#include <stdio.h>
#include <string.h>
int main(){
char st[] = "text";
char ok[200];
ok[0] = '\0'; /* OR
memset(ok, 0, sizeof(ok));
*/
strcat(ok, st);
printf("%s", ok);
return 0;
}
Hope this helps,
Best regards,
Tom.
To convert a character to a (null terminated) string you could simply do:
char* ctos(char c)
{
char s[2];
sprintf(s, "%c\0", c);
return s;
}
Working example: http://ideone.com/Cfav3e