Char pointers and strings - c

I found this program on-line, that claims to split a string on the format "firstName/lastName". I tested, and it works:
char *splitString(char* ptrS, char c){
while( *ptrS != c ){
if( *ptrS == '\0'){
return NULL;
}
ptrS++;
}
return ptrS;
}
int main(){
char word[100];
char* firstName;
char* lastName;
printf("Please insert a word : ");
fgets(word, sizeof(word), stdin);
word[strlen(word)-1] = '\0';
firstName = word;
lastName = splitString(word, '/');
if(lastName == NULL ){
printf("Error: / not found in string\n");
exit(-1);
}
*lastName = '\0';
lastName++;
printf("First name %s, Last name %s\n",firstName, lastName);
return(0);
}
What I'm seeing here however, is only one char array being created, and the firstName and lastName pointers being placed properly.Maybe it is because I'm a little confused about the relation between pointers and arrays but I have a few questions about this program:
How many strings -as char arrays- are produced after the program is executed?
Are the char pointers used in this program the same as strings?
Why I can use those char pointers used as strings in printf? I can use char pointers as strings on every C program?
As a corollary, what's the relationship between pointers and arrays? Can they be used interchangeably?

How many strings -as char arrays- are produced after the program is executed?
You have one char[], of size 100. However, at the end of the program's execution, you actually have two strings stored in it.
A string is a set of chars stored contiguously in memory terminated with '\0' (null/0).
In this program we take the input, and search for the '/' character. When found, it is replaced with the string terminator:
"John/Smith\0"
"John\0Smith\0"
The pointer to the beginning of the array will allow us to access the first string ("John"), and the pointer that previously pointed to the '/' character is incremented, so that it now points to "Smith"
initialisation:
"John/Smith\0"
^
|
word/firstname
after lastName = splitString(word, '/');:
"John/Smith\0"
^ ^
| lastname
word/firstname
after *lastName = '\0'; lastName++;:
"John\0Smith\0"
^ ^
| lastname
word/firstname
So there is still only one array (word) but you have two pointers (firstname &lastname) to the strings within.
Are the char pointers used in this program the same as strings?
The char* pointers are not strings, but they point to them. You can pass the pointers to any function that is expecting a string (I expand a bit below)
Why I can use those char pointers used as strings in printf? I can use char pointers as strings on every C program?
In C (and C++) functions cannot pass arrays of data. A function like this:
int func(char string[]){}
will not actually be passed the array itself, but instead, it will be passed a pointer to the beginning of the array.
It is often the case that the [] notation is used where the function will be operating on an array (in function headers char* str and char str[] are equivalent) as it removes any ambiguity that the pointer isn't there to reference a single char (or int etc).
Printf() takes pointers to the string, and knowing that it is a string (thanks to the %s identifier in the format string) it will print out each char from the memory location that the pointer identifies until it hits the '\0' character.
A valid string always has this terminator, and so when working with strings, this is safe.
You will often see functions that take an array, and an additional parameter to denote the size of the array:
int do_something_with_array(int array[], size_t array_length){}
This is because without a terminating value or knowing the size of the array, there is no way to know that you have left the array and started processing out of bounds which isn't allowed and can cause memory corruption or cause the runtime to kill your program (crash).
It is a common misconception that pointers and arrays are the same.
In most cases you handle arrays via pointers, so that handling the data is the same whether you have an array or a pointer to one. There are some things to keep in mind however; this as an example.

How many strings -as char arrays- are produced after the program is executed?
There are 1 char array in this program, namely word[100], others like firstName and last Name are just char pointers..
Are the char pointers used in this program the same as strings?
Char pointers are very different to Strings, Char pointers are something you can use to point at a char or a string. In this program firstName and lastName are only char pointers that are used to point at different places of the character array word[] to split the array

Related

Reverse order in array of char in C

The pointers confuse me a lot. I have a function that takes as arguments argc (the number of argument that are strings + 1 that is the name of the code) and char* argv[], that, if I understood well, is an array of pointers. Now as result I need to print on each line the argument (string) and the reversed string. This means that if I pass as arguments hello world, I need to have:
hello olleh
world dlrow
I tried to implement a part of the code:
int main(int argc, char *argv[])
{
int i = 1;
int j;
while (i < argc)
{
while (argv[i][j] != 0) {
printf("%c", argv[i][j]);
j++;
}
i++;
}
return 0;
}
}
And now I'm literally lost. The inner loop doesn't work. I know that argv[i] pass through all my arguments strings, but I need obviously to enter in the strings (array of chars), to swap the pointers. Also I don't understand why the difference between argv[0] and *argv, because in theory argv[0] print the first element of the array that is a pointer, so an address, but instead of this it prints the first argument.
char* argv[] is a "array of pointers to a character" It's important to learn how to read types in C; because, those types will enable / thwart your ability to do stuff.
Types are read right to left. [] is a type of array, with an unspecified number of elemnts * is a pointer type, char is a base type. Combine these, and you now have "array of pointers to a character"
So to get something out of argv, you would first specify which element it is in the array. argv[0] would specify the first element. Let's look at what is returned. Since the array is not part of the result, the answer is "a pointer to a character"
char* line = argv[0];
would capture the pointer to a character, which is stored in argv[0].
In C a char* or a "pointer to a character" is the convention used for a string. C doesn't have a new type for "string"; rather it uses pointers to characters, where advancing the pointer eventually runs into the \0 character that signals the string's end.
int main(int argc, char* argv[]) {
int index = 0;
while (index <= argc) {
char* line = argv[index];
printf("%d, %s\n", index, line);
index++;
}
}
should dump the arguements passed to your program. From there, I imagine you can handle the rest.
Notice that I never converted the pointer to an array. While arrays can be used as pointers if you never specify the index of the array, in general pointers can't be used as arrays unless you rely on information that isn't in the type system (like you clearly grabbed the pointer from an array elsewhere).
Good luck!
---- Updated to address the question "How do I reverse them?" ----
Now that you have a simple char* (pointer to a character) how does one reverse a string?
Remember a string is a pointer to a character, where the next characters eventually end with a \0 character. First we will need to find the end of the string.
char* some_string = ...
char* position = some_string;
while (*position != 0) {
position++;
}
// end_of_string set, now to walk backwards
while (position != some_string) {
position--;
printf("%c", *end_of_string);
}

Receive an array of strings from a function and find out it's length [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have this code:
char** SplitToWords(char* str);
int main()
{
char** wordarr;
char str[] = "This is a sentence";
wordarr = SplitToWords(str);
return 0;
}
After the main comes the function implementation.
I am not sure the following does what I want it to do (i.e. receive an array of strings from a function):
wordarr = SplitToWords(str);
I somehow managed to convince the compiler that it's ok, but I assume it just does something else.
If it does, how do I find out the length of the array (the number of strings in it).
Thanks
I'll try to quickly visit all aspects you might not yet fully understand:
A string in C is described as a contiguous sequence of chars, ending with a char of value 0 (as a literal: '\0'). It is not a first class object, therefore hasn't its own type. So what you use to hold a string is an array of char. Therefore, taking your question by the word, "receive an array of strings from a function" is not possible.
An array is a contiguous sequence of objects of the same type. In C, the identifier of an array doesn't have a value itself; when it's evaluated, it decays as a pointer to the array's first element instead. This is especially important when passing arrays to functions or returning them from functions -- you can't actually pass the array, you always pass a pointer
e.g. you could write:
char x[] = "foo"; // initialize a char array from a string literal
char *xp = x; // here, x evaluates as a pointer to the first element of the array
You already use pointer types for your function's argument and return value, I just think it's quite important to understand what happens entirely.
You write char** SplitToWords(char* str); and ask whether this returns an "array of strings" -- well, sort of, as you should understand after reading 1. and 2. -- What it does is returning a pointer to char *. This pointer could be a pointer to the first element of an array. So in this case, it would return a pointer to an array of char * pointers. Each of these pointers could itself be a pointer to an array of chars, therefore point to a string. But what's very important is to understand you never return an array, you always return a pointer to it. It's so important because:
You might get the idea to do something like this:
char** SplitToWords(char* str)
{
char *words[16];
// code to fill `words` with pointers to the actual words
return words; // WRONG!
}
Here, because you're not returning the array words but a pointer to it (see point 2), you return a pointer to an object that no longer exists. words is in the scope of your function and has automatic storage duration, that means it only lives as long as the execution is inside of the function. One solution would be to declare words with the static storage class specifier. This way, it lives for the entire execution time of the program. But be aware that this also means there's only a single instance ever, it's always the same object. This will be a major headache for threaded programs, for example. The other way around is to dynamically allocate words using malloc(). But then, the caller of the function must free() it later.
As for your second question, how to let the caller know the number of words -- it's in the comments already, but just for completeness, a typical approach to solve this is to append another entry that is a NULL pointer. So the caller can iterate over the pointers until it finds NULL.
Regarding your comment, of course you can create the array outside the function and pass a pointer to the function, so the function only fills it. This is a common idiom in C (e.g. think about fgets(), which takes a pointer to the char array that's filled with a string by the function).
Functions working this way will need an additional size_t parameter, so they know the size of the array they should fill through the pointer, otherwise you'd have the risk of buffer overflows (this is why gets() was finally removed from the C standard). If you decide that the caller provides the storage, your function should have this prototype:
// returns the number of words found, up to `nwords`
size_t SplitToTwords(char **words, size_t nwords, char *str);
It should be called e.g. like this:
char *words[16];
size_t nwords = SplitToWords(words, 16, "the quick brown fox"); // returns 4
Remember that the strings holding the words themselves need storage as well. You can either manipulate the bytes in str to insert a '\0' after each word, overwriting the first whitespace character (this is what strtok() does) or you can copy the words to new strings, but then you would have to malloc() each of them again and the caller has to free() them later.
Yes, you could solve it by using a function with return value char **. However, there's no way to find out how many words there are afterwards.
You can solve this by allocating one more element for the return pointer and set it to NULL. Then you can get the number of words with this code:
wordarr = SplitToWords(str);
char **ptr=wordarr;
int noWords=0;
while(!*(ptr+noWords))
noWords++;
But if you want to return multiple data in C, you either need to define a return struct or using return arguments. In this case, it could look like this for the first option:
typedef struct wordList {
char **wordarr;
int noWords;
}
wordList SplitToWords(char* str);
And the second:
char** SplitToWords(char* str, int *noWords);
or
void SplitToWords(char* str, char*** wordarr, int *noWords);
Note that there's three *. That's because we want it to be a pointer to char **
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXSTRINGS 5000
int main(int argc, char *argv[]) {
char *stringTable[MAXSTRINGS];
char sentence[] = "This is a sentence";
char *token = NULL;
int i = 0;
while ((token = strtok(token == NULL ? sentence : NULL, " ")) != NULL)
{
printf("%s\n\r", token);
stringTable[i] = (char *)malloc(strlen(token) + 1); //have no "plain" C compiler - VS C++ used so cast needed :)
strcpy(stringTable[i++], token);
}
stringTable[i] = NULL; // if you need to iterate through later
printf("%d tokens found\n\r", i);
for (int y = 0; y < i; y++)
free(stringTable[y]);
}

strcat (s1, s2) continues to apparent to my temp variable array

Newbie to programming (school) and I'm a little confused on what/why this is happening.
I have a loop that is iterating over an array of elements, for each element I am taking the integer of the array, converting it to a char using the function getelementsymbol, and using strcat to append to my temp array. The problem I am having is that the elements of my temp array contain the residual of the element proceeding it. This is the snippet of my code. The output I receive is this:
word1
word1word2
word1word2word3
char* elementsBuildWord(const int symbols[], int nbSymbols){
/* ROLE takes a list of elements' atomic numbers and allocate a new string made
of the symbols of each of these elements
PARAMETERS symbols an array of nbSymbols int which each represent the atomic number
of an element
nbSymbols symbols array's size
RETURN VALUE NULL if the array is of size <= 0
or if one of the symbols is not found by our getElementSymbol function
other the address of a newly allocated string representing the concatenation
of the names of all symbols
*/
char s1[MAX_GENERATED_WORD_LENGTH];
int y;
char *s2;
size_t i;
for (i = 0; i < nbSymbols; i++){
y = symbols[i];
s2 = getElementSymbol(y);
strcat(s1, s2);
}
printf("%s ", s1);
}
Firstly, your s1 is not initialized. strcat function append a new string to an existing string. This means that your s1 has to be a string from the very beginning. An uninitialized char array is not a string. A good idea would be to declare your s1 as
char s1[MAX_GENERATED_WORD_LENGTH] = { 0 };
or at least do
s1[0] = '\0';
before starting your cycle.
Secondly, your getElementSymbol function returns a char * pointer. Where does that pointer point to? Who manages the memory it points to? This is non-obvious from your code. It is possible that the function returns an invalid pointer (like a pointer to a local buffer), which is why might see various anomalies. There's no way to say without seeing how it is implemented.
strcat is supposed to append to a string. use strcpy if you want to overwrite the existing string. You could also use s1[0] = '\0'; before strcat to "blank" the string if you really want to, but looks like you really want strcpy.
From the snippet above it's not even clear why you need s1 - you could just print s2...

How does strcpy() copy a string to an array when you can't change the address of an array?

So basically strcpy assigns the address of the 2nd argument to the 1st, but how does it do it with an array as the first argument? like in my program, i tried changing the address of the array but unfortunately it wont compile. So I had to resort to making a character pointer variable to assign the return value of capitalize. Is there something I'm misunderstanding?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char string[20];
char *Capitalize(char *str)
{
int i;
char *temp;
temp = malloc(sizeof(char)*(int)(strlen(str)+1));
for(i = 0;i < strlen(str);i++)
{
if(*(str+i) >= 'a' && *(str+i)<= 'z')
*(temp+i) = *(str+i) - 32;
else
*(temp+i) = *(str+i);
}
*(temp+i) = '\0';
return temp;
}
int main(void)
{
string word;
printf("Enter word to capitalize: ");
scanf("%19s",word);
word = Capitalize(word);
printf("%s",word);
return 0;
}
strcpy() makes a copy, just like the name implies. it's perfectly legal to copy a string in to an array.
When you make an initialization of an array such as:
char myarr[] = "hello";
You're actually copying the characters into the array.
You seem to be confusing arrays with pointers (see here for some reason you can't treat them the same)
In C, qualifying an array by name without an indexer, is equivalent to specifying a pointer to the memory address of the first element in the array, that is why you can pass as a parameter an array to functions like strcpy.
char * strcpy ( char * destination, const char * source );
strcpy will copy whatever series of characters are found, starting at memory address specified by source, to the memory address specified by destination, until a null character (0) is found (this null character is also copied to the destination buffer).
The address values specified in the parameters are not modified, they just specify from where in memory to copy and where to. It is important that destination is pointing to a memory buffer (can be a char array or a block of memory requested via malloc) with enough capacity for the copied string to fit, otherwise a buffer underrun will occur (you will write characters past the end of your buffer) and your program might crash or behave in a weird way.
Hope I have been clear and not confused you more with my explanation ;)
The thing you seem to be missing is that in c/c++ strings ARE arrays, in most practical respects declaring
char c[] = "hello";
and
char* c = "hello";
is the same thing, all strcpy does is copy the characters into the destination memory, whether that memory is allocated as an array (presumably on the stack) or pointer (presumably on the heap);it does not make a difference.

Char x[50] and Char x[100] Output

I'm not used to C as I'm primarily a Java guy, with some knowledge of C++, so forgive me if this is a trivial question. I could not seem to find an answer while searching online.
I'm initializing a char array...
char tcp[50];
So that I can concatenate a const char and a char. In examples I saw an easy way to do this was by creating that empty char array and then using...
strcat(x,y);
To stick them together.
Problem is, printing out the blank char array when it is set to "50" gives me a result of:
X??|?
When I change it to...
char tcp[100];
And print it, its blank. Why is this?
The array contents are undefined, assuming it is a local (automatic) array.
Use:
char tcp[50] = "";
Or:
char tcp[50] = {0};
Or:
char tcp[50];
tcp[0] = 0;
Or:
char tcp[50];
memset(tcp, 0, sizeof(tcp));
As you like.
Always null terminate you char arrays before doing anything:
tcp[0] = '\0';
C happily allocates the space for the array you declare, but it does not set its content to 0.
Therefore, the content of the array you're printing is random (or rather depending in the previous contents of the memory)
When creating an array, the compiler puts it somewhere in memory but does not initialize it, so whatever is in that memory when the program is started will be the initial "string".
Terminate the string manually after you created the array, either by making the whole array "zeroed" out, or just put zero as the first character:
char tcp[50] = { '\0' };
Or
char tcp[50];
/* ... */
tcp[0] = '\0';
The difference here is, you're essentially working with two empty arrays trying to merge them in the memory space of one (not sure if that makes sense for you).
First of all, in C you have to terminate strings with \0. That's something not exposed or visible in Java. Also you essentially used two undefined strings (as there's no value set).
#include <stdio.h>
#include <string.h>
char target[256];
const char source_a[] = "Hello";
const char source_b[] = "World!";
int void(main)
{
target[0] = '\0'; // this essentially empties the string as we set the first entry to be the end. Depending on your language version of C, you might as well write "char target[256] = {'\0'};" above.
strcat(target, source_a); // append the first string/char array
strcat(target, " "); // append a const string literal
strcat(target, source_b); // append the second string
printf("%s\n", target);
return 0;
}
Important: Using strcat() can be unsave, as there's no length check performed, and other than Java, these "strings" have a fixed length (the one you set when defining the variables). If there's no length given, but you copy a string on initialization, that length is taken (e.g. char test[] = "Hello!"; will be 7 chars long (due to terminating \0)).
If you'd like a more Java like approach on strings, use C++ and the std::string class, that performs a lot more similar to Java's strings.

Resources