-1

Possible Duplicate:
Problem with processing individual strings stored in an array of pointers to multiple strings in C

Ok so I'm trying to change a char of a string to another char in C. The thing is, each string is an element of a 1D array so essentially all together its a 2D array because a string itself is an array of chars. Anyways I have a problem creating code to do this. Is it even possible to do this? Any help is appreciated.

Here's the code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main ()
{ 
int i, size;
char **a;

a=(char**)malloc(sizeof(char*));

printf("Enter the size of the array:");
scanf("%d", &size);

for(i=0;i<size;i++){
 a[i]=(char*)malloc(sizeof(char)*8);
}

a[3]="Read";


while(*(a[3])!='\0'){
 if(*(a[3]) == 'e'){
    *(a[3]) = 'r';
 }
}

 printf("%s\n", a[3]);

 system("pause");
 return 0;

}
1
  • What is the problem exactly? You didn't say. Do you get an error? Commented Apr 3, 2012 at 18:25

5 Answers 5

1
a=(char**)malloc(sizeof(char*));

printf("Enter the size of the array:");
scanf("%d", &size);

for(i=0;i<size;i++){
 a[i]=(char*)malloc(sizeof(char)*8);
}

Nope. You've allocated 1 char*. Then you treat it like it's size elements. You need to allocate size * sizeof(char*) bytes. (Note that this multiplication could also overflow.)

a[3]="Read";

Bad times. You are overwriting a[3] (which previously pointed to an allocation of 8 chars) with the location of a string literal, "Read". This leaks the previous allocation and also puts a non-modifiable string into a[3]. You should look into strncpy et al. for this.

Sign up to request clarification or add additional context in comments.

Comments

0

You didn't allocate enough space for a. Instead of

a=(char**)malloc(sizeof(char*));

you need

a=(char**)malloc(sizeof(char*)*size);

and obviously this must move to be after size has been read.

Once you sort that rather mundane problem out the fundamental problem is here:

a[3]="Read";

This makes the pointer a[3] point at a literal which cannot be modified. Instead you need to copy the contents of that literal into a[3]. Like this:

strcpy(a[3], "Read");

You must understand that a[3]=... assigns just the pointer a[3] and does not modify the string to which a[3] points.

Now, your code will obviously be in error if size is less than 4 since then a[3] would be out of bounds, but I guess a[3] is just transient while you debug this.

Your while loop is all wrong. Judging from your comments you want something like this:

char *p = a[3];
while (*p != '\0')
{
    if (*p == 'e')
        *p = 'r';
    p++;
}

No need to cast the return value of malloc in C, so remove the casts. sizeof(char) is always equal to 1 so you can remove that too.

9 Comments

Ok so I get that I didn't allocate enough memory space for the array and its elements but I have another problem. I have no idea how to replace chars of the string stored in say a[3], that's why I tried using the while loop which doesn't work.
Contrary, you're not supposed to be able to change a literal, but you in fact can using a pointer. It's not like it goes into read-only memory.
Doesn't work is no good to us. How can we help if that's all the info you give? That said, I pointed out in my answer that your string assignment was wrong. Use strcpy instead.
@OrgnlDave In fact, read-only memory is exactly where it goes, on typical systems. Modifying the contents of a literal is UB.
I encounter an infinite while loop
|
0

This:

a=(char**)malloc(sizeof(char*));

allocates space for one string. What you probably intend is something like:

char **a = NULL;
size_t number_of_strings = 8; /* for argument's sake */

a = malloc(number_of_strings * sizeof(char*));
if (!a) 
    return NOT_ENOUGH_MEMORY_ERROR;

At this point, you can dereference elements of a, e.g., a[3]. You'll still want to allocate space for those guys too:

char *staticStr = "Read";
a[3] = malloc(strlen(staticStr) + 1);
strncpy (a[3], staticStr, strlen(staticStr) + 1);

Start with that and see if rethinking how you're allocating memory will help you fix your other bugs.

Some notes:

  • You don't need to cast the result of malloc in C
  • You don't need to use sizeof(char) for allocating memory, which is always 1
  • You should be using a corresponding free() for each a[i] and for a itself, to prevent memory leaks

Comments

0

I see another problem, when you allocate memory for the:

a = (char **) malloc(sizeof(char *));

You are allocating memory for just one position, but you are using size positions. Then your code should be:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main ()
{ 
int i, size;
char **a;
char *ptr;



printf("Enter the size of the array:");
scanf("%d", &size);

 a=(char**)malloc(size * sizeof(char*));

for(i=0;i<size;i++){
 a[i]=(char*)malloc(sizeof(char)*8);
}

strcpy(a[3], "Read");

ptr=a[3];
while(*ptr!='\0'){
 if(*ptr == 'e'){
    *ptr = 'r';
 }
 ptr++;
}

 printf("%s\n", a[3]);

 system("pause");
 return 0;

}

and of course, you need to free the allocated memory.

In your while when you try to change the 'e' to 'r' you are always point to the same char. You need a new pointer to walk throw the array.

Comments

0

Your while loop doesn't do anything.

while(*(a[3])!='\0'){
 if(*(a[3]) == 'e'){
    *(a[3]) = 'r';
 }
}

It doesn't advance the pointer, it just keeps it at the first position.

A more proper-ish way would be to make a temporary pointer and use it to walk the string

char *temp = a[3];
while (*temp != '\0') {
  if (*temp == 'e') *temp = 'r';
  temp++;
}

11 Comments

I thought other people dealt with that pretty well. It doesn't matter, of course, because you can modify a literal. You shouldn't, you can't in debug mode, but it'll let you do it.
@DavidHeffernan I just built "char *a; a = "Hello!"; char *b = a; b[2] = 'b';" in Visual Studio 2010. Fault in debug mode, ran fine and even modified it in release. The proof is in the compiling.
@DavidHeffernan and I quote another StackOverflow comment, "Originally, the C89 (C90) standard did not outlaw modifying literals because there was too much code written before the standard that would be broken by it. Compilers can generate warnings. GCC 4.x does not have the -fwritable-strings option that GCC 3.x had, but GCC 3.x would warn about at least some attempts to modify strings. Writing const-correct code is harder than writing code which pays no attention to const, so people are apt to take the lazy route, still. " The standards, for backwards-compatibility, allow it
@DavidHeffernan I won't disagree that you shouldn't do it for 1,000 reasons. And also, in all C++ standards, they have never, ever been modifiable. But the fact remains that in C, you can. And other people already covered the topic of not modifying it. Should I copy-paste the answers into this? That's a real question - I'm not exactly an SO veteran. The real problem was worthless while loop - otherwise the code would've worked.
@DavidHeffernan I couldn't find an area of C99 that contradicted it, I'm not confusing anything. I wasn't spending a lot of time looking because I'm not asserting that you should do this or that it's even worth discussing. The point is you can. Have I hurt your pride or something? If it's in the C99 standard please cough it up, I'd like to expand my knowledge
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.