C Get size of Array of array of chars - c

i want to get the number of elements at Text array the answer should be 2
char Text[5][10] = {
"Big12345",
"Big54321",
};
i want to a code to count number of elements in array of chars

In this particular case, anything after the initializers will be 0, so:
size_t counter = 0;
while ( Text[counter][0] != 0 )
counter++;
But, in general, C doesn't give you a good way of doing this. You either have to track the number of elements being used separately, or you have to use a sentinel value in the array.

You are mistaken. The number of elements in the array is 5. Two elements have non-empty strings and three elements have empty strings. But In fact an empty string can be placed anywhere in the array. For example
char Text[5][10] =
{
"Big12345",
"",
"Big54321",
};
This declaration is equivalent to
char Text[5][10] =
{
"Big12345",
"",
"Big54321",
"",
""
};
You could write a function that determines how many elements contain non-empty strings. For example
#include <stdio.h>
size_t count_non_empty( size_t m, size_t n, char s[][n] )
{
size_t count = 0;
for ( size_t i = 0; i < m; i++ )
{
count += s[i][0] != '\0';
}
return count;
}
int main(void)
{
char Text[5][10] =
{
"Big12345",
"",
"Big54321",
};
printf( "There are %zu non-empty elements\n", count_non_empty( 5, 10, Text ) );
return 0;
}
The program output is
There are 2 non-empty elements

Use the following to find the number of elements in your array which have a string assigned to them:
#include <stdio.h>
#include <string.h>
int main()
{
char Text[5][10] = {"Big12345",
"Big54321",};
int i, n;
for(i = 0, n = 0 ; i < 5 ; i++)
if(strlen(Text[i]) > 0)
n += 1;
printf("%d elements have a length > 0\n", n);
return 0;
}

Related

Inconsistent output given by same code on different C compilers

Different compilers are giving different outputs for the same logic in my algorithm.
I wrote the following code for a C code exercise.
The code checks for the longest string in a string vector.
But the same logic gives two different outputs.
Here's what is happening. I have no idea what I did wrong.
First version - without a printf() inside the if condition
Here the if (j > longest) just attributes new values for int longest and int index.
#include <stdio.h>
int main(void) {
char *vs[] = {"jfd", "kj", "usjkfhcs", "nbxh", "yt", "muoi", "x", "rexhd"};
int longest, index = 0;
/* i is the index for elements in *vs[].
* "jfd" is 0, "kj" is 1... */
for (int i = 0; i < sizeof(*vs); i++) {
/* j if the index for string lengths in vs[].
* for "jfd", 'j' is 0, 'f' is 1... */
for (int j = 0; vs[i][j] != '\0'; j++) {
/* if j is longer than the previous longest value */
if (j > longest) {
longest = j;
index = i;
}
}
}
printf("Longest string = %s\n", vs[index]);
return 0;
}
I ran it on https://replit.com/. It gave the unexpected output for longest string of "jfd". https://replit.com/#Pedro-Augusto33/Whatafuck-without-printf?v=1
Second version - with a printf() inside the if condition
Now I just inserted a printf() inside the if (jf > longest) condition, as seen in the code block bellow.
It changed the output of my algorithm. I have no idea how or why.
#include <stdio.h>
int main(void) {
char *vs[] = {"jfd", "kj", "usjkfhcs", "nbxh", "yt", "muoi", "x", "rexhd"};
int longest, index = 0;
/* i is the index for elements in *vs[].
* "jfd" is 0, "kj" is 1... */
for (int i = 0; i < sizeof(*vs); i++) {
/* j if the index for string lengths in vs[].
* for "jfd", 'j' is 0, 'f' is 1... */
for (int j = 0; vs[i][j] != '\0'; j++) {
/* if j is longer than the previous longest value */
if (j > longest) {
printf("Whatafuck\n");
longest = j;
index = i;
}
}
}
printf("Longest string = %s\n", vs[index]);
return 0;
}
I also ran it on https://replit.com/. It gave the expected output for longest string of "usjkfhcs". https://replit.com/#Pedro-Augusto33/Whatafuck-with-printf?v=1
Trying new compilers
After replit.com giving two different outputs, I tried another compiler to check if it also behaved strangely. https://www.onlinegdb.com/online_c_compiler gives random outputs. Sometimes it's "jfd", sometimes it's "usjkfhcs". https://onlinegdb.com/iXoCDDena
Then I went to https://www.programiz.com/c-programming/online-compiler/ . It always gives the expected output of "usjkfhcs".
So, my question is: why are different compilers behaving so strangely with my algorithm? Where is the flaw of my algorithm that makes the compilers interpret it different?
The code does not make sense.
For starters the variable longest was not initialized
int longest, index = 0;
So using it for example in this statement
if (j > longest) {
invokes undefined behavior.
In this for loop
for (int i = 0; i < sizeof(*vs); i++) {
the expression sizeof( *vs ) is equivalent to expression sizeof( char * ) and yields either 4 or 8 depending on the used system. It just occurred such a way that the array was initialized with 8 initializers. But in any case the expression sizeof( *vs ) does not provide the number of elements in an array and its value does not depend on the actual number of elements.
Using the if statement within the for loop in each iteration of the loop
for (int j = 0; vs[i][j] != '\0'; j++) {
/* if j is longer than the previous longest value */
if (j > longest) {
longest = j;
index = i;
}
}
Also does not make sense. It does not calculate the exact length of a string that is equal to j after the last iteration of the loop. So in general such a loop shall not be used for calculating length of a string.
Consider a string for example like "A". Using this for loop you will get that its length is equal to 0 while its length is equal to 1..
It seems you are trying to find the longest string a pointer to which stored in the array.
You could just use standard C string function strlen declared in header <string.h>. If to use your approach with for loops then the code can look the following way
#include <stdio.h>
int main(void)
{
const char *vs[] = { "jfd", "kj", "usjkfhcs", "nbxh", "yt", "muoi", "x", "rexhd" };
const size_t N = sizeof( vs ) / sizeof( *vs );
size_t longest = 0, index = 0;
for ( size_t i = 0; i < N; i++ )
{
size_t j = 0;
while ( vs[i][j] != '\0' ) ++j;
if ( longest < j )
{
longest = j;
index = i;
}
}
printf( "Longest string = %s\n", vs[index] );
printf( "Its length = %zu\n", longest );
return 0;
}

Error: assignment to expression with array type while using selection-sort

Basically, I'm trying to sort an agenda with 3 names using selection sort method. Pretty sure the selection sort part is OK. The problem is that apparently my code can identify the [0] chars of the string, but cannot pass one string to another variable. Here is my code:
include <stdio.h>
typedef struct{
char name[25];
} NAME;
int main(){
int a, b;
char x, y[25];
static NAME names[]={
{"Zumbazukiba"},
{"Ademiro"},
{"Haroldo Costa"}
};
for(a=0; a<4; a++){
x = names[a].name[0];
y = names[a];
for(b=(a-1); b>=0 && x<(names[b].name[0]); b--){
names[b+1] = names[b];
}
names[b+1].name = y;
}
}
I keep getting this error message:
main.c:21:11: error: assignment to expression with array type
y = names[a];
There are at least two errors in your code, in the line flagged by your compiler. First, you can't copy character strings (or, indeed, any other array type) using the simple assignment (=) operator in C - you need to use the strcpy function (which requires a #include <string.h> line in your code).
Second, you have declared y as a character array (char y[25]) but names is an array of NAME structures; presumably, you want to copy the name field of the given structure into y.
So, instead of:
y = names[a];
you should use:
strcpy(y, names[a].name);
Feel free to ask for further clarification and/or explanation.
For starters I do not see the selection sort. It seems you mean the insertion sort.
Arrays do not have the assignment operator. So statements like this
names[b+1].name = y;
where you are trying to assign an array are invalid.
And in statements like this
y = names[a];
you are trying to assign an object of the structure type to a character array.
Moreover the loops are also incorrect.
The array has only 3 elements. So it it is unclear what the magic number 4 is doing in this loop
for(a=0; a<4; a++){
and this loop
for(b=(a-1); b>=0 && x<(names[b].name[0]); b--){
skips the first iteration when a is equal to 0.
Here is a demonstrative program that shows how the selection sort can be applyed to elements of your array.
#include <stdio.h>
#include <string.h>
#define LENGTH 25
typedef struct
{
char name[LENGTH];
} NAME;
int main(void)
{
NAME names[] =
{
{ "Zumbazukiba" },
{ "Ademiro" },
{ "Haroldo Costa" }
};
const size_t N = sizeof( names ) / sizeof( *names );
for ( size_t i = 0; i < N; i++ )
{
puts( names[i].name );
}
putchar( '\n' );
for ( size_t i = 0; i < N; i++ )
{
size_t min = i;
for ( size_t j = i + 1; j < N; j++ )
{
if ( strcmp( names[j].name, names[min].name ) < 0 )
{
min = j;
}
}
if ( i != min )
{
NAME tmp = names[i];
names[i] = names[min];
names[min] = tmp;
}
}
for ( size_t i = 0; i < N; i++ )
{
puts( names[i].name );
}
putchar( '\n' );
return 0;
}
The program output is
Zumbazukiba
Ademiro
Haroldo Costa
Ademiro
Haroldo Costa
Zumbazukiba

How to check first letter of one string with last letter of another string inside of same char array

How can I complete the function canArrangeWords() ?
Question : Given a set of words check if we can arrange them in a list such that the last letter of any word and first letter of another word are same. The input function canArrangeWords shall contain an integer num and array of words arr. num denotes the number of word in the list (1<=num<=100). arr shall contain words consisting of lower case letters between 'a' - 'z' only . return 1 if words can be arranged in that fashion and -1 if cannot.
Input : 4 pot ten nice eye
output : 1
input : 3 fox owl pond
output: -1
Please help me complete this program .
**
#include<stdio.h>
#include<string.h>
int canArrangewords(int,char [100][100]);
void main(){
int n ,count=0 , i ;
char arrayS[100][100];
scanf("%d",&n);
for (i = 0; i < n; ++i)
{
scanf("%s",arrayS[i]);
}
for(i=0;i<n;i++)
{
printf("%s",arrayS[i]);
printf("\n");
}
printf("%c\n",arrayS[2][4]);
canArrangewords(n , arrayS);
}
int canArrangewords(int n,char arrayS[100][100]){
int i , j ;
for ( i = 0; i < n; i++)
{
for ( j = i+1 ; j < strlen(arrayS[j+1]); i++)
{
int flag = strlen(arrayS[j+1]) - 1;
int temp = strcmp(arrayS[i][0],arrayS[j][flag]);
}
}
}
}
Well, first of all think of the way you can reach that answer.
If you only need to know if they can or can not be arranged and you do not have to do so your self you can use an empty array of int array[26] for each letter a-z.
The rule is that from all the first and last letters for all the words only two MAY appear an odd amount of times - the first letter of first word in list and the last letter in the last word in the list, the rest MUST appear an even amount of times. I would add a check to make sure the letters are lowercase as well. good luck!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MINASCII 97
#define LETTERS 26
void UpdateArray(char letter, int* arr)
{
if(arr[letter - MINASCII] == 0)
{
++arr[letter - MINASCII];
}
else
{
--arr[letter - MINASCII];/*for each second time same letter is seen reduce back to zero */
}
}
int canArrangewords(int wordNum, char* wordArr[])
{
int arr[LETTERS] = {0};
int i = 0;
int count = 0 ;
char first;
char last;
char* string;
for (i= 0; i< wordNum; ++i)
{
string = wordArr[i];
first = string[0];
last = string[strlen(string)-1];
UpdateArray(first, &arr[0]);
UpdateArray(last, &arr[0]);
}
for(i = 0; i< LETTERS; ++i)
{
count+=arr[i];
}
if(count == 2 || count == 0)/*either once each or twice -see word1 example in main*/
{
return 1;
}
return -1;
}
int main()
{
int i = 0;
char* words[] = {"pot", "ten", "nice", "eye"};
char* words1[] = {"pot", "ten", "nip"};
char* words2[] = {"fox", "owl", "pond"};
i = canArrangewords(4,words);
printf("%d\n", i);
i = canArrangewords(3,words1);
printf("%d\n", i);
i = canArrangewords(3,words2);
printf("%d\n", i);
return 0;
}
Change your array of words into an array of pointers to words. Then you can simply exchange the pointers.
To speed things up, instead of a pointer to a word, have it point to a structure:
struct WORD {
char *firstchar; // begin of word
char *lastchar; // last char of word
} *words[100]; // array of 100 pointers to words
To read the words:
char buf[100];
for (i = 0; i < n; ++i)
{
scanf("%s",buf);
int len= strlen(buf);
words[i]= malloc(sizeof(struct WORDS));
words[i]->firstchar= malloc(len+1);
strcpy(words[i]->firstchar, buf);
words[i]->lastchar= words[i]->firstchar + len-1;
}
Now compare and sort:
if (*words[i]->lastchar == *words[j]->firstchar) {
struct WORDS *tmp= words[i+1];
words[i+1]= words[j];
words[j]= tmp;
}
Do this in a loop, a kind of bubble sort. I leave that to you.

Outputs differing -- can't understand the logic

Basically I am creating an array 'string' with some values in it, creating another array ('auxstring'), and then storing all the values of the initial array in reverse order. Finally I print them out.
How come when I execute the program as is, I get garbage as the output? However, if I put another number in the 'string' array (ie: {3,1,1,3,4}) it works fine (outputs: 43113).
It also works fine if I add this line:
"printf("%d\n", sizeof(auxstring));"
right before the for loop.
I'm sure it's something very basic, but I would like to understand what is going on behind the scene and why adding a number at the end of the initial string, or putting that printf, somehow outputs the accurate numbers.
Thanks.
#include <stdio.h>
#include <string.h>
int main(void) {
int i=0, j, l;
char string[] = {3,1,1,3};
char auxstring[sizeof(string)];
for (j=(sizeof(auxstring) - 1); j >= auxstring[0]; j--) {
auxstring[j] = string[i];
i++;
}
for (l=0; l < sizeof(auxstring); l++) {
printf("%d",auxstring[l]);
}
return 0;
}
The condition in the for loop
for (j=(sizeof(auxstring) - 1); j >= auxstring[0]; j--) {
^^^^^^^^^^^^^^^^^^
does not make sense because at least the array auxstring is not initialized.
Also the loop is complicated because it uses two variables as indices.
Ans the variables i, j, l should have the type size_t - the type of the returned value of the operator sizeof.
The program can look the following way
#include <stdio.h>
int main(void)
{
char string[] = { 1, 2, 3, 4 };
char auxstring[sizeof( string )];
const size_t N = sizeof( string );
for ( size_t i = 0; i < N; i++ )
{
auxstring[i] = string[N - i - 1];
}
for ( size_t i = 0; i < N; i++ )
{
printf( "%d", auxstring[i] );
}
return 0;
}
Its output is
4321
The loop condition should be j >= 0.
Right now you compare against the uninitialized value in auxstring[0], which is indeterminate (and will seem random).

Count of similar characters without repetition, in two strings

I have written a C program to find out the number of similar characters between two strings. If a character is repeated again it shouldn't count it.
Like if you give an input of
everest
every
The output should be
3
Because the four letters "ever" are identical, but the repeated "e" does not increase the count.
For the input
apothecary
panther
the output should be 6, because of "apther", not counting the second "a".
My code seems like a bulk one for a short process. My code is
#include<stdio.h>
#include <stdlib.h>
int main()
{
char firstString[100], secondString[100], similarChar[100], uniqueChar[100] = {0};
fgets(firstString, 100, stdin);
fgets(secondString, 100, stdin);
int firstStringLength = strlen(firstString) - 1, secondStringLength = strlen(secondString) - 1, counter, counter1, count = 0, uniqueElem, uniqueCtr = 0;
for(counter = 0; counter < firstStringLength; counter++) {
for(counter1 = 0; counter1 < secondStringLength; counter1++) {
if(firstString[counter] == secondString[counter1]){
similarChar[count] = firstString[counter];
count++;
break;
}
}
}
for(counter = 0; counter < strlen(similarChar); counter++) {
uniqueElem = 0;
for(counter1 = 0; counter1 < counter; counter1++) {
if(similarChar[counter] == uniqueChar[counter1]) {
uniqueElem++;
}
}
if(uniqueElem == 0) {
uniqueChar[uniqueCtr++] = similarChar[counter];
}
}
if(strlen(uniqueChar) > 1) {
printf("%d\n", strlen(uniqueChar));
printf("%s", uniqueChar);
} else {
printf("%d",0);
}
}
Can someone please provide me some suggestions or code for shortening this function?
You should have 2 Arrays to keep a count of the number of occurrences of each aplhabet.
int arrayCount1[26],arrayCount2[26];
Loop through strings and store the occurrences.
Now for counting the similar number of characters use:
for( int i = 0 ; i < 26 ; i++ ){
similarCharacters = similarCharacters + min( arrayCount1[26], arrayCount2[26] )
}
There is a simple way to go. Take an array and map the ascii code as an index to that array. Say int arr[256]={0};
Now whatever character you see in string-1 mark 1 for that. arr[string[i]]=1; Marking what characters appeared in the first string.
Now again when looping through the characters of string-2 increase the value of arr[string2[i]]++ only if arr[i] is 1. Now we are tallying that yes this characters appeared here also.
Now check how many positions of the array contains 2. That is the answer.
int arr[256]={0};
for(counter = 0; counter < firstStringLength; counter++)
arr[firstString[counter]]=1;
for(counter = 0; counter < secondStringLength; counter++)
if(arr[secondString[counter]]==1)
arr[secondString[counter]]++;
int ans = 0;
for(int i = 0; i < 256; i++)
ans += (arr[i]==2);
Here is a simplified approach to achieve your goal. You should create an array to hold the characters that has been seen for the first time.
Then, you'll have to make two loops. The first is unconditional, while the second is conditional; That condition is dependent on a variable that you have to create, which checks weather the end of one of the strings has been reached.
Ofcourse, the checking for the end of the other string should be within the first unconditional loop. You can make use of the strchr() function to count the common characters without repetition:
#include <stdio.h>
#include <string.h>
int foo(const char *s1, const char *s2);
int main(void)
{
printf("count: %d\n", foo("everest", "every"));
printf("count: %d\n", foo("apothecary", "panther"));
printf("count: %d\n", foo("abacus", "abracadabra"));
return 0;
}
int foo(const char *s1, const char *s2)
{
int condition = 0;
int count = 0;
size_t n = 0;
char buf[256] = { 0 };
// part 1
while (s2[n])
{
if (strchr(s1, s2[n]) && !strchr(buf, s2[n]))
{
buf[count++] = s2[n];
}
if (!s1[n]) {
condition = 1;
}
n++;
}
// part 2
if (!condition ) {
while (s1[n]) {
if (strchr(s2, s1[n]) && !strchr(buf, s1[n]))
{
buf[count++] = s1[n];
}
n++;
}
}
return count;
}
NOTE: You should check for buffer overflow, and you should use a dynamic approach to reallocate memory accordingly, but this is a demo.

Resources