Reversing a string with and without Dynamic Memory [duplicate] - c

This question already has answers here:
Why is this string reversal C code causing a segmentation fault? [duplicate]
(8 answers)
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 2 years ago.
int length(char *);
char* reverse(char *);
int main()
{
int a;
char p;
a=length("Computer");
printf("%d", a);
printf("\nReverse : %s", reverse("Computer"));
getch();
return 0;
}
int length(char *p)
{
int i;
for(i=0;*(p+i)!='\0'; i++);
return(i);
}
char* reverse(char *p)
{
int len, i;
char temp;
for(len=0; *(p+len)!='\0'; len++);
for(i=0; i<len/2; i++)
{
temp=*(p+i);
*(p+i)=*(p+len-1-i);
*(p+len-1-i)=temp;
}
return(p);
}
I am trying to print the length of the string inputted without using strlen() function and also creating a user defined function using pointer and function to reverse a string without using strrev() function. After compilation the program doesn't throws an error but it just does not display anything. The length is being printed correctly but the reverse section is not being printed and I can't figure out why? Help me out here people.

first of all, as user3121023 said, string constants (or literals) cannot be modified.
The problem was with indexes, pointer and at the end the piece of code that reverse the string. I adjust it in certain points and I'm gonna attach you here:
#include <stdio.h>
#include <stdlib.h>
int length(char *);
char * reverseWithDynamicMemory(char *, int);
char * reverseWithoutDynamicMemory(char *, int, char *);
int main() {
char *pWord = "Computer";
int wordLength = length(pWord);
char reverseWordWithouDynamicMemory[wordLength];
printf("Word Lenght: %d\n", wordLength);
printf("\nReverse with Dynamic Memory: %s\n", reverseWithDynamicMemory(pWord, wordLength));
printf("Reverse without Dynamic Memory: %s\n\n", reverseWithoutDynamicMemory(pWord, wordLength, reverseWordWithouDynamicMemory));
return 0;
}
int length(char *pWord) {
int i;
for (i = 0; *(pWord + i) != '\0'; i++);
return i;
}
char * reverseWithDynamicMemory(char *pWord, int length) {
int i = 0, end = length - 1;
char *reverseWord = (char *) malloc(sizeof(char) * length);
if(!reverseWord) {
printf("\nError allocating memory for reverseWord...\n");
exit(EXIT_FAILURE);
}
while (i < end || end >= 0) {
reverseWord[i] = pWord[end];
end--;
i++;
}
reverseWord[length] = '\0';
return reverseWord;
}
char * reverseWithoutDynamicMemory(char *pWord, int length, char *reverseWord) {
int i = 0, end = length - 1;
while (i < end || end >= 0) {
reverseWord[i] = pWord[end];
end--;
i++;
}
reverseWord[length] = '\0';
return reverseWord;
}
Some useful tips:
There was an implicit declaration of function 'getch' which is invalid in C99
Unused variable 'p'
Use more descriptive names
I've created a variable with dynamic memory inside the function reverse. Otherwise address of stack memory associated with local variable 'reverseWord' is returned.
Best regards,
Denny

Related

Modifying an array makes printf unusable [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 12 days ago.
I am trying to make an array of modifiable length, i defined a function called "add" that should add a char to the last of the array, but this result in putchar and printf not working. Why is this happening? and how can i fix it?
the output should be "hix", and the output is apparently ""
#include <stdio.h>
typedef struct
{
char* ptr;
size_t len;
}
bytes;
void add(bytes text, char chr)
{
text.ptr[text.len++] = chr;
}
bytes parse(char text[])
{
size_t index = 0;
while (text[index]) ++index;
return (bytes) {text, index};
}
void print(bytes text)
{
for (size_t index = 0; index < text.len; ++index)
{
putchar(text.ptr[index]);
}
}
int main()
{
bytes str = parse("hi");
add(str, 'x'); // if i remove this line "print" works, but only prints "hi"
print(str);
return 0;
}
When you try to modify string literal you will get memory overflow allocation problem.
So Your final code with allocation memory to sort the problem of Segmentation fault (core dumped)
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char * ptr;
size_t len;
}
bytes;
void add(bytes * text, char chr) {
text -> ptr[text -> len++] = chr;
}
bytes parse(char text[]) {
size_t index = 0;
char * new_ptr = NULL;
while (text[index]) ++index;
new_ptr = (char * ) malloc(index + 1);
if (new_ptr == NULL) {
printf("Memory allocation failed!\n");
exit(1);
}
for (int i = 0; i < index; i++) {
new_ptr[i] = text[i];
}
new_ptr[index] = '\0';
return (bytes) {
new_ptr,
index
};
}
void print(bytes text) {
for (size_t index = 0; index < text.len; ++index) {
putchar(text.ptr[index]);
}
}
int main() {
bytes str = parse("hi");
add( & str, 'x');
print(str);
free(str.ptr);
return 0;
}
Result :
hix
You can check by compile this code on C compiler

String returned from function contains garbage [duplicate]

This question already has answers here:
Returning an array using C
(8 answers)
Closed 3 years ago.
I want the function lch() to return a string that can be used outside the function.
This is the code I have written, but it does not seem to work:
char *lch(char *ch,int n){
char c[n];
for(int i=0;i<n;i++){
c[i] = *ch;
}
puts(c); // check output string inside function
return c;
}
char str[100],*p;
main(){
p = lch("a",20);
puts(p); // check output outside function
}
I am confused with strings and how they should be passed to functions.
I want the output string to become the same on both calls to puts().
What should I do?
That is the result of the code above:
aaaaaaaaaaaaaaaaaaaa // inside the function
        ¢ÞêÊ· // outside the function
First of all, returning locally allocated storage will not work. You have to return dynamically allocated storage, and with a proper size to accommodate the null-terminator:
char *c = malloc(n+1);
/* ... */
/* end of program: */
free(p);
Second, you want to pass a character to your function, not a string:
char *lch(char ch,int n){
/* ... */
c[i] = ch;
/* ... */
p = lch('a', 20);
Third, you have to null-terminate your string:
int i;
for(i=0;i<n;i++){
c[i] = ch;
}
ch[i] = '\0';
puts(c); //check output string inside function
Here's the dynamically-allocated storage approach:
#include <stdlib.h>
#include <stdio.h>
char *lch(char ch,int n){
char *c = malloc(n+1);
int i;
for(i=0;i<n;i++){
c[i] = ch;
}
c[i] = '\0';
puts(c); //check output string inside function
return c;
}
char *p;
int main(void){
p = lch('a',20);
puts(p); //check output outside function
free(p);
return 0;
}
This also fixes the declaration and return type of main (main is supposed to be int main(void) or int main(int argc, char **argv)), removes the unneeded variable str, and adds needed #includes.
The reason your code does not do what you expect it to do is because the string in the function is allocated on the stack, which means that its memory is cleaned as soon as you exit the function.
That means the pointer p points to garbage value after the call to lch().
Also, you can not declare an array of size that is not a constant value, so the line:
char c[n];
would simply not work.
To solve this, you will need to dynamically allocate the string using malloc(3) :
char* lch(char ch, int n)
{
char * c;
/* Allocate n bytes of memory for the string */
c = malloc(n + 1);
if (NULL == c)
{
/* Failed to allocate memory, exit the function */
return c;
}
for(int i = 0; i < n; i++)
{
c[i] = ch;
}
/* Add a terminating null byte (to make it a string) */
c[i] = '\0';
puts(c);
return c;
}
int main(void)
{
char * p;
p = lch('a', 20);
puts(p);
/* Free the string from the memory */
free(p);
return 0;
}
I added a few fixes to the code but the main thing you need to look at is the use of malloc(3).
I dynamically allocated n+1 bytes of memory for the string, then wrote the data into the string (plus a '\0'), and when the function exits the memory will still be available and wont be corrupted.
The call to free is needed to free the memory we have allocated.
You can read more about malloc(3) here: https://linux.die.net/man/3/malloc

C structs, strings and segmentation faults [duplicate]

This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 5 years ago.
So this is supposed to be a concordance program where it grabs words from a text file. I'm trying to use a struct to store the string, and also the number of times the word occurs in the text file. I also want to place the struct object into an array of structs, because I will need to sort the words alphabetically once I have them all. However, I'm getting a segmentation fault inside my createStruct function. I know the problem is with my limited knowledge of pointers and passing by reference. I've been messing with createStruct and compareStruct for days now and it just isn't clicking.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef struct word{
char *wordArr;
int wordCount;
}word;
char *makeLowerCase(char word[]);
char *removeFirstChar(char word[]);
char *removeLastChar(char word[]);
void createStruct(struct word wordObj, char word[]);
void structCompare(struct word wordObj, struct word objArr[]);
int main(int argc, char * argv []) {
char buff[] ="##Hello$$$$$"; //hard coded, will grab words from a .txt file
struct word newWord = {.wordArr = NULL, .wordCount = 0};
struct word structArray[500];
makeLowerCase(buff);
removeFirstChar(buff);
removeLastChar(buff);
createStruct(newWord, buff);
structCompare(newWord, structArray);
//trying to print from the array
printf("%s %d", structArray->wordArr, structArray->wordCount);
return 0;
}
char *makeLowerCase(char grabbedWord[]) {
int i;
size_t wordLength = strlen(grabbedWord);
for(i = 0; i < wordLength; i++) {
grabbedWord[i] = tolower(grabbedWord[i]);
}
return grabbedWord;
};
char *removeFirstChar(char inputWord[]) {
int i = 0;
size_t length = strlen(inputWord);
if (!isalnum(inputWord[i])) {
i++;
strncpy(inputWord, &inputWord[i], length);
return removeFirstChar(inputWord);
}
return inputWord;
};
char *removeLastChar(char inputWord[]) {
size_t length = strlen(inputWord);
if (!isalnum(inputWord[length - 1])) {
inputWord[length - 1] = 0;
return removeLastChar(inputWord);
}
return inputWord;
};
void createStruct(struct word wordObj, char string[]) {
strcpy(wordObj.wordArr, string);
wordObj.wordCount = 1;
};
void structCompare(struct word obj, struct word structArr[]) {
int i;
for(i = 0; i < sizeof(structArr); i++) {
if(structArr[i].wordCount == 0) {
strcpy(structArr[i].wordArr, obj.wordArr);
structArr[i].wordCount = obj.wordCount;
}
else if(strcmp(structArr[i].wordArr, obj.wordArr) == 0) {
structArr->wordCount++;
}
else {
strcpy(structArr[i].wordArr, obj.wordArr);
structArr[i].wordCount = obj.wordCount;
}
}
};
You get a segmentation fault because of a NULL pointer.
For copying a string, you use strcpy(char *dest, char *src). But the dest needs to be allocated. In your case, is just NULL;
So this is what you need to do:
// Add a \0 to the end of a string so you know when to stop.
char buff[] ="##Hello$$$$$\0";
// Allocate the char array so you know where to copy it. I allocate it by default to 500, change this based on your needs.
struct word newWord = {.wordArr = (char *)malloc(sizeof(char) * 500), .wordCount = 0};
If you pass the struct to a function directly, you will pass a copy of it so any change done in the function, will not be seen outside of the function. So you need to pass a pointer to the struct instead of the actual struct.

Converting string from lowercase to uppercase seg fault [duplicate]

This question already has answers here:
Memory access violation. What's wrong with this seemingly simple program?
(7 answers)
Closed 5 years ago.
I am trying to convert a string that has been passed to this function from lowercase to uppercase. I keep getting a seg fault, and cannot determine why.
void uppercase(char* input)
{
int str_size = strlen(input);
char *string = input;
for (int i = 0; i < str_size; i++)
{
string[i] += -32;
printf("%c", string[i]);
}
return;
}
Function calling the function uppercase:
#include <stdio.h>
#include <string.h>
int main(void)
{
uppercase("max");
return(0);
}
The string that you are passing is a literal possibly present in read-only memory (since it is a string literal which is a constant) which you aren't allowed to modify. Hence the error.
Store the string in a character array and then pass that to the function.
char str[]="max";
uppercase(max);
http://www.geeksforgeeks.org/storage-for-strings-in-c/
https://softwareengineering.stackexchange.com/questions/294748/why-are-c-string-literals-read-only
As #dasblinkenlight said, you cannot modify a string literal.
Try this instead:
int main(void)
{
char str[4] = "max";
uppercase(str);
return(0);
}
Or you can also malloc a string and pass it in.
You cannot pass string literals as an argument to the function. try storing it first in array and then pass it to the function.
#include <stdio.h>
#include <string.h>
void uppercase(char* input)
{
int str_size = strlen(input);
char *string = input;
for (int i = 0; i < str_size; i++)
{
string[i] += -32;
printf("%c", string[i]);
}
return;
}
int main(void)
{
char str[]="max";
uppercase(str);
return(0);
}

imitate strcpy function in c using char pointers

I am try to write a user defined function which will do exactly what strcpy() library function do. But although there is no error, my program crashes and not copying second string to first string. What's wrong with this code and how to fix it?
#include<stdio.h>
#include<string.h>
int main(){
char *ch1="abcd";
char *ch2="efgh";
str_cpy(ch1,ch2);
}
str_cpy(char *c1,char *c2){
int i=0;
while(c1[i]!='\0'){
i++;
}
printf("%c",*(c1+3));
int k;
for(k=0;k<=i;k++){
*(c1+k)=*(c2+k);
}
}
String literals are generally put into read only area, that's why the program crashed when you are writing into c1. The destination string needs to be an array or allocated buffer:
char c1[5];
str_cpy(c1, c2);
Also, in the function, it looks you are copying c2 to c1, but you are counting the length of c1, you should count the length of c2 instead:
// copy string c2 to c1
void str_cpy(char *c1, const char *c2){
int i=0;
while(c2[i]!='\0'){
i++;
}
int k;
for(k=0;k<=i;k++){
*(c1+k)=*(c2+k);
}
}
Your program invokes undefined behavior because you are trying to write to a string literal. String literals can be stored in read only memory, which is probably the case on your system, hence causing a crash.
Note that your string copying function can perform the copy in a single loop:
char *str_cpy(char *c1, const char *c2) {
for (int i = 0;; i++) {
c1[i] = c2[i];
if (c1[i] == '\0')
return c1;
}
}
You can verify the behavior with a modified main:
#include <stdio.h>
char *str_cpy(char *c1, const char *c2) {
for (int i = 0;; i++) {
c1[i] = c2[i];
if (c1[i] == '\0')
return c1;
}
}
int main(void) {
char buf[20];
char *ch2 = "Hello world\n";
printf("%s\n", str_cpy(buf, ch2));
return 0;
}
Here is a possible rework of your code, which doesn't have to pre-define buffer size (c1). You simply pass the buffer address. Also, please note that such buffer has to be freed once used (for example, if declared in local scope, not in main()):
#include <stdio.h>
#include <stdlib.h>
char *str_cpy(char **c1, const char *c2) {
int i, size = 0;
for(i = 0; ; i++)
if(c2[i] == '\0')break;
size = i + 1;
if(!(*c1 = realloc(*c1,size*sizeof(char))))
return *c1;//or devise some more sophisticated error handling
for (i = 0;; i++) {
(*c1)[i] = c2[i];
if (c2[i] == '\0')
return *c1;
}
}
int main(void){
char *ch1 = malloc(1); //you're responsible for freeing it, once used
char *ch2 = "Hello, everybody in the neighborhood!";
printf("%s\n",str_cpy(&ch1,ch2));
free(ch1);
return 0;
}
Please, also note you don't need to #include <string.h>

Resources