If I had an array of characters for example:
A = [w, o, r, n, g, , w, o, r, d]
And another array for example:
B = [c, o, r, r, e, c, t, , w, o, r, d, .]
I need to compare the words in array A (which are separated by a blank space) to array B and if any of the words in the first array exist in the second array, then that word should be printed. So for example, since "word" exists in the first array and in the second array, then "word" should be printed out.
How do I go about this?
Let's see how I would do it:
You will need a function that, given an array of char, splits it in an array of words (and put them in C strings, NUL terminated please :-) ). I would put the length of this array and the array in a struct
struct WordCollection
{
size_t NumWords;
char **Words;
}
Now... How to do this function?
Let's say we "cheat" a little and decide that our arrays A and B are NUL terminated (or if they are . terminated like B, then you replace the . with a NUL). Now, this being C, you should first count the number of spaces in the string, allocate an array of char* (WordCollection::Words) big enough to contain n + 1 char* (and put this n + 1 in WordCollection::NumWords) and using strtok "tokenize" the string and put the words in the array you created.
Then you should (could) split the A and B array in words using this function. You'll obtain two WordCollection, A1 and B1.
To make it quicker, I would qsort B1.
Then for each word in A1 you bsearch it in B1 (it isn't a bad word... It means Binary Search, and it's a quick method of searching something in an ordered array)
Done :-)
I'll add that, if this is the first time you use bsearch and qsort, it's better you look at the samples you can find around. Their syntax can be "tricky".
Now... I know you won't look at the code :-) so I'll put it here
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct WordCollection
{
size_t NumWords;
char **Words;
};
void splitWord(char *str, struct WordCollection *wc)
{
char *c;
char **currentWord;
c = str;
wc->NumWords = 1;
while (*c != '.')
{
if (*c == ' ')
{
wc->NumWords++;
}
c++;
}
*c = '\0';
wc->Words = (char**)malloc(wc->NumWords * sizeof(char*));
c = strtok(str, " ");
currentWord = wc->Words;
while (c)
{
*currentWord = c;
currentWord++;
c = strtok(NULL, " ");
}
}
int myComp(const void *p1, const void *p2)
{
return strcmp(*(const char**)p1, *(const char**)p2);
}
int main(void)
{
char a[] = { 'w', 'o', 'r', 'n', 'g', ' ', 'w', 'o', 'r', 'd', '.' };
char b[] = { 'c', 'o', 'r', 'r', 'e', 'c', 't', ' ', 'w', 'o', 'r', 'd', '.' };
struct WordCollection a1, b1;
struct WordCollection *pSmaller, *pBigger;
size_t i;
splitWord(a, &a1);
splitWord(b, &b1);
if (a1.NumWords <= b1.NumWords)
{
pSmaller = &a1;
pBigger = &b1;
}
else
{
pSmaller = &b1;
pBigger = &a1;
}
qsort(pBigger->Words, pBigger->NumWords, sizeof(char*), myComp);
for (i = 0; i < pSmaller->NumWords; i++)
{
void *res = bsearch(&pSmaller->Words[i], pBigger->Words, pBigger->NumWords, sizeof(char*), myComp);
if (res)
{
printf("Found: %s", pSmaller->Words[i]);
}
}
free(a1.Words);
free(b1.Words);
return 0;
}
And on ideone
Basically you need to somehow separate the words, and then iterate through the combinations. There are a hundred ways to do this -- it simply requires programming.
You can also do it like that:
Insert all words from set A into set C with suffix 'A'. You will get =>
worngAwordA
Insert all words from set B into set C with suffix 'B'. You will get =>
correctBwordB
Run sorting algo on set C such as qsort. You will get =>
correctBwordAwordBworngA
Loop in set C until it's size-1. Compare word[i] with word[i+1] - if they match except the last letter - you found duplicate and you can print it out.
I don't know about this algorithm complexity, but it clearly should be faster than just brute-force scan of all words combinations :-)
Related
I need the length of an array. One way works perfectly, one gives the wrong answer, and one doesn't compile.
This doesn't compile:
size_t len = sizeof(array) / sizeof(array[0]);
This counts only first 4 letters:
size_t len = sizeof(array) / sizeof(char);
And len = 12 works.
I really don't understand this so some hint is greatly appreciated.
const char array[] = {'t', 'h', 'i', 's', 'i', 's', 'm', 'y', 't', 'e', 'x', 't', '\0'};
void count_chars(const char *array, unsigned int *counts)
{
size_t len = 12;
for(size_t i = 0; i < len; i++){
counts[(int)array[i]]++;
}
}
You cant determine the size of the passed array inside function. You need to pass size as an additional parameter.
const char array[] = {'t', 'h', 'i', 's', 'i', 's', 'm', 'y', 't', 'e', 'x', 't', 0};
void count_chars(const char *arr, unsigned int *counts, size_t size)
{
for(size_t i = 0; i < size; i++)
counts[(unsigned)arr[i]]++;
}
int main(void)
{
int cnt[sizeof(array[0]) * (1 << CHAR_BIT)];
count_chars(array, cnt, sizeof(array) / sizeof(array[0]));
}
You need to cast to unsigned (not int) because char values can be negative.
What you are trying to do is actually impossible in C. The general rule of thumb is to calculate the length of the array in the function where the array is declared and pass it to the function. This is due to the fact that C doesn't pass the entire array when calling a function but rather just the base address as a pointer variable. To breakdown your approaches and the reason they do/don't work are:
size_t len = sizeof(array) / sizeof(array[0]);
This the commonly accepted approach but the prerequisite is that array must be declared in the same scope not be a pointer.
size_t len = sizeof(array) / sizeof(char);
As array is pointer a type variable and therefore has the size 4(atleast on 32-bit machines) dividing by sizeof(char) is 1 resulting in the answer 4
size_t len = 12;
This works as it's hard coded.
An easy solution in your case could be use:
size_t len = strlen(array)
as mentioned assuming you can guarantee that the last element will be 0 or '\0'. In this situation you could also simply modify the looping condition to:
for(int i = 0; array[i] != 0; i++) {
...
}
Hope I could clarify your doubt
size_t len = sizeof(array) / sizeof(array[0]);
This is general approach for getting the length of an array. However, this will not work inside count_chars function because array is defined as local variable (a pointer) inside the API. And if it is the case, the result will be 13 (not 12 as you mentioned) because it count also the \0 at the end.
For string of characters, it is possible to use strlen. As in the question, you expected result = 12 so this might be your right solution. However, this will not work if there is some \0 value in the middle because it will find first string terminator (\0).
In C if you want to get length of Null Terminated Strings you have to check for NULL \0 and count characters.
Check here how strlen method works.
//Custom Strlen function.
size_t my_strlen(const char *str)
{
register const char *s;
for (s = str; *s; ++s);
return(s - str);
}
Strlen Source
To count length of Arrays (General) like Int,Float,Double you can use below method.
size_t int_arr_len = sizeof(int_arr) / sizeof(int_arr[0]);
size_t float_arr_len = sizeof(float_arr) / sizeof(float_arr[0]);
Full Source Code below
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char char_arr[] = {'t', 'h', 'i', 's', 'i', 's', 'm', 'y', 't', 'e', 'x', 't', 0}; // `\0` Null Terminated.
const int int_arr[] = {10, 20, 30, 40, 50};
const float float_arr[] = {1.5f, 2.5f, 3.5f, 4.5f, 5.5f};
//Custom Strlen function.
size_t my_strlen(const char *str)
{
register const char *s;
for (s = str; *s; ++s);
return(s - str);
}
int main()
{
//Array length for Strings(Char array. Null Terminated. `\0`)
size_t char_arr_len1 = strlen(char_arr);
size_t char_arr_len2 = my_strlen(char_arr);
//Array length for General arrays like Int,Float,Double...etc
size_t int_arr_len = sizeof(int_arr) / sizeof(int_arr[0]);
size_t float_arr_len = sizeof(float_arr) / sizeof(float_arr[0]);
//Print length of arrays.
printf("char_arr_len1: %zu\n", char_arr_len1);
printf("char_arr_len2: %zu\n", char_arr_len2);
printf("int_arr_len: %zu\n", int_arr_len);
printf("float_arr_len: %zu\n", float_arr_len);
return 0;
}
How to concatenate two characters and store the result in a variable?
For example, I have 3 characters 'a', 'b' and 'c' and I need to join them together and store them in an array and later use this array as a string:
#include <stdio.h>
#include <string.h>
char n[10];
main ()
{
// now I want insert them in an array
//ex: n = { a + b + c }
}
There are many ways, the following 2 methods have exactly the same results: (using your code as a starting point.)
#include <stdio.h>
#include <string.h>
int main(void)
{
//Given the following
char a = 'a';
char b = 'b';
char c = 'c';
// assignment by initializer list at time of creation
char n1[10] = {a,b,c};
//usage of a string function
char n2[10] = {0}; //initialize array
sprintf(n2, "%c%c%c", a, b, c);
return 0;
}
Both result in a null terminated char arrays, or C strings.
Simply:
char a = 'a', b = 'b', c = 'c';
char str[4];
str[0] = a;
str[1] = b;
str[2] = c;
str[3] = '\0';
Or, if you want str to be stored on the heap (e.g. if you plan on returning it from a function):
char *str = malloc(4);
str[0] = a;
...
Any introductory book on C should cover this.
An assignment similar to that can only be done when the char array is declared using array initialiation with a brace-enclosed list:
char a = 'a', b = 'b', c = 'c';
char n[10] = {a, b, c};
After the declaration you can't do it like this because a char array is not a modifiable lvalue:
n = {a, b, c}; //error
To insert characters in an array that has been previously initialized, you need to either insert them one by one as exemplified in another answer, or use some library function like sprintf.
sprintf(n, "%c%c%c", a, b, c);
In both of my examples the char array will be null terminated by the compiler so you can use it as a string, if you assign the characters one by one, make sure to place a null terminator at the end ('\0'), only then will you have a propper string.
I have a program to calculate the highest value of consonants in a string as followed:
int solve(const char* strin) {
char *vowels = "aeiou";
int solution = 0;
int current = 0;
char *c;
while(c = *strin++) {
current = strchr(vowels, c) ? 0 : current + c - 96;
if(current > solution) solution = current;
}
return solution;
}
I got quite confused with the command char *vowels = "aeiou"; because, as I've learned at university, the pointer only refers to the first element in an array unless there exists an increment or decrement. Is it valid to write like this? And why?
When you write
char* vowels = "aeiou";
the pointer vowels points to the first element of the "array" i.e. 'a', what you do with that pointer is up to you, if you e.g. want access the third element that vowels points to then *(vowels + 2) will give you that - the address of the same is vowels + 2
you can also declare vowels like this
char vowels[] = "aeiou"; here vowels again tells where the array starts
the prototype of strchr looks like this
char *strchr( const char *str, int ch );
When you pass in vowels you tell the function to start looking where vowels starts for the 'ch'. strchr looks until it finds the end of the string which is a \0, if it finds it returns a pointer to that location i.e. vowels + 0, +1 ,...
I'm running into an issue with a pair of strings. Toward the bottom of my first function I test the length of both strings, and even though searchingForLength should be less than half the size of searchedLength, they are the same "length". What is going on here?
Here's the code:
#include <stdio.h>
#include <stdbool.h>
bool findString(const char searched[], const char searchingFor[]) {
int i, j, k = 0, searchedLength = sizeof(searched)/sizeof(searched[0]), searchingForLength = sizeof(searchingFor)/sizeof(searchingFor[0]);
bool in = false;
for (i = 0; i < searchedLength; i++) {
for (j = 0; j < searchingForLength; j++) {
if (searched[i] == searchingFor[j]) {
k++;
if (k == searchingForLength) {
in = true;
}
}
}
}
printf("%d\n", k);
printf("%d\n",searchingForLength);
printf("%d\n",searchedLength);
if (in == true) {
printf("Yes\n");
}
else {
printf("No\n");
}
return in;
}
int main (void) {
const char searched[] = { 'I', ' ', 'l', 'i', 'k', 'e', ' ', 'p', 'i', 'e' };
const char searchingFor[] = { 'l', 'i', 'k', 'e' };
findString(searched, searchingFor);
return 0;
}
Sizeof is evaluated at compile time, and in this case it will return the size of a pointer (char[] is more or less a char*). You should use strlen instead.
Oh and as it has been mentioned, you strings are not zero-terminated, so that won't really work either. You should define your strings as
const char blah[] = "whee"
The sizeof is an operator and it gives the size of the type of it's argument, which is not the length of a string.
For arrays it gives the size of the array in bytes, to calculate the length of a string you need strlen(), but none of your arrays are strings, and hence you can't use strlen(), they are not strings in a c string sense.
A string in c, is a sequence of non-nul bytes followed by a nul byte, your arrays don't have a terminating nul, so the str* functions can't handle them properly.
A simple implementation of strlen() would be
size_t strlen(const char *string)
{
size_t length;
length = 0;
while (*string++ != '\0')
length++;
return length;
}
as you can see, if there is no '\0' or nul byte1 in the data, the function will keep iterating beyond the end of the string, what happens after that is undefined.
1They are the same and their value is 0
I have to work with a given function that is declared like this:
void someFunc (char** characters, int from, int to);
The problem is, i cant find a way to pass a matrix to it, for example:
char matrix[4][4] = { { 'a', 'e' , 'i', 'm'},
{ 'b', 'f' , 'j', 'n'},
{ 'c', 'g' , 'k', 'p'},
{ 'd', 'h' , 'l', 's'} };
someFunc(matrix, 2, 3); //doesnt work
someFunc(&matrix, 2, 3); //doesnt work
The compiler complains, but i cant change the signature of someFunc, so how i can do to pass a char matrix to the function?
AS #IgorTandetnik said
define like this
char* data[]= {matrix[0], matrix[1], matrix[2], matrix[3]};
someFunc(data, 2, 3); // works fine
array of character pointers initialized with the each row of matrix and then passed this as argument
test code:
#include<stdio.h>
void someFunc (char** characters, int from, int to);
char matrix[4][4] = { { 'a', 'e' , 'i', 'm'},
{ 'b', 'f' , 'j', 'n'},
{ 'c', 'g' , 'k', 'p'},
{ 'd', 'h' , 'l', 's'} };
main()
{
char* data[]= {matrix[0], matrix[1], matrix[2], matrix[3]};
someFunc(data, 2, 3);
}
void someFunc (char** c , int from, int to)
{
int i=0,j=0;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
printf("%c\n",c[i][j]); //printf("%c",*(c[i]+j));
}
instead of using an automatic matrix just malloc a pointer to pointer the code goes like this
main(void)
{
int i;
char **ptr = NULL;
ptr = (char**)malloc(sizeof(char) * 4);
for(i = 0 ; i < 4 ; i++)
ptr[i] = (char*)malloc(sizeof(char) * 4);
//initialize your matrix here
someFunc(ptr , 2 , 3);
}
or , if you are ready to modify the function prototype (just a tiny bit) use this one instead void sumFunc(char matrix[][4) , int from , int to) and you won't have to change any thing else
The below code will work. But you may need to access the array using one index instead of two index in the function. When you declare a double index array, the data is not store as a "pointer to pointer". So you may not pass char foo0[ ][ ] using char **foo1.
void someFunc (char* characters)
{
char c = character[0]; // c = 'a'
c = character[4] // c = 'b'
c = character[8] // c = 'c'
c = character[12] // c = 'd'
}
void main(void)
{
char matrix[4][4] = {
{ 'a', 'e' , 'i', 'm'},
{ 'b', 'f' , 'j', 'n'},
{ 'c', 'g' , 'k', 'p'},
{ 'd', 'h' , 'l', 's'} };
someFunc((char*)matrix);
}
An example of char **variable would be:
char *array[]={"this","is","char","pointer"};
Used like:
someFunc(array, 2, 3);
An example of an array of the previous would have to be something like:
char *array[][5] = {
{"this","is","char","element","one"},
{"this","is","char","element","two"},
{"this","is","char","element","three"}};
But that is not what your prototype requires. Use the previous example to see that that does for you.
[EDIT] per your question and my comment, here is how to access the content of an array. (it is random and can be printed in any format you need).
#include <windows.h>
#include <ansi_c.h>
int main(void)
{
char *array[]={"this","is","char","pointer"};
int i,j;
//print in columns
printf("Columns:\n");
for(i=0;i<7; i++)
{
for(j=0;j<4;j++)
{
if(i> strlen(array[j]))
printf(" ");
else
printf("%c", array[j][i]);
}
printf("\n");
}
//print in rows (easier)
printf("\n\nRows:\n");
for(i=0;i<4;i++)
{
printf("%s\n", array[i]);
}
getchar();
return 0;
}
I had a similar experience once and I found out that using char matrixes kinda give some issues ... this is my actual suggestion, I hope you'll understand it. (I know it's late, but maybe it will be to aid for somebody else)
void someFunc(char* matrix, int from, int to){/*function declaration*/}
int main(){
int x = 4; //first matrix's dimension
int y = 4; //second matrix's dimension
char matrix[x*y];
//printing the matrix all in a single row
for(int i=0, i<x, i++)
for(int j=0, j<y, j++)
printf("%c", matrix[i+j*x]);
//it is just way simpler, reduces a ton of complexity, and having a string is much more flexible than having a matrix, especially with chars
return 0
}