compiler does not allow me to edit the passed string [duplicate] - c

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 5 years ago.
I looked around and I could not find a solution of my problems in other question. For some reason, then I get segmentation fault when I run my program and it seems to be because i am changing the give string. I tried passing a pointer to a char pointer and edit that, but to no avail.
what I get:
before: juanpablo
Segmentation fault (core dumped)
My code:
void rm_char(char* word, int pos){
printf("before: %s\n", word);
int len = strlen(word);
int i;
i = pos;
while(word[i+1] != '\0'){
word[i] = word[i+1];
i++;
}
word[i] = '\0';
printf("after: %s\n", word);
}
int main(void){
rm_char("juanpablo", 2);
}

From the C Standard (6.4.5 String literals)
7 It is unspecified whether these arrays are distinct provided their
elements have the appropriate values. If the program attempts to
modify such an array, the behavior is undefined.
To escape the error you could call the function like
char s[] = "juanpablo";
rm_char( s, 2 );
Take into account that it is better to use type size_t instead of the type int for the second parameter and the variable len declared like
int len = strlen(word);
is not used in the function.
The function should be declared like
char * rm_char(char* word, size_t pos);
Here is a demonstrative program
#include <stdio.h>
#include <string.h>
char * rm_char(char *word, size_t pos)
{
size_t n = strlen( word );
if ( pos < n )
{
//memmove( word + pos, word + pos + 1, n - pos );
do
{
word[pos] = word[pos+1];
} while ( word[pos++] );
}
return word;
}
int main(void)
{
char word[] = "juanpablo";
puts( word );
puts( rm_char( word, 2 ) );
return 0;
}
Its output is
juanpablo
junpablo

Related

C Program to print string from commandline in reverse [duplicate]

This question already has answers here:
Reversing a string in C
(27 answers)
Closed 2 years ago.
/* Pgm to print string from commandline and reverse it */
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
int main(int argc, char *argv[]) {
if(argc<1){
perror("Not enough arguments");
}
// Printing the string
for(int i=1; i<argc ; i++){
printf("%s\n",argv[i]);
}
//Part to print the string in reverse
char *arr = (char*) malloc(sizeof(argv[1])+1); // +1 for the NULL terminator
strcpy(arr,argv[1]);
char *str = (char*) malloc(sizeof(argv[1])+1); //buffer array
//Reverse part begins
int j=0;
for(int i= sizeof(argv[1]); i>=0 ; i--){
str[j] = arr[i];
j++;
}
for(int j=0;j<sizeof(argv[1]);j++){ // Printing the reverse string
printf("R=%s\n",&str[j]);
}
free(arr);
free(str);
return 0;
}
This program is expected to print the text from argv[1] on commandline in reverse order. But the output I get is weird.
output
user#DESKTOP-KI53T6C:/mnt/c/Users/user/Documents/C programs$ gcc linex.c -o linex -Wall -pedantic -std=c99
user#DESKTOP-KI53T6C:/mnt/c/Users/user/Documents/C programs$ ./linex hello
hello
R=
R=
R=
R=
R=olleh
R=lleh
R=leh
R=eh
Also when the input is above a certain number of characters, it automatically truncates it:
user#DESKTOP-KI53T6C:/mnt/c/Users/user/Documents/C programs$ ./linex strcmpppssdsdssdsd
strcmpppssdsdssdsd
R=spppmcrts
R=pppmcrts
R=ppmcrts
R=pmcrts
R=mcrts
R=crts
R=rts
R=ts
All I want is the output to be : 'olleh' when I type 'hello'
The expression argv[1] has the type char *. That is it is a pointer. sizeof( char * ) that is equivalent to the expression sizeof( argv[1] ) is equal to 4 or 8 depending on the used system.
So for example in this line
char *arr = (char*) malloc(sizeof(argv[1])+1);
there are allocated not enough memory to store a string pointed to by the pointer argv[1]. Instead of the expression sizeof( argv[1] ) you need to use expression strlen( argv[1] ).
Also to output a string in the reverse order there is no any need to allocate dynamically a character array. This is just a bad idea.
Here is a demonstrative program that shows how to output a string in the reverse order.
#include <stdio.h>
#include <string.h>
int main(void)
{
const char *s = "Hello";
for ( size_t i = strlen( s ); i != 0; )
{
putchar( s[--i] );
}
putchar( '\n' );
return 0;
}
The program output is
olleH
If you want not just to output a string in the reverse order but to create a new string in the reverse order then what you need is to write a function that performs copying of a string stored in one character array into another character array.
Here is a demonstrative program.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * copy_reverse( char *s1, const char *s2 )
{
size_t n = strlen( s2 );
s1[n] = '\0';
while ( *s2 ) s1[--n] = *s2++;
return s1;
}
int main(void)
{
const char *s1 = "Hello";
char *s2 = malloc( strlen( s1 ) + 1 );
if ( s2 ) puts( copy_reverse( s2, s1 ) );
free( s2 );
return 0;
}
The program output is the same as shown above
olleH

Segmentation Fault when using strtok

I get segmentation fault when using char *s in main. If I use char s[100] or something like that everything is ok. Why is that? SIGSEGV appears when i call find_short(char *s) function on line with instruction char *token = strtok(s, delim);. This is my code:
#include <sys/types.h>
#include <string.h>
#include <limits.h>
#include <stdio.h>
int find_short(char *s)
{
int min = INT_MAX;
const char delim[2] = " ";
char *token = strtok(s, delim);
while(token != NULL) {
int len = (int)strlen(token);
if (min > len)
min = len;
token = strtok(NULL, delim);
}
return min;
}
int main()
{
char *s = "lel qwew dasdqew";
printf("%d",find_short(s));
return 0;
}
The line:
char *s = "lel qwew dasdqew";
creates a pointer to a constant string in memory.
Because that string is constant, you are unable to change its contents.
The strtok function will try to modify the contents by inserting \0 at the token-delimiter locations, and will fail because the string cannot be modified.
Changing the line to:
char s[] = "lel qwew dasdqew";
Now makes s an array of local data that you are free to change. strtok will now work because it can change the array.
The main your mistake is that you selected a wrong function to do the task.:)
I will say about this below.
As for the current program then string literals in C though they do not have constant character array types are immutable. Any attempt to change a string literal results in undefined behavior. And the function strtok changes passed to it string inserting the terminating zero between sub-strings.
Instead of the function strtok you should use string functions strspn and strcspn. They do not change the passed argument. So using these functions you are able to process also string literals.
Here is a demonstrative program.
#include <stdio.h>
#include <string.h>
size_t find_short( const char *s )
{
const char *delim= " \t";
size_t shortest = 0;
while ( *s )
{
s += strspn( s, delim );
const char *p = s;
s += strcspn( s, delim );
size_t n = s - p;
if ( shortest == 0 || ( n && n < shortest ) ) shortest = n;
}
return shortest;
}
int main(void)
{
const char *s = "lel qwew dasdqew";
printf( "%zu", find_short( s ) );
return 0;
}
Its output is
3

passing a char* as argument breaks program whereas char[] does not [duplicate]

This question already has answers here:
What is the difference between char s[] and char *s?
(14 answers)
Definitive List of Common Reasons for Segmentation Faults
(1 answer)
Closed 5 years ago.
I have the following code to split strings by tokens:
char **strToWordArray(char *str, const char *delimiter)
{
char **words;
int nwords = 1;
words = malloc(sizeof(*words) * (nwords + 1));
int w = 0;
int len = strlen(delimiter);
words[w++] = str;
while (*str)
{
if (strncmp(str, delimiter, len) == 0)
{
for (int i = 0; i < len; i++)
{
*(str++) = 0;
}
if (*str != 0) {
nwords++;
char **tmp = realloc(words, sizeof(*words) * (nwords + 1));
words = tmp;
words[w++] = str;
} else {
str--;
}
}
str++;
}
words[w] = NULL;
return words;
}
If I do this:
char str[] = "abc/def/foo/bar";
char **words=strToWordArray(str,"/");
then the program works just fine but if I do this:
char *str = "abc/def/foo/bar";
char **words=strToWordArray(str,"/");
then I get a segmentation fault.
Why is that? The program expects a char* as an argument then why does a char* argument crash the program?
Because the function contains:
*(str++) = 0;
which modifies the string that was passed to it. When you do:
char *str = "abc/def/foo/bar";
str points to a read-only string literal. See the section titled Attempting to modify a string literal in this question:
Definitive List of Common Reasons for Segmentation Faults

Segmentation Fault with Direct Memory Access [duplicate]

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 8 years ago.
The following code results in a seg fault, when running in GDB it appears when the memory is changed to decrease the character by 32.
#include <stdio.h>
char *upper(char *);
int main(void) {
char *my_word = "hello";
printf("Upper: %s\n", upper(my_word));
return 0;
}
char *upper(char *string) {
while(*string != '\0') {
*string -= 32;
string++;
}
return string;
}
When you use string++ at the end it will point to \0.
char *upper(char *string) {
while(*string != '\0') {
*string -= 32;
string++; // don't use this method here
}
return string; // it will return the address of \0
}
while returning it will return the address of \0. so it wont print anything.
Try the following changes-
#include <stdio.h>
#include<string.h>
char *upper(char *);
int main(void) {
char my_word[] = "hello";
printf("Upper: %s\n", upper(my_word));
return 0;
}
char *upper(char *string) {
int i;
for(i=0;string[i];i++)
string[i] -=32;
return string;
}

Reverse a string of any length using pointers in C [duplicate]

This question already has answers here:
How do you reverse a string in place in C or C++?
(21 answers)
How to read unlimited characters in C
(3 answers)
Closed 9 years ago.
I was just browsing through some interview questions and found this code to reverse a string using pointers. But I see that here they have defined char string[100] which limits the string length. I am not so good at C. How do I modify the same to make it a string of any length?
#include<stdio.h>
int string_length(char*);
void reverse(char*);
main()
{
char string[100];
printf("Enter a string\n");
gets(string);
reverse(string);
printf("Reverse of entered string is \"%s\".\n", string);
return 0;
}
void reverse(char *string)
{
int length, c;
char *begin, *end, temp;
length = string_length(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--;
}
}
int string_length(char *pointer)
{
int c = 0;
while( *(pointer+c) != '\0' )
c++;
return c;
}
Instead of static array use dynamic memory allocation: char *tab = malloc(n * sizeof(char)) where n is some variable representing desired length.
You can use malloc() for this purpose if you want the size to be decided/inputted by the user at runtime.
malloc()
Dynamic memory allocation is the solution..
Take a pointer to the string and allocate the memory dynamically.. this allocates at run time..
This will solve your problem..
char *str;
str = (char*)malloc(n *sizeof(char));
NOTE: typecasting is optional in C and 'n' here is the required length.(can be user input).

Resources