an array of char pointers in c - c

I want to use an array of char pointers where each pointer in the array is pointing to a char in another char array, therefore, I would be able to print the char array through the pointers.
char city[14] = {'D', 'u', 'b', 'a', 'i'};
char *charPointers[100] = {0};
for(size_t i = 0;city[i] != '\0'; i++)
charPointers[i] = &city[i];
printf("\ncity = ");
for(size_t i = 0; *charPointers != 0; i++)
//printf("%c", *(charPointers[i]));
putchar(*charPointers[i]);
Is charPointers an array of pointers or simply a string ?
If it's a string, then how can I use an array of pointers such that each pointer is pointing to a char?
What's an elegant way to achieve what I want? (preferably using pointer arithmetic)

charPointers is an array of pointers; it is categorically not simply a string.
Since it isn't a string, your second question is moot.
Your loop condition is incorrect; you need to write:
for (size_t i = 0; charPointers[i] != 0; i++)
//printf("%c", *(charPointers[i]));
putchar(*charPointers[i]);
putchar('\n');
You're testing whether the first pointer is null; it isn't. You need to check the current pointer on each iteration. The loop below might help you understand what's going on, too:
for (size_t i = 0; charPointers[i] != 0; i++)
printf("%zd [%s]\n", i, charPointers[i]);
This code:
#include <stdio.h>
int main(void)
{
char city[14] = {'D', 'u', 'b', 'a', 'i'};
char *charPointers[100] = {0};
for(size_t i = 0;city[i] != '\0'; i++)
charPointers[i] = &city[i];
printf("city = ");
for (size_t i = 0; charPointers[i] != 0; i++)
putchar(*charPointers[i]);
putchar('\n');
for (size_t i = 0; charPointers[i] != 0; i++)
printf("%zd [%s]\n", i, charPointers[i]);
return 0;
}
produces this output:
city = Dubai
0 [Dubai]
1 [ubai]
2 [bai]
3 [ai]
4 [i]

charPointer is an array of pointers to char. A pointer to an array of char would be char (*p)[100];.
Your code is near correct, here is the not-segfaulting version :
char city[14] = {'D', 'u', 'b', 'a', 'i', '\0'};
char* charPointers[100] = {0};
size_t i =0;
for(i = 0; city[i] != '\0'; i++)
charPointers[i] = city + i;
charPointers[i] = city + i; // Don't forget to add the \0 at the end !
printf("\ncity = ");
for(i = 0; *charPointers[i] != '\0'; i++)
printf("%c", *charPointers[i]);
I don't really know what you want to do, but the code above is storing a pointer to each character of the string city in each element of charPointers.
However, if you want to store a pointer to existing string in charPointers (for instance, each element of charPointers points to a city name), here would be the correct code:
char* cityNames[NB_CITY];
char* city = "Dubai";
cityNames[0] = city;
printf("%s\n", cityNames[0]); // gives "Dubai"

charPointers is clearly an array of pointers to characters. The array city is a string (as pointed out in a comment) since you've specified a length of 14 but only provided 5 actual characters. The rest are set to zero which will terminate the string.
A much clearer way to get the same result would be:
const char *city = "Dubai";
Your loop over *charPointers is strange, since it treats *charPointers as a character, when it's really a pointer.
Perhaps you meant:
for(size_t i = 0; charPointers[i] != NULL; ++i)
printf("%s\n", charPointers[i]);

I want to use an array of char pointers where each pointer in the array is pointing to a char in another char array
Why? There is never a reason why you would want to do this, in real world programming.
therefore, I would be able to print the char array through the pointers
Indeed. That's handy if your program is too fast and too effective.
Is charPointers an array of pointers or simply a string?
It's an array of pointers.
What's an elegant way to achieve what I want?
There is no elegant way to "use an array of char pointers where each pointer in the array is pointing to a char in another char array". This is obfuscation and it fills no purpose except making your code slow and unreadable.
Sane, elegant code would look like this:
const char city [] = {'D', 'u', 'b', 'a', 'i', '\0'};
printf("City = ");
print_str(city);
...
void print_str (const char* str)
{
while(*str != '\0')
{
putchar(*str);
str++;
}
}

Related

Function to reverse a two-dimensional set of strings in C isn't reversing more than the first and last characters

this is my first post in Stack Overflow. If I am missing anything, please let me know and I will try to add more information.
The function below is only supposed to use pointer operations and not array operations, as part of an assignment.
I have this function in C that is part of a larger program:
void reverseString(char strings[NUM_STRINGS][STRING_LENGTH])
{
int i, j;
char *ptr; //Declare pointer variable.
for (i = 0; i < NUM_STRINGS; i++)
{
ptr = strings[i];
do { //Here, we ignore the null terminators in the char array.
ptr++;
} while (*ptr != '\0');
ptr--; //Iterate the pointer variable once downward.
j = i;
while (strings[j] < ptr) //While loop for reversing the string
{
//printf("ptr: %d\n", ptr);
//printf("strings[j]: %d\n", strings[j]);
char temp = *strings[j];
*strings[j++] = *ptr;
*ptr-- = temp;
}
}
}
What it is supposed to do is accept a 2D char array with 4 strings and with each string holding up to 32 bytes of text. Then, it reverses each string in-place in the array. For example, if I input the four strings:
Hello
World
Good
morning
It is supposed to then return:
olleH
dlroW
dooG
gninrom
However, what ends up happening is that only the first and last characters of each string are reversed. For example:
oellH
dorlW
dooG
gorninm
I have tried different solutions such as using i instead of j in the while loop or using prefix ++ instead of suffix, but nothing has worked yet. Any pointers as to what I should be looking for?
Thank you.
The solution is below. As described in my comment below, I added a secondary pointer instead of using strings[j] in the loop. The pointer now references to the beginning of the string instead of the entire array of strings.
void reverseString(char strings[NUM_STRINGS][STRING_LENGTH])
{
int i, j;
char *ptr; //Declare pointer variable.
char *ptr2;
for (i = 0; i < NUM_STRINGS; i++)
{
ptr = strings[i];
ptr2 = strings[i];
do { //Here, we ignore the null terminators in the char array.
ptr++;
} while (*ptr != '\0');
ptr--; //Iterate the pointer variable once downward.
j = i;
while (ptr2 < ptr) //While loop for reversing the string
{
char temp = *ptr2;
*ptr2++ = *ptr;
*ptr-- = temp;
}
}
}

Looping through *array[] but not array[] in C?

What makes *array[] to be able to be looped through but not array[]?
Example:
int main()
{
int i;
char *greeting[] = {"Hello", "World",
"Good Bye", "World"};
for(i = 0; i < 4; i++)
printf("Greeting message: %s\n", greeting[i] );
return 0;
}
And is there any way of getting a character from a specific element in this array? If I wanted to get the character 'W' in the last element, would that be possible or is it just possible to print out the whole string?
W is greeting[3][0]
Just treat greeting[n] as another array of chars.
printf("first char of greeting 3 is %c\n", greeting[3][0]);

copying portions of string, which are stored in a char array, to another array

I wanted to try and copy parts of strings which are already stored in one array of strings to another empty array. (I think called array of pointers to char arrays )
I would like to copy the first 3 characters of each string and store them in the second array and then print them out - like so
AAA
BBB
CCC
DDD
EEE
FFF
Here is my code.
void main()
{
/*ARRAY 1*/
char *line1 = "AAAAA";
char *line2 = "BBBBB";
char *line3 = "CCCCC";
char *line4 = "DDDDD";
char *line5 = "EEEEE";
char *line6 = "FFFFF";
char *array1[6];
array1[0] = line1;
array1[1] = line2;
array1[2] = line3;
array1[3] = line4;
array1[4] = line5;
array1[5] = line6;
int i;
char *array_main[6];
for(i = 0; i<6 ; i++ ) {
array_main[i] = ("%*.*s\n",1,3,array1[i]);
printf("%s", array_main[i]);
printf("\n");
}
}
do i need to do a malloc here ? (for array_main[i]) from what i understand, I am basically just copying the address of the particular characters to array_main's elements.
EDIT - Sorry, I should have made this clearer, I want to collect the strings in array_main and then print them in order outside of the loop which actually copies the data.
You are copying pointers to statically declared strings to an array. That's theoretically fine. Howevery, you want to cut off the remainder of the strings, so you need to prepare memory for the target strings, because if you write to the strings you will invoke undefined behaviour.
This line:
array_main[i] = ("%*.*s\n",1,3,array1[i]);
definitely doesn't do what you want though. I think this shouldn't even compile.
You loop over the array and malloc the appropriate size of bytes (3+1), then copy over the parts of the string that you want (don't forget the 0-byte at the end).
So it should look like this:
for(i = 0; i < 6; i++)
{
array_main[i] = malloc(4);
snprintf(array_main[i], 4, "%.3s", array[i]);
printf("%s\n", array_main[i]);
free(array_main[i]);
}
A simpler version (with unneccessary memeory overhead) would be this:
for(i = 0; i < 6; i++)
{
array_main[i] = strdup(array[i]);
array_main[i][3] = 0;
printf("%s\n", array_main[i]);
free(array_main[i]);
}
#include <stdio.h>
#include <string.h>
int main(void){
const char *array1[6] = {"AAAAA", "BBBBB", "CCCCC", "DDDDD", "EEEEE", "FFFFF" };
char array_main[6][4] = {{0}};//4 : 3 + 1 (+1 for End of string('\0'))
int i;
for(i = 0; i<6 ; i++ ) {
strncpy(array_main[i], array1[i], 3);
printf("%s\n", array_main[i]);
}
return 0;
}

Strange printf output in C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * reverse(char *string);
int main(int argc, char *argv[])
{
char array[10];
array[0] = 'a';
array[1] = 'b';
array[2] = 'c';
array[3] = 'd';
array[4] = 'e';
printf("1%s\n",array);
char *p = reverse(array);
printf("4%s\n",p);
printf("5%s\n",array);
}
char * reverse(char *string)
{
int size = strlen(string);
char reversed[size];
int i;
int j = 0;
for(i = size-1; i >= 0; i--)
{
reversed[j] = string[i];
j++;
}
printf("2%s\n",reversed);
string = reversed;
printf("3%s\n",string);
return reversed;
}
This code basically just initializes an array of values and passes it into a method that reverses these values.
I am not sure if this is the best way to execute the task, since I am new to pointers and arrays in C.
But the real question is this:
Can anyone figure out why in this line
printf("4%s\n",p);
if you remove the preceding '4', so it looks like so
printf("%s\n",p);
the line won't print at all?
You are returning a pointer to local variable(reversed) in the function reverse the question should actually be: Why did it work in the first place?.
This code string = reversed; will only copy the pointer, and again the local copy of the pointer so it has no effect outside the function.
To reverse a string you don't need additional memory - this can be done in-place.
Strings in C must end with the null character. You're using strlen on a non null-terminated string.
Furthermore, you just a very lucky person, because there is a serious problem with you code: you forget to add \0 symbol at the end of string.
UPD: the main problem is with code line char reversed[size];.
It's a regular local variable, it has automatic duration, which means that it springs into existence when the function is called and disappears when the function returns (see this link).
You need to change it to:
char *reversed = malloc((size+1)*sizeof(char));
UPD-2: another bug fixing will be:
1) add array[5] = '\0'; after all other array initializing lines
2) add reversed[j] = '\0'; after for...loop:
for(i = size-1; i >= 0; i--)
{
reversed[j] = string[i];
j++;
}
reversed[j] = '\0';
UPD-3: But in general it will much more correctly initialize your string in appropriate way:
char array[10] = "abcde";

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