Allocate char array and strings - c

I have problem understanding the code below.
What value index=strlen(strs[0]) gets?
char *a= malloc (sizeof(char)*(index+1)) Is this the standard way to allocate array for char array?
What does strs[i][j] represent?
This is the code I found on leetcode. Just trying to understand the code. (code from sanghi user on leetcode)
#include<string.h>
char* longestCommonPrefix(char** strs, int strsSize)
{
int i=0; int j=0;int index;int tempindex=0;
if(strsSize<1)
return "";
index=strlen(strs[0]);
char *a;
a= malloc(sizeof(char)*(index+1));
strcpy(a,strs[0]);
for(i=1;i<strsSize;i++)
{ tempindex=0;
for(j=0;j<index;j++)
{
if(a[j]==strs[i][j])
tempindex++;
else
{a[j]='\0';
break;
}
}
if (tempindex==0)return ("");
if(tempindex<index)index=tempindex;
}
return a;
}
Expected results can be found on https://leetcode.com/problems/longest-common-prefix/

strs is an array of strings. strsSize is the number of strings in the array.
index = strlen(strs[0]);
This simply gets the length of strs[0], the first string in the array.
a = malloc(sizeof(char)*index+1);
This will allocate enough memory to store a string of the same size. I say enough memory because each string actually has length + 1 characters. The last character is \0, a null terminator. You always have to make sure to terminate your strings or else a bunch of weird buffer overflow stuff can happen.
str[i][j]
This accesses the jth character in the ith string in the array.

For starters the program is bad and invalid.:)
For example the size of the one dimensional array first element of which is pointed to by the parameter strs shall have the type size_t instead of int.
And all other variables that deal with indices also shall have the type size_t as for example
size_t index = strlen( strs[0] );
because the standard C function strlen has the return type size_t.
The source array is not changed in the function so the first parameter shall be declared with the qualifier const.
That is the function declaration shall look like
char * longestCommonPrefix( const char** strs, size_t strsSize);
Farther the elements (strings) of the array can have different lengths, So this loop
for(j=0;j<index;j++)
has undefined behavior because some element (string) of the array can have length less than the value of the variable index.
In fact there is no need to calculate lengths of the elements of the array. The loop can use the condition
for( j=0; j < index && strs[i][j] != '\0'; j++)
And moreover the function has a memory leak due to this return sub-statement in the if statement
a= malloc(sizeof(char)*(index+1));
//...
if (tempindex==0)return ("");
That is the allocated memory pointed to by the pointer a will not released.
What value index=strlen(strs[0]) gets?
index gets the length of the string stored in the first element of the array of strings.
For example if you have an array
char *strs[] = { "Hello", "Bye", "Good Morning" };
then index is set to the length of the string "Hello".
char a= malloc (sizeof(char)(index+1)) Is this the standard way to
allocate array for char array?
Yes in this declaration there is allocated a memory large enough to store the string (including its terminating zero) of the first element of the array pointed to by strs.
What does strs[i][j] represent?
strs[i][j] access j-th character of the i-th element of the array pointed to by strs.
For example for the declaration above strs[0][0] is equal to 'H', strs[0][1] is equal to 'e', strs[1][0] is equal to 'B' and so on.
P.S. A better approach to define the function is the following as it is shown in the demonstrative program.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
size_t longestCommonPrefix( const char **strs, size_t strsSize )
{
size_t n = 0;
if ( strsSize != 0 )
{
n = strlen( *strs );
for ( size_t i = 1; n != 0 && i < strsSize; i++ )
{
size_t j = 0;
while ( j < n && strs[i][j] == strs[i-1][j] ) j++;
if ( j < n ) n = j;
}
}
return n;
}
int main(void)
{
char * strs[] = { "0123456789", "012345", "0123" };
size_t n = longestCommonPrefix( ( const char ** )strs, sizeof( strs ) / sizeof( *strs ) );
char *p = NULL;
if ( n != 0 )
{
p = malloc( n + 1 );
memcpy( p, strs[0], n );
p[n] = '\0';
printf( "The longest common prefix is \"%s\"\n", p );
}
free( p );
return 0;
}
The program output is
The longest common prefix is "0123"

Related

i made a length() function in c and i want to put the number it returns into the size of an array,

but it isn't possible because I can't put a variable in the array size. ideas?
the function will check how many digits build the integer and will return that number
int intLength(int number)
{
for(int i=0;i<number;i++)
{
number=number/10;
if(number==1||number==0)
{
return i;
}
}
}
void just_a_function(void)
{
number=241;
char string[intLength(number)]={0};
}
The function has undefined behavior because it returns nothing when the number is not positive.
And for a two-digit number the function returns 1 because the expression can yield 1.
number=number/10;
It can look the following way
size_t intLength( int number )
{
const int Base = 10;
size_t n = 0;
do
{
++n;
} while ( number /= Base );
return n;
}
As for your question then you may not initialize a variable length array.
From the C Standard(6.7.9 Initialization)
3 The type of the entity to be initialized shall be an array of
unknown size or a complete object type that is not a variable length
array type.
So this variable length array declaration with an initializer
char string[intLength(number)]={0};
is incorrect.
Instead you can use the standard C function memset declared in the header <string.h>.
Here is a demonstrative program.
#include <stdio.h>
#include <string.h>
size_t intLength( int number )
{
const int Base = 10;
size_t n = 0;
do
{
++n;
} while ( number /= Base );
return n;
}
int main(void)
{
char string[intLength( 241 ) + 1];
printf( "The size of the string is %zu\n", sizeof( string ) );
memset( string, 0, sizeof( string ) );
return 0;
}
The program output is
The size of the string is 4
In the declaration
char string[intLength( 241 ) + 1];
I added one more character for the terminating zero
'\0' provided that the character array will indeed contain a string.
You are asking for a Variable Length Array (VLA).
VLAs cannot be initialized with the = {}; syntax, since the compiler does not know at compile-time how much space to initialize.
Instead, use memset:
void just_a_function(void)
{
number=241;
char string[intLength(number)]; // Declare a VLA
memset(string, 0, intLength(number)); // Set it to empty/zero
}
If your compiler does not support VLAs, then you would use malloc instead:
void just_a_function(void)
{
number=241;
char* string = malloc(intLength(number)+1);
string[0]='2';
string[1]='4';
string[2]='1';
string[3]='\0';
free(string);
}

Problem storing strings inside double pointer

I've been doing this code wars challenge in which you have to take a string, and capitalize each letter, forming a Mexican wave-looking array of strings. For example, an input string like
hello
will result in ["Hello", "hEllo", "heLlo", "helLo", "hellO"]
I managed to complete it in JavaScript, and decided to attempt it in C. The actual code itself is working, as it prints the correct output, but the problem I am having is actually storing the string inside a double pointer.
This is my code:
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void wave(char *s, char **array);
int main(void)
{
char *s = malloc(6);
strcpy(s, "hello");
char **array = malloc(pow(strlen(s)+1, 2));
wave(s, array);
for (int i = 0; i < strlen(s); i++)
{
printf("s = %s\n", array[i]);
}
free(array);
free(s);
return 0;
}
void wave(char *s, char **array)
{
char s2[strlen(s)+1];
for (int i = 0; i < strlen(s); i++)
{
s[i] = tolower(s[i]);
}
int array_index = 0;
for (int i = 0; i < strlen(s); i++)
{
strcpy(s2, s);
if (s[i] != ' ')
{
s2[i] = toupper(s2[i]); // Printing out `s2` here results in the correct output
array[array_index++] = s2; // Adding it here works, but when trying to access it outside of this function, it gives the incorrect output
}
}
}
When printing the string inside the function, I get the following output (which is correct):
Hello
hEllo
heLlo
helLo
hellO
But when I try to print it out inside the main() function, I get the following:
s = hellO
s = hellO
s = hellO
s = hellO
s = hellO
It seems like it is adding/accessing only the last string in the array. I cannot understand why accessing the element inside the wave() function works, but accessing it outside of that function doesn't.
I've had this problem twice before, both in C and C++, and have been unable to solve it, and it is really annoying me.
I left this as a comment, but since it might not be clear, I'll post my answer in code...
As stated in my comment, there's no point allocating a pointer array - on a 64 bit machine, that would be 6 pointers, each requiring 8 bytes to point at a 7 byte long data block - a total of 104 bytes (ignoring the added allocator padding per allocation).
Instead, a single allocation could suffice, allocating 42 bytes to contain all the "wave" strings and their NUL byte in a single block of memory (saving memory while improving locality).
int main(void) {
/* Assuming string "hello" */
const char *org = "hello";
/* Calculate length only once and store value */
const size_t len = strlen(org);
const size_t len_with_nul = len + 1;
/* Allocate `len` strings in a single allocation */
char *buf = malloc(len * len_with_nul);
/* Copy each string to it's place in the buffer */
for (size_t i = 0; i < len; ++i) {
/* position in the buffer */
char *pos = buf + (i * len_with_nul);
/* copy the NUL as well */
memcpy(pos, org, len_with_nul);
/* Wave... */
pos[i] = toupper(pos[i]);
}
/* Print result */
for (size_t i = 0; i < len; i++) {
char *pos = buf + (i * len_with_nul);
printf("s = %s\n", pos);
}
/* Free buffer */
free(buf);
return 0;
}
EDIT - Why is using a single memory block better?:
In this case we allocate a single memory "block" (blob / slice). This offers a number of advantages:
We perform a single allocation and deallocation instead of a larger number of allocations and deallocations.
This improves speed by performing less actions.
We also improve memory locality, which minimizes CPU cache misses and improves performance.
We use less memory.
Each memory allocation comes with a price - we need a pointer to hold the memory address for the memory we allocated. A pointer "costs" 8 bytes on a 64bit machine and 4 bytes on a 32bit machine.
By using a single allocation, we "pay" less.
This is true even if we ignore the metadata attached to the memory block allocated (which requires memory from the memory allocator).
I should note that C doesn't really care about the contents of a memory block, it's all zeros and ones. The meaning given to these zeros and ones is left to the developer.
Even the printf function doesn't care about the contents of the memory it's reading - it simply reads the memory according to the formatting it was instructed to follow by the developer (the %s informs the function that the memory relates to a NUL terminated string).
There are some concerns about memory alignment which are CPU and system specific - but these don't apply to single byte strings. They apply to multi-byte types (such as short, int, and long). So we don't need to worry about them in this example.
In this sense, it basically means that the developer is free to manage the memory and the contents as they see fit (putting aside memory alignment).
This is not to say that it's always better to allocate a single block of memory (if you need to use realloc, you might prefer smaller chunks)... but usually a single block of memory is better.
For starters it is unclear why you are allocating dynamically memory for the string literal "hello".
char *s = malloc(6);
strcpy(s, "hello");
It does not make any sense.
Just write
const char *s = "hello";
This declaration
char **array = malloc(pow(strlen(s), 2));
also does not make sense. What you need is the following.
size_t n = strlen( s );
char **array = malloc( n * sizeof( char * ) );
for ( size_t i = 0; i < n; i++ )
{
array[i] = malloc( n + 1 );
}
The function wave can be defined the following way
void wave( const char *s, char **array )
{
size_t n = strlen( s );
for ( size_t i = 0; i < n; i++ )
{
strcpy( array[i], s );
array[i][i] = toupper( ( unsigned char )s[i] );
}
}
and then in main after the function call
for ( size_t i = 0; i < n; i++ )
{
puts( array[i] );
}
for ( size_t i = 0; i < n; i++ ) free( array[i] );
free( array );
Here is the full program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void wave( const char *s, char **array )
{
size_t n = strlen( s );
for ( size_t i = 0; i < n; i++ )
{
strcpy( array[i], s );
array[i][i] = toupper( ( unsigned char )s[i] );
}
}
int main(void)
{
const char *s = "hello";
size_t n = strlen( s );
char **array = malloc( n * sizeof( char * ) );
for ( size_t i = 0; i < n; i++ )
{
array[i] = malloc( n + 1 );
}
wave( s, array );
for ( size_t i = 0; i < n; i++ )
{
puts( array[i] );
}
for ( size_t i = 0; i < n; i++ ) free( array[i] );
free( array );
return 0;
}
Its output is
Hello
hEllo
heLlo
helLo
hellO

Initialize string array in C and count number of letters inside

I found this example
int SizeofCharArray(char *phrase)
{
int size = 0;
int value = phrase[size];
while(value != 0)
{
value = phrase[size];
size++;
};
//printf("%i%s", size, "\n");
return size;
}
here
But how can I count number of letters in string array using pure C? Even I do not understand how can I initialize string array?!
Thank you!
The posted code is of rather poor quality. The name of the function, SizeofCharArray, does not match the description, count number of letters in string array.
If you want to return the number of characters in the array, use:
int SizeofCharArray(char *phrase)
{
int size = 0;
char* cp = phrase;
while( *cp != '\0')
{
size++;
cp++;
};
return size;
}
If you want to return the number of letters in the array, use:
int isLetter(char c)
{
return (( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ));
}
int GetNumberOfLetters(char *phrase)
{
int num = 0;
char* cp = phrase;
while( *cp != '\0')
{
if ( isLetter(*cp) )
{
num++;
}
cp++;
};
return num;
}
This will count the number of alphabetic characters in a c-string:
#include <ctype.h>
int numberOfLetters(char *s)
{
int n = 0;
while (*s)
if (isalpha(*s++))
n++;
return n;
}
If you want the actual number of characters, counting characters like spaces and numbers, just use strlen(s) located in string.h.
To find the length of C string, you can use strlen() function
#include<string.h>
char str[]="GJHKL";
const char *str1="hhkjj";
int len1=strlen(str)<<"\n";
int len2=strlen(str1);
It's not particularly good C. I doesn't give you the size of a char array -- that's impossible to determine if you've lost that information. What it does give you is the size of a null-terminated char array (AKA a c-string), and it does so by counting the characters until it finds the null-terminator (0 byte or '\n'). As a matter of fact, what you've got up top is a not particularly good strlen implementation (strlen is a standard library function that does the same thing -- determine the size of a null-terminated char array)
I believe this below should be a little more C-ish implementation of the same thing:
size_t strlen(const char *s){
const char* ptr = s;
for(; *ptr; ++ptr); //move the pointer until you get '\0'
return ptr-s; //return the difference from the original position (=string length;)
}
It returns size_t (64 bit unsigned int if you're on a 64 bit machine and 32 on 32 machines, so it will work on arbitrarily long strings as long as they fit into memory) and it also declares that it won't modify the array it measures (const char *s means a pointer you promise not to use to change what it points to).

Finding the length of a Character Array in C

What is a way in C that someone could find the length of a character array?
I will happily accept pseudo-code, but am not averse to someone writing it out if they'd like to :)
Provided the char array is null terminated,
char chararray[10] = { 0 };
size_t len = strlen(chararray);
If you have an array, then you can find the number of elements in the array by dividing the size of the array in bytes by the size of each element in bytes:
char x[10];
int elements_in_x = sizeof(x) / sizeof(x[0]);
For the specific case of char, since sizeof(char) == 1, sizeof(x) will yield the same result.
If you only have a pointer to an array, then there's no way to find the number of elements in the pointed-to array. You have to keep track of that yourself. For example, given:
char x[10];
char* pointer_to_x = x;
there is no way to tell from just pointer_to_x that it points to an array of 10 elements. You have to keep track of that information yourself.
There are numerous ways to do that: you can either store the number of elements in a variable or you can encode the contents of the array such that you can get its size somehow by analyzing its contents (this is effectively what null-terminated strings do: they place a '\0' character at the end of the string so that you know when the string ends).
Although the earlier answers are OK, here's my contribution.
//returns the size of a character array using a pointer to the first element of the character array
int size(char *ptr)
{
//variable used to access the subsequent array elements.
int offset = 0;
//variable that counts the number of elements in your array
int count = 0;
//While loop that tests whether the end of the array has been reached
while (*(ptr + offset) != '\0')
{
//increment the count variable
++count;
//advance to the next element of the array
++offset;
}
//return the size of the array
return count;
}
In your main function, you call the size function by passing the address of the first element of your array.
For example:
char myArray[] = {'h', 'e', 'l', 'l', 'o'};
printf("The size of my character array is: %d\n", size(&myArray[0]));
You can use strlen
strlen(urarray);
You can code it yourself so you understand how it works
size_t my_strlen(const char *str)
{
size_t i;
for (i = 0; str[i]; i++);
return i;
}
if you want the size of the array then you use sizeof
char urarray[255];
printf("%zu", sizeof(urarray));
If you want the length of the character array use sizeof(array)/sizeof(array[0]), if you want the length of the string use strlen(array).
There is also a compact form for that, if you do not want to rely on strlen. Assuming that the character array you are considering is "msg":
unsigned int len=0;
while(*(msg+len) ) len++;
using sizeof()
char h[] = "hello";
printf("%d\n",sizeof(h)-1); //Output = 5
using string.h
#include <string.h>
char h[] = "hello";
printf("%d\n",strlen(h)); //Output = 5
using function (strlen implementation)
int strsize(const char* str);
int main(){
char h[] = "hello";
printf("%d\n",strsize(h)); //Output = 5
return 0;
}
int strsize(const char* str){
return (*str) ? strsize(++str) + 1 : 0;
}
You can use this function:
int arraySize(char array[])
{
int cont = 0;
for (int i = 0; array[i] != 0; i++)
cont++;
return cont;
}
By saying "Character array" you mean a string? Like "hello" or "hahaha this is a string of characters"..
Anyway, use strlen(). Read a bit about it, there's plenty of info about it, like here.
Well, 11 years later, I run into this issue with a college assignment. The solution I found, worked without having to alter the function signatures that the assignment was asking for.
In my case, I had to make a function that returns the item index if the item existed or depending on if the itemPrefix (e.g. 'B' for Banana) already exists or not in the character array itemPrefixes to avoid passing duplicate prefixes.
So, I had to use a for loop (or while loop). The problem was that the assignment had given me specific signatures for each function and for that specific function it didn't allow me to pass the count variable that was on the main() function as an argument.
I had to improvise.
Both the ways mentioned above didn't work. strlen() didn't work as intended since there was not a '\0' end character that strings have. The sizeof() method also didn't work, because it returned the size of the pointer of the character array that was passed in as an argument instead of the number of elements.
So, this is the function I came up with. A simple while loop that checks whether the current character is NULL (or 0).
void charArrLength(char array[]) {
int arrLength = 0;
while (array[arrLength] != 0) {
arrLength++; //increment by 1
}
printf("Character array has %d elements", arrLength);
}
For this to work though, in the main() function, you need to declare your character array as a character pointer and then allocate the memory that you need based on the number of items that you ultimately wish to have inside your array.
void charArrLength(char array[]) {
int arrLength = 0;
while (array[arrLength] != 0) {
arrLength++;
}
printf("Character array has %d elements", arrLength); //should give 33
}
int main() {
char *array; //declare array as a pointer
int arraySize = 33; //can be anything
array = (char*) malloc(arraySize * sizeof(char));
charArrLength(array);
free(array); //free the previously allocated memory
}
Below you will see how I utilised this function in my assignment.
First, here is the above function tailored to my needs.
int isItemExists(char itemPrefixes[], char itemPrefix) {
int count = 0; //declare count variable and set to 0
int itemIndex = -1; //declare item index variable and set it to -1 as default
while (itemPrefixes[count] != 0) {
count++;
}
for (int i = 0; i < count; i++) {
if (itemPrefix == itemPrefixes[i]) {
itemIndex = i; //if item exists, set item index to i
}
}
return itemIndex;
}
Then, how I declared the itemPrefixes array in main() function and how I allocated the needed memory based on n (the number of items the user would like to add to itemPrefixes array).
char *itemPrefixes;
int n = 0; //number of items to be added variable
printf("> Enter how many items to add: ");
scanf("%d", &n);
//allocate n * size of char data type bytes of memory
itemPrefixes = (char*) malloc(n * sizeof(char));
And finally, here is how that function was used after all.
do {
printf("\n\n> Enter prefix for item %d: ", i + 1);
scanf(" %c", &itemPrefix);
//prompt the user if that itemPrefix already exists
if (isItemExists(itemPrefixes, itemPrefix) != -1) {
printf("\nItem prefix already exists! Try another one.\n");
}
} while (isItemExists(itemPrefixes, itemPrefix) != -1);
Also, in the end of the code I free the previously allocated memory.
free(itemPrefixes);
To clear this out, again, this could be much easier if the conditions were different. The assignment was strict about not passing n as an argument. Nevertheless, I hope I help someone else that might be looking for this in the future!
Just for the sake of it, if anybody sees this and has something simpler to suggest, feel free to tell me.

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