Folks, here is an implementation of memset(), however I have been told that there is one logical mistake in the code. Could you help me find it.
I feel that a double pointer for the target string should be passed to this function, which will be like passing the address of the pointer variable and not the pointer itself.
I am getting an "access violation" when I execute the code in MS VC++ IDE.
The definition of the ‘C’ Library function memset is
void *memset(char *s, char c, size_t n)
Copy c to the first n characters of s. Return s.
void *memset(char *s, char c, size_t n)
{
size_t i;
for (i = 0; i < n; i++, s++)
{
*s = c;
}
return s;
}
This has several problems.
void *memset(char *s, char c, size_t n)
{
size_t i;
for (i = 0; i < n; i++, s++) /* incrementing s means you cannot return */
{ /* the original value */
*s = c; /* consider using s[i] = c after not incr. s*/
}
return s; /* this should probably be a cast back to void */
}
You shouldn't be changing the pointer that is returned.
Check the return value of the function. What does it return? What is it documented to return?
I have a feeling that your size_t n may be off by one.
Also s points at the end of the string instead of the original s by the end of the function.
You modify the value of s and then return it. This means you will be returning a pointer to the end of the memset region, not the start (which is probably what you want)
You make the statement that you are getting a "access violation". That indicates that you are calling the function with a non-null value for 's', however, either 's' was not properly initialized
// bad - s will have some arbitrary value as allocated on the stack (all bets are off)
char *s;
memset(s,0,100);
// good
char s[100];
memset(s,0,100);
// bad - the memset will generate an access violation on byte 101
char s[100];
memset(s,0,101);
// good
char *s = malloc(100);
memset(s,0,100);
** one note not related to the access violation... returning 's' the way you do is not the same behavior as the traditional memset() in string.h. In that library, the return value is supposed to be the value of 's' as input. In your code you are returning a pointer to the byte after the last byte which would generate an access violation. for example:
// good
char *s = malloc(100);
char *d = memset(s,0,100);
printf("%s\n",d); // generates an access violation
in the memset() doc, d and s should have the same value. In your code, d = s[101];
Hum...
Try this:
void *memset (char* s, char c, size_t n){
char* begin = s;
char* end = begin + n;
whilw (begin != end) *begin++ = c;
return s;
}
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'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.
#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'm trying to solve a problem found on my C programming book.
#include <stdio.h>
char *f (char s[], char t[], char out[]);
int main(void)
{
char s[] = "ISBN-978-8884981431";
char t[] = "ISBN-978-8863720181";
char out[10];
printf ("%s\n", f(s,t,out));
return 0;
}
char *f (char s[], char t[], char out[]) {
int i;
for (i=0; s[i] == t[i]; i++)
out[i] = s[i];
out[i] = '\0';
return &out[0];
}
As you can see from the code, this code uses as return value &out[0]: does this means that the complete array is used as return value?
char *f (char s[], char t[], char out[]);
int main(void)
{
char s[] = "ISBN-978-8884981431";
char t[] = "ISBN-978-8863720181";
char out[10];
printf ("%s\n", f(s,t,out));
return 0;
}
char *f (char s[], char t[], char out[]) {
for (; *(s+=1) == *(t+=1);)
*(out+=1) = *s;
*(out+1) = '\0';
return out;
}
This is my proposed solution, but while the proposed code returns "ISBN-978-88", mine only returns "8".
The array is smaller than the lenght of the string, how the proposed code can work without any kind of overflow?
Thanks for your responses.
Your code is too aggressive on side effects: the += 1 operation (which is more commonly denoted simply as ++) should be applied after the copy to the output has been made, not after the comparison.
In addition, you need to save the value of the out buffer before incrementing the pointer, so that you could return a pointer to the beginning of the copied string.
char *orig = out;
for ( ; *s == *t ; s++, t++)
*out++ = *s;
*out = '\0';
return orig;
Demo on ideone.
Your code is returning a pointer to the end of the out array. Not the start. You need to stash the initial value of out and return that.
As an aside, the fact that you can do assignments inside a comparison doesn't mean it's a good idea. That code is going to be very hard to maintain.
&out[0] is equivalent to out. Since arrays in C are passed by reference, in a sense, yes it does return the entire array.
Your solution only prints "8" because you're returning a pointer into the middle of the array. When it tries to print the string, it has no way of knowing that it's in the middle of the array/string, thus you only get a substring printed.
Language: C
I am trying to program a C function which uses the header char *strrev2(const char *string) as part of interview preparation, the closest (working) solution is below, however I would like an implementation which does not include malloc... Is this possible? As it returns a character meaning if I use malloc, a free would have to be used within another function.
char *strrev2(const char *string){
int l=strlen(string);
char *r=malloc(l+1);
for(int j=0;j<l;j++){
r[j] = string[l-j-1];
}
r[l] = '\0';
return r;
}
[EDIT] I have already written implementations using a buffer and without the char. Thanks tho!
No - you need a malloc.
Other options are:
Modify the string in-place, but since you have a const char * and you aren't allowed to change the function signature, this is not possible here.
Add a parameter so that the user provides a buffer into which the result is written, but again this is not possible without changing the signature (or using globals, which is a really bad idea).
You may do it this way and let the caller responsible for freeing the memory. Or you can allow the caller to pass in an allocated char buffer, thus the allocation and the free are all done by caller:
void strrev2(const char *string, char* output)
{
// place the reversed string onto 'output' here
}
For caller:
char buffer[100];
char *input = "Hello World";
strrev2(input, buffer);
// the reversed string now in buffer
You could use a static char[1024]; (1024 is an example size), store all strings used in this buffer and return the memory address which contains each string. The following code snippet may contain bugs but will probably give you the idea.
#include <stdio.h>
#include <string.h>
char* strrev2(const char* str)
{
static char buffer[1024];
static int last_access; //Points to leftmost available byte;
//Check if buffer has enough place to store the new string
if( strlen(str) <= (1024 - last_access) )
{
char* return_address = &(buffer[last_access]);
int i;
//FixMe - Make me faster
for( i = 0; i < strlen(str) ; ++i )
{
buffer[last_access++] = str[strlen(str) - 1 - i];
}
buffer[last_access] = 0;
++last_access;
return return_address;
}else
{
return 0;
}
}
int main()
{
char* test1 = "This is a test String";
char* test2 = "George!";
puts(strrev2(test1));
puts(strrev2(test2));
return 0 ;
}
reverse string in place
char *reverse (char *str)
{
register char c, *begin, *end;
begin = end = str;
while (*end != '\0') end ++;
while (begin < --end)
{
c = *begin;
*begin++ = *end;
*end = c;
}
return str;
}