Change char by index [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 last year.
Trying to change char by index:
char *p = "test";
for (int i = 0; i < 4; ++i) {
p[i] = 50;
}
printf("%s\n", p);//test
What I'm doing wrong?

you cannot change a literal,
char*p="test";
doesnt copy the literal. You should do
char p[] = "test";
or
#include <string.h>
....
char *p = strdup("test");
if you want to deal with a pointer rather than a char array.

The line
char *p = "test";
will make the pointer p point to the string literal "test".
String literals are read-only. Attempting to modify them will invoke undefined behavior.
If you want "test" to be writable, then you must allocate (writable) memory for it, for example by declaring an array:
char arr[] = "test";
That line is equivalent to
char arr[5] = "test";
which creates an array of 5 characters and initializes the first 4 characters to "test" and initializes the 5th character to a null terminating character.
Now that you have allocated memory for the string, you can write to it at will, for example you could write:
for (int i = 0; i < 4; ++i) {
arr[i] = 50;
}
Or you could make a pointer p point to the array, and use the pointer for accessing the string, as you did in the code in the question:
char *p = arr;
for (int i = 0; i < 4; ++i) {
p[i] = 50;
}

Related

Bus error when dereferencing the same address [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 2 months ago.
I'm trying the squeeze program from K&R. However, I keep getting a bus error. The code below directly triggers the problem. Shouldn't this be portable?
int main() {
char* str = "foo";
for (int i = 0, j = 0; str[i]; ++i)
str[j] = '.';
}
The function from the book:
void squeeze(char s[], int c)
{
int i, j;
for (i = j = 0; s[i] != '\0'; i++)
if (s[i] != c)
s[j++] = s[i];
s[j] = '\0';
}
str points to a string constant. Such constants are read only, so attempting to modify them triggers undefined behavior which in your particular case manifests in the program crashing.
Instead, declare str as an array, which can be modified:
char str[] = "foo";

How to proprely modify a 2d array in C?

HI I'm getting a segfault with this code :
#include <stdio.h>
#include <stdlib.h>
int main()
{
char **array;
int i = 0;
array = (char **)malloc(sizeof(char *) * 20);
for (i = 0; i < 20; i++)
{
array[i] = (char *)malloc(sizeof(char *) * 20);
array[i] = "____________________";
}
array[0][0] = '2';
return(0);
}
What am I doing wrong ?
I'm very confused when I need to modify 2d arrays, what are my best options here ?
Thanks a lot.
You get a segfault because with array[i] = "____________________"; you let point each array[i] to a string literal. Note that you do not copy the contents of the literal but let array[i] directly point to it. Consequently, with array[0][0] = '2' you are altering a string literal then, which is undefined behaviour (very likely to become apparent as a segfault in this case).
Use strcpy(array[i],"____________________); instead.
BTW: write array[i] = malloc(sizeof(char) * (20+1)); (note the sizeof(char) instead of sizeof(char*) here and the +1 for the string termination character).

Why does this code produce a segmentation fault? [duplicate]

This question already has answers here:
Access violation error when reversing a string c++ [duplicate]
(1 answer)
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 9 years ago.
On line 18, I get a seg fault in the first iteration (i = 0).
#include <stdio.h>
int main(void) {
char* str = "mono";
int length = 0;
int i;
for (i = 0; ; i++) {
if (str[i] == '\0') {
break;
} else {
length++;
}
}
for (i = 0; i < length / 2; i++) {
char temp = str[length - i - 1];
str[length - i - 1] = str[i]; // line 18
str[i] = temp;
}
printf("%s", str);
return 0;
}
I wrote this algorithm to reverse a string.
You are modifying a string literal:
char* str = "mono";
and string literals are non-modifiable in C.
To fix your issue, use an an array initialized by the string literal:
char str[] = "mono";
Runtime Error:
char* str = "mono"; // str points to an address in the code-section, which is a Read-Only section
str[1] = 'x'; // Illegal memory access violation
Compilation Error:
const char* str = "mono"; // This is a correct declaration, which will prevent the runtime error above
str[1] = 'x'; // The compiler will not allow this
All Good:
char str[] = "mono"; // str points to an address in the stack or the data-section, which are both Read-Write sections
str[1] = 'x'; // Works OK
Notes:
In all cases, a string "mono" is placed in the code-section of the program.
In the last example, the contents of that string are copied into the str array.
In the last example, the str array is located in the stack if str is a non-static local variable, and in the data-section of the program otherwise.

Initialize array of characters using pointers

This problem is driving me crazy, I'm sure I'm missing something. I need to initialize an array of chars using only pointers. Below is the code I have so far:
int p2(){
/* Implements problem 2 of lab */
// Create an array
char **s = (char**)malloc( 11 *sizeof(char));
char *p = *s;
char start ='A';
while( p != s+10){
*p = start;
start++;
p++;
}
return(0);
}
The problem I'm having is I don't know how to address the characters inside of the array. I understand the base address of the array is **s, and the pointer to the first element is *s. What I don't understand is how to get to **s+10 (i.e. the end of the array).
Can anyone shine some light for me??? Please!
EDIT: Ok, looks like I misunderstood the question. I appears I need to create an array of strings (thus the char ** allocation). Then I need to loop through this array, and assign each string (i.e. char *) a value 15 chars long. Please let me know if I'm understanding this correctly:
char **strings ==> strings[0 ... n ] where each element is a pointer to a char (possibly an array). There for *string ==> strings[0], *(string+1) = strings[1], etc etc.
Am I close or way off?
char **s is 2 dimensional array of characters, or array of C strings if you want.
If you want to use array of characters you should use:
char *string = (char*)malloc( 11 *sizeof(char));
If you really want to initialize array of strings, at first step you're initializing array of pointers, that's:
char **s = (char**)malloc( 11 *sizeof(char *));
Please note that I'm using char * inside sizeof. Than when you may use strings, but at first you must initialize each string.
s[0] = (char*) malloc( 15*size(char)); // This is actually string, 14 characters long (NULL terminated)
char *p = s[0]; // p is pointer to beginning of your string now
And there's two way how to address your string:
s[0][3] // 4th character of your string
p[3]
Or if you want to use just pointers:
char *p = *(s+0);
*(p+3); // 4th character
*((*(s+0))+3) // To do it "hardcore"
EDIT: added an example
When you have **char p and use p++ or p + 1, C increases memory address. *p operator tells compiler that you now want to work with data stored in memory, not with pointer. Therefor those two syntax do the same:
p[10] = 'a';
*(p+10) = 'a';
So if you want traverse both your dimensions, you should use:
for( int i = 0; i < 11; i++){
char *p = *(s+i);
for( int j = 0; j < 10; j++){
*(p + j) = 'a'; // Say you wanna fill them with as
}
// You may also use this syntax:
while( p < (*(s+i) + 10)){ // or use != instead of <
*p = 'a';
p++;
}
}
I think you meant this:
char *s = (char*) malloc(11 *sizeof(char));
char *p = s;
In which case you'd address the characters with s[x]
First, you don't need a char ** unless you need an array of arrays.
Second, you can get to the end of the array with (*s)[10] or *((*s)+10)
Third, in C programming, don't cast the result of malloc()
The code is falling apart here.
char **s = (char**)malloc( 11 *sizeof(char));
You're allocating enough memory for 11 chars, which sounds like what you want to do.
However, you're casting the address to those 11 chars to a (char**) as if you were allocating space for pointers, not chars.
Why should you use a double pointer for creating an array of chars?
char *s = (char *) malloc(10 * sizeof(char));
char *start = s; // save starting pointer
for(; s < start+10; s++)
*s = 'a';
return 0;
If you allocate char ** essentially you're allocating an array of pointers to char(eg. array of strings). If you need char array, allocate char array. If you start working with pointers a design of stack and heap can be really helpful.

C101--string vs. char:

AFunc changes what was sent to it, and the printf() outputs the changes:
void AFunc ( char *myStr, int *myNum )
{
*myStr = 's';
*myNum = 9;
}
int main ( int argc, char *argv[] )
{
char someString = 'm';
int n = 6;
AFunc(&someString, &n);
printf("%c" "%d", someString, n);
}
But what if the string was more than one char? How would the code look differently? Thanks for any help.
If it were a "string" instead of a char, you would do something like this:
#include <stdio.h>
void AFunc (char *myStr, int *myNum) {
myStr[0] = 'p'; // or replace the lot with strcpy(myStr, "pax");
myStr[1] = 'a';
myStr[2] = 'x';
myStr[3] = '\0';
*myNum = 9;
}
int main (void) {
char someString[4];
int n = 6;
AFunc(someString, &n);
printf("%s %d", someString, n);
return 0;
}
which outputs:
pax 9
A "string" in C is really an array of characters terminated by the \0 (NUL) character.
What the above code does is to pass in the address of the first character in that array and the function populates the four characters starting from there.
In C, a pointer to char isn't necessarily a string. In other words, just because you have char *x;, it doesn't mean that x is a string.
To be a string, x must point to a suitably allocated region which has a 0 in it somewhere. The data from the first character that x points to and up to the 0 is a string. Here are some examples of strings in C:
char x[5] = {0}; /* string of length 0 */
char x[] = "hello"; /* string of length 5, the array length being 6 */
char *x = "hello"; /* string of length 5. x is a pointer to a read-only buffer of 6 chars */
char *x = malloc(10);
if (x != NULL) {
strcpy(x, "hello"); /* x is now a string of length 5. x points
to 10 chars of useful memory */
}
The following are not strings:
char x[5] = "hello"; /* no terminating 0 */
char y = 1;
char *x = &y; /* no terminating 0 */
So now in your code, AFunc's first parameter, even though is a char * isn't necessarily a string. In fact, in your example, it isn't, since it only points to a memory that has one useful element, and that's not zero.
Depending upon how you want to change the string, and how the string was created, there are several options.
For example, if the myStr points to a writable memory, you could do something like this:
/* modify the data pointed to by 'data' of length 'len' */
void modify_in_place(char *data, size_t len)
{
size_t i;
for (i=0; i < len; ++i)
data[i] = 42 + i;
}
Another slightly different way would be for the function to modify data until it sees the terminating 0:
void modify_in_place2(char *data)
{
size_t i;
for (i=0; data[i]; ++i)
data[i] = 42 + i;
}
You are only dealing with chars and char pointers. None of the char pointers are valid strings as they are not null terminated.
Try defining a string and see what it looks like.
But what if the string was more than one char? How would the code look
differently? Thanks for any help
Ofcourse, you would modify the other characters as well, but in the exact same way you did the first time.
Declare a char array and pass its address
Modify values at those address
A char array would be a more clear term for a string.

Resources