I am unable to use strtok over a char - c

I am unable to use strtok over char *a but on b its working.
Its working with malloc and array
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DELIM ":"
int main()
{
char *a = "xgdgsf: duh d";//unable to use strtok on it
char *token=NULL;
printf("%s",a);
char *b = malloc(strlen(a) + 1);
strcpy(b, a);//i can use strtko on it
token=strtok(b,DELIM);
printf("\n%s",token);
token=strtok(a,DELIM);
printf("\n%s",token);
return 0;
}

You have passed a to strtok which is a string literal. You can't do that because strtok modifies the string.
If you had defined the array as
const char *a = "xgdgsf: duh d";
then the compiler would give you a warning.
The second call to strtok should be
token=strtok(NULL, DELIM);
to extract the second token from b.

Change
char *a = "xgdgsf: duh d";
to
char *a = strdup("xgdgsf: duh d");
In C, string literals are read only. However, do remember that you need to free the pointer after calling strdup. Do it with free(a) when you are done with the string.

As others have pointed out, the problem is that a points to a string literal. strtok modifies its input (it overwrites the delimiters with a string terminator) and the behavior on attempting to modify a string literal is undefined - you may get a runtime error, the code may work as expected, or something else may happen. String literals are supposed to be immutable, but it's not guaranteed that they'll be stored in read-only memory.
There are several ways to resolve this. One is to declare a as an array and initialize it with the string:
char a[] = "xgdgsf: duh d";
Another is to dynamically allocate a buffer and copy the contents of the string to it:
char *a = malloc( strlen( "xgdgsf: duh d" ) + 1 );
if ( a )
strcpy( a, "xgdgsf: duh d" );
If it's available on your system, you can use the non-standard function strdup to do the same thing:
char *a = strdup( "xgdgsf: duh d" );
When declaring a pointer to a string literal, it's usually a good idea to qualify it as const:
const char *a = "xgdgsf: duh d";
that way the compiler will yak at you if you try to modify (assign to) *a or a[i] or pass it to a function that expects a plain char * as an input. That way mistakes like using strtok on a literal are caught at compile time, not runtime.

Related

The strtok Function With char * Argument

I was just playing around with some code, and ended up typing something along the lines of the following piece of code. The issue seems to be that the char *string line isn't actually interchangeable with a char string[], but I can't seem to wrap my head around why strtok(...) throws a "segmentation violation" if my argument is initialized as a char* to a string, or why it would even require an initialization of char[] instead?
#include <stdio.h>
#include <string.h>
//extern char *strtok (char *__restrict __s, const char *__restrict __delim);
char *string = "Hello world whats up?";
/*
SEGV - Must be char string[] in order to execute.
e.g. char string[] = "Hello world whats up?";
*/
char *delim = "\t ";
char *token;
int main (argc, argv)
int argc;
char **argv;
{
token = strtok(string, delim);
while ( token != NULL ) {
printf("%s\n", token);
token = strtok(NULL, delim);
}
}
The strtok function (potentially) modifies the string passed to it as its first argument. That is the critical point, here.
In your code snippet (not using the [] version), your string variable is initialized to be the address of a string literal. That literal is a constant and is likely to be placed in read-only memory. Thus, when you call strtok and that function finds a delimiter character, it attempts to replace that character with a nul, which would require writing to memory to which it does not have the required access – and your program crashes.
However, in your version using the [] syntax, you are declaring a (modifiable) array of characters and initializing it with a copy of the string literal.
In summary:
char* pc = "Hello, World!"; // pc points to a CONSTANT string literal
char ca[] = "Hello, World!"; // ca is a 'normal' array initialized with data
In C all literal strings are non-modifiable, they are in essence read-only.
When you define and initialize string you make it point to the first character of such a literal string.
This is the reason it's recommended to use const char * for literal strings.
If you want to modify the string in any way, and strtok modifies the string it tokenizes, then you must use an explicit modifiable array.

How to write to char* from a function in C

I am struggling to write a char* passed as an argument. I want to write some string to char* from the function write_char(). With the below code, I am getting a segmentation fault.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void write_char(char* c){
c = (char*)malloc(11*(sizeof(char)));
c = "some string";
}
int main(){
char* test_char;
write_char(test_char);
printf("%s", test_char);
return 0;
}
You have two problems (related to what you try to do, there are other problems as well):
Arguments in C are passed by value, which means that the argument variable (c in your write_char function) is a copy of the value from test_char in the main function. Modifying this copy (like assigning to it) will only change the local variables value and not the original variables value.
Assigning to a variable a second time overwrites the current value in the variable. If you do e.g.
int a;
a = 5;
a = 10;
you would (hopefully) not wonder why the value of a was changed to 10 in the second assignment. That a variable is a pointer doesn't change that semantic.
Now how to solve your problem... The first problem could be easily solved by making the function return a pointer instead. And the second problem could be solved by copying the string into the memory instead of reassigning the pointer.
So my suggestion is that you write the function something like
char *get_string(void)
{
char *ptr = malloc(strlen("some string") + 1); // Allocate memory, +1 for terminator
strcpy(ptr, "some string"); // Copy some data into the allocated memory
return ptr; // Return the pointer
}
This could then be used as
char *test_string = get_string();
printf("My string is %s\n", test_string);
free(test_string); // Remember to free the memory we have allocated
Within the function
void write_char(char* c){
c = (char*)malloc(11*(sizeof(char)));
c = "some string";
}
the parameter c is a local variable of the function. Changing it within the function does not influence on the original argument because it is passed by value. That is the function deals with a copy of the original argument.
You have to pass the argument by reference through pointer to it.
Also the function has a memory leak because at first the pointer was assigned with the address of the allocated memory and then reassigned with the address of the first character of the string literal "some string".
If you want to create a copy of a string literal then what you need is the following
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void write_char( char **s )
{
const char *literal = "some string";
*s = malloc( strlen( literal ) + 1 );
if ( *s ) strcpy( *s, literal );
}
int main( void )
{
char *test_char = NULL;
write_char( &test_char );
if ( test_char ) puts( test_char );
free( test_char );
}
The program output is
some string
Do not forget to allocate dynamically a character array that is large enough to store also the terminating zero of the string literal.
And you should free the allocated memory when the allocated array is not needed any more.
If you want just to initialize a pointer with the address of a string literal then there is no need to allocate dynamically memory.
You can write
#include <stdio.h>
void write_char( char **s )
{
*s = "some string";
}
int main( void )
{
char *test_char = NULL;
write_char( &test_char );
puts( test_char );
}
In C, you'll need to pass a pointer to a pointer. Your malloc call is trying to change the value of the variable that's being passed in, but it's actually only a copy. The real variable you pass in will not be changed.
Also, the way that you copy a string into a char* is not using assignment... Here's some revised code:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void write_char(char** c){
size_t len = strlen("some string");
*c = (char*)malloc(len + 1); // + 1 for null termination
strncpy(*c, "some string", len);
}
int main(){
char* test_char;
write_char(&test_char);
printf("%s", test_char);
return 0;
}
String assignment in C is very different from most modern languages. If you declare a char * and assign a string in the same statement, e.g.,
char *c = "some string";
that works fine, as the compiler can decide how much memory to allocate for that string. After that, though, you mostly shouldn't change the value of the string with =, as this use is mostly for a constant string. If you want to make that especially clear, declare it with const. You'll need to use strcpy. Even then, you'll want to stay away from declaring most strings with a set string, like I have above, if you're planning on changing it. Here is an example of this:
char *c;
c = malloc(16 * sizeof(char));
strcpy(c, "Hello, world\n");
If you're passing a pointer to a function that will reallocate it, or even malloc in the first place, you'll need a pointer to a pointer, otherwise the string in main will not get changed.
void myfunc(char **c) {
char *tmp = realloc(*c, 32 * sizeof(char));
if(tmp != NULL) {
*c = tmp;
}
}
char *c = malloc(16 * sizeof(char));
strcpy(c, "Hello, world\n");
myfunc(&c);
char* test_char="string"; // initialize string at the time of declaration
void write_char(char* c){
c = (char*)malloc(11*(sizeof(char)));
}
int main(){
char* test_char="strin";
write_char(test_char);
printf("%s", test_char);
return 0;
}

How to assign an array of characters to a string literal

I have an array of char and I'm trying to have a string literal with the same chars in the array.
I tried strcpy, and try =, and I tried what I did in the following code. But it doesn't seem to work or I'm understanding something.
char s1[10]="Youssef";
char *s2
while(*s2!='\0')
*s2++=*s1++;
printf("%s",s2);
Process doesn't return.
String literals are read only.
In any case, what you are trying to do seems you are confused.
A string literal: char *sl = "string literal";
An uninitialized char pointer: char *s2;
In order to do the copy you like, you first need to allocate memory for the string.
Moreover, you cannot do pointer arithmetics with an array. Arrays and pointers are not the same thing!
Furthermore, you should remember the origin of s2 pointer, since after incrementing it until the copy is complete, you would then need to reset the pointer.. Exercise: Think what would happen if you did the copy in a function (preferably named mystrcpy`)...
Complete example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char s1[10]="Youssef";
char *s2 = malloc(sizeof(char) * (strlen(s1) + 1)); // +1 for the NULL-terminator
int i = 0;
char *origin_s2 = s2;
while(s1[i] != '\0')
*s2++ = s1[i++];
*s2 = '\0';
s2 = origin_s2;
printf("%s\n", s2);
return 0;
}
Output:
Youssef
PS: It is highly recommended to check if the dynamic allocation of the memory was successful (check if return value of malloc() is not NULL).

Is it possible to modify a string of char in C?

I have been struggling for a few hours with all sorts of C tutorials and books related to pointers but what I really want to know is if it's possible to change a char pointer once it's been created.
This is what I have tried:
char *a = "This is a string";
char *b = "new string";
a[2] = b[1]; // Causes a segment fault
*b[2] = b[1]; // This almost seems like it would work but the compiler throws an error.
So is there any way to change the values inside the strings rather than the pointer addresses?
When you write a "string" in your source code, it gets written directly into the executable because that value needs to be known at compile time (there are tools available to pull software apart and find all the plain text strings in them). When you write char *a = "This is a string", the location of "This is a string" is in the executable, and the location a points to, is in the executable. The data in the executable image is read-only.
What you need to do (as the other answers have pointed out) is create that memory in a location that is not read only--on the heap, or in the stack frame. If you declare a local array, then space is made on the stack for each element of that array, and the string literal (which is stored in the executable) is copied to that space in the stack.
char a[] = "This is a string";
you can also copy that data manually by allocating some memory on the heap, and then using strcpy() to copy a string literal into that space.
char *a = malloc(256);
strcpy(a, "This is a string");
Whenever you allocate space using malloc() remember to call free() when you are finished with it (read: memory leak).
Basically, you have to keep track of where your data is. Whenever you write a string in your source, that string is read only (otherwise you would be potentially changing the behavior of the executable--imagine if you wrote char *a = "hello"; and then changed a[0] to 'c'. Then somewhere else wrote printf("hello");. If you were allowed to change the first character of "hello", and your compiler only stored it once (it should), then printf("hello"); would output cello!)
No, you cannot modify it, as the string can be stored in read-only memory. If you want to modify it, you can use an array instead e.g.
char a[] = "This is a string";
Or alternately, you could allocate memory using malloc e.g.
char *a = malloc(100);
strcpy(a, "This is a string");
free(a); // deallocate memory once you've done
A lot of folks get confused about the difference between char* and char[] in conjunction with string literals in C. When you write:
char *foo = "hello world";
...you are actually pointing foo to a constant block of memory (in fact, what the compiler does with "hello world" in this instance is implementation-dependent.)
Using char[] instead tells the compiler that you want to create an array and fill it with the contents, "hello world". foo is the a pointer to the first index of the char array. They both are char pointers, but only char[] will point to a locally allocated and mutable block of memory.
The memory for a & b is not allocated by you. The compiler is free to choose a read-only memory location to store the characters. So if you try to change it may result in seg fault. So I suggest you to create a character array yourself. Something like: char a[10]; strcpy(a, "Hello");
It seems like your question has been answered but now you might wonder why char *a = "String" is stored in read-only memory. Well, it is actually left undefined by the c99 standard but most compilers choose to it this way for instances like:
printf("Hello, World\n");
c99 standard(pdf) [page 130, section 6.7.8]:
The declaration:
char s[] = "abc", t[3] = "abc";
defines "plain" char array objects s and t whose elements are initialized with character string literals.
This declaration is identical to char
s[] = { 'a', 'b', 'c', '\0' }, t[] = { 'a', 'b', 'c' };
The contents of the arrays are modifiable. On the other hand, the declaration
char *p = "abc";
defines p with type "pointer to char" and initializes it to point to an object with type "array of char" with length 4 whose elements are initialized with a character string literal. If an attempt is made to use p to modify the contents of the array, the behavior is undefined.
You could also use strdup:
The strdup() function returns a pointer to a new string which is a duplicate of the string s.
Memory for the new string is obtained with malloc(3), and can be freed with free(3).
For you example:
char *a = strdup("stack overflow");
All are good answers explaining why you cannot modify string literals because they are placed in read-only memory. However, when push comes to shove, there is a way to do this. Check out this example:
#include <sys/mman.h>
#include <unistd.h>
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int take_me_back_to_DOS_times(const void *ptr, size_t len);
int main()
{
const *data = "Bender is always sober.";
printf("Before: %s\n", data);
if (take_me_back_to_DOS_times(data, sizeof(data)) != 0)
perror("Time machine appears to be broken!");
memcpy((char *)data + 17, "drunk!", 6);
printf("After: %s\n", data);
return 0;
}
int take_me_back_to_DOS_times(const void *ptr, size_t len)
{
int pagesize;
unsigned long long pg_off;
void *page;
pagesize = sysconf(_SC_PAGE_SIZE);
if (pagesize < 0)
return -1;
pg_off = (unsigned long long)ptr % (unsigned long long)pagesize;
page = ((char *)ptr - pg_off);
if (mprotect(page, len + pg_off, PROT_READ | PROT_WRITE | PROT_EXEC) == -1)
return -1;
return 0;
}
I have written this as part of my somewhat deeper thoughts on const-correctness, which you might find interesting (I hope :)).
Hope it helps. Good Luck!
You need to copy the string into another, not read-only memory buffer and modify it there. Use strncpy() for copying the string, strlen() for detecting string length, malloc() and free() for dynamically allocating a buffer for the new string.
For example (C++ like pseudocode):
int stringLength = strlen( sourceString );
char* newBuffer = malloc( stringLength + 1 );
// you should check if newBuffer is 0 here to test for memory allocaton failure - omitted
strncpy( newBuffer, sourceString, stringLength );
newBuffer[stringLength] = 0;
// you can now modify the contents of newBuffer freely
free( newBuffer );
newBuffer = 0;
char *a = "stack overflow";
char *b = "new string, it's real";
int d = strlen(a);
b = malloc(d * sizeof(char));
b = strcpy(b,a);
printf("%s %s\n", a, b);

Why does *(str+i) = *(str +j) not work here?

void reverse(char *str){
int i,j;
char temp;
for(i=0,j=strlen(str)-1; i<j; i++, j--){
temp = *(str + i);
*(str + i) = *(str + j);
*(str + j) = temp;
printf("%c",*(str + j));
}
}
int main (int argc, char const *argv[])
{
char *str = "Shiv";
reverse(str);
printf("%s",str);
return 0;
}
When I use char *str = "Shiv" the lines in the swapping part of my reverse function i.e str[i]=str[j] dont seem to work, however if I declare str as char str[] = "Shiv", the swapping part works? What is the reason for this. I was a bit puzzled by the behavior, I kept getting the message "Bus error" when I tried to run the program.
When you use char *str = "Shiv";, you don't own the memory pointed to, and you're not allowed to write to it. The actual bytes for the string could be a constant inside the program's code.
When you use char str[] = "Shiv";, the 4(+1) char bytes and the array itself are on your stack, and you're allowed to write to them as much as you please.
The char *str = "Shiv" gets a pointer to a string constant, which may be loaded into a protected area of memory (e.g. part of the executable code) that is read only.
char *str = "Shiv";
This should be :
const char *str = "Shiv";
And now you'll have an error ;)
Try
int main (int argc, char const *argv[])
{
char *str = malloc(5*sizeof(char)); //4 chars + '\0'
strcpy(str,"Shiv");
reverse(str);
printf("%s",str);
free(str); //Not needed for such a small example, but to illustrate
return 0;
}
instead. That will get you read/write memory when using pointers. Using [] notation allocates space in the stack directly, but using const pointers doesn't.
String literals are non-modifiable objects in both C and C++. An attempt to modify a string literal always results in undefined behavior. This is exactly what you observe when you get your "Bus error" with
char *str = "Shiv";
variant. In this case your 'reverse' function will make an attempt to modify a string literal. Thus, the behavior is undefined.
The
char str[] = "Shiv";
variant will create a copy of the string literal in a modifiable array 'str', and then 'reverse' will operate on that copy. This will work fine.
P.S. Don't create non-const-qualified pointers to string literals. You first variant should have been
const char *str = "Shiv";
(note the extra 'const').
String literals (your "Shiv") are not modifiable.
You assign to a pointer the address of such a string literal, then you try to change the contents of the string literal by dereferencing the pointer value. That's a big NO-NO.
Declare str as an array instead:
char str[] = "Shiv";
This creates str as an array of 5 characters and copies the characters 'S', 'h', 'i', 'v' and '\0' to str[0], str[1], ..., str[4]. The values in each element of str are modifiable.
When I want to use a pointer to a string literal, I usually declare it const. That way, the compiler can help me by issuing a message when my code wants to change the contents of a string literal
const char *str = "Shiv";
Imagine you could do the same with integers.
/* Just having fun, this is not C! */
int *ptr = &5; /* address of 5 */
*ptr = 42; /* change 5 to 42 */
printf("5 + 1 is %d\n", *(&5) + 1); /* 6? or 43? :) */
Quote from the Standard:
6.4.5 String literals
...
6 ... If the program attempts to modify such an array [a string literal], the behavior is undefined.
char *str is a pointer / reference to a block of characters (the string). But its sitting somewhere in a block of memory so you cannot just assign it like that.
Interesting that I've never noticed this. I was able to replicate this condition in VS2008 C++.
Typically, it is a bad idea to do in-place modification of constants.
In any case, this post explains this situation pretty clearly.
The first (char[]) is local data you can edit
(since the array is local data).
The second (char *) is a local pointer to
global, static (constant) data. You
are not allowed to modify constant
data.
If you have GNU C, you can compile
with -fwritable-strings to keep the
global string from being made
constant, but this is not recommended.

Resources